1205be291c58d45a4844c17b346d16637152037e0Garrett Cooper/* 2205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * a race in pid generation that causes pids to be reused immediately 3205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 4205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * From the mainline commit 5fdee8c4a5e1800489ce61963208f8cc55e42ea1: 58b718291663a9d3424967c0767886e5699319959Wanlong Gao * 6205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * A program that repeatedly forks and waits is susceptible to having 7205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * the same pid repeated, especially when it competes with another 8205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * instance of the same program. This is really bad for bash 9205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * implementation. Furthermore, many shell scripts assume that pid 10205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * numbers will not be used for some length of time. 118b718291663a9d3424967c0767886e5699319959Wanlong Gao * 12205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * Race Description: 13205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 14205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * A B 15205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 16205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * // pid == offset == n // pid == offset == n + 1 17205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * test_and_set_bit(offset, map->page) 18205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * test_and_set_bit(offset, map->page); 19205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * pid_ns->last_pid = pid; 20205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * pid_ns->last_pid = pid; 21205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * // pid == n + 1 is freed (wait()) 22205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 23205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * // Next fork()... 24205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * last = pid_ns->last_pid; // == n 25205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * pid = last + 1; 26205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 27205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * Copyright (C) 2010 Red Hat, Inc. 28205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * This program is free software; you can redistribute it and/or 29205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * modify it under the terms of version 2 of the GNU General Public 30205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * License as published by the Free Software Foundation. 31205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 32205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * This program is distributed in the hope that it would be useful, 33205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * but WITHOUT ANY WARRANTY; without even the implied warranty of 34205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 35205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 36205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * Further, this software is distributed without any warranty that it 37205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * is free of the rightful claim of any third person regarding 38205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * infringement or the like. Any license provided herein, whether 39205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * implied or otherwise, applies only to this software file. Patent 40205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * licenses, if any, provided herein do not apply to combinations of 41205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * this program with other software, or any other product whatsoever. 42205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 43205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * You should have received a copy of the GNU General Public License 44205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * along with this program; if not, write the Free Software 45205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 46205be291c58d45a4844c17b346d16637152037e0Garrett Cooper * 02110-1301, USA. 47205be291c58d45a4844c17b346d16637152037e0Garrett Cooper */ 488b718291663a9d3424967c0767886e5699319959Wanlong Gao 49205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <sys/types.h> 50205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <sys/stat.h> 51205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <sys/wait.h> 52205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <fcntl.h> 53205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <errno.h> 54205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <unistd.h> 55205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <stdio.h> 56205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include <stdlib.h> 57205be291c58d45a4844c17b346d16637152037e0Garrett Cooper#include "test.h" 58205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 59205be291c58d45a4844c17b346d16637152037e0Garrett Cooperchar *TCID = "fork13"; 60205be291c58d45a4844c17b346d16637152037e0Garrett Cooperint TST_TOTAL = 1; 61205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 622664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubisstatic unsigned long pid_max; 63205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 642664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis#define PID_MAX_PATH "/proc/sys/kernel/pid_max" 652664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis#define PID_MAX 32768 662664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis#define RETURN 256 67205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 68205be291c58d45a4844c17b346d16637152037e0Garrett Cooperstatic void setup(void); 69205be291c58d45a4844c17b346d16637152037e0Garrett Cooperstatic int pid_distance(pid_t first, pid_t second); 70205be291c58d45a4844c17b346d16637152037e0Garrett Cooperstatic void cleanup(void); 71205be291c58d45a4844c17b346d16637152037e0Garrett Cooperstatic void check(void); 72205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 738b718291663a9d3424967c0767886e5699319959Wanlong Gaoint main(int argc, char *argv[]) 74205be291c58d45a4844c17b346d16637152037e0Garrett Cooper{ 75d6d11d08678aac1ed2c370ea8e42e5f45aea07beCyril Hrubis tst_parse_opts(argc, argv, NULL, NULL); 76205be291c58d45a4844c17b346d16637152037e0Garrett Cooper setup(); 77205be291c58d45a4844c17b346d16637152037e0Garrett Cooper check(); 78205be291c58d45a4844c17b346d16637152037e0Garrett Cooper cleanup(); 79205be291c58d45a4844c17b346d16637152037e0Garrett Cooper tst_exit(); 80205be291c58d45a4844c17b346d16637152037e0Garrett Cooper} 81205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 828b718291663a9d3424967c0767886e5699319959Wanlong Gaostatic void check(void) 83205be291c58d45a4844c17b346d16637152037e0Garrett Cooper{ 843f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper long lc; 85205be291c58d45a4844c17b346d16637152037e0Garrett Cooper pid_t last_pid = 0; 86205be291c58d45a4844c17b346d16637152037e0Garrett Cooper pid_t pid; 87205be291c58d45a4844c17b346d16637152037e0Garrett Cooper int child_exit_code, distance, reaped, status; 88205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 89205be291c58d45a4844c17b346d16637152037e0Garrett Cooper for (lc = 0; TEST_LOOPING(lc); lc++) { 90d59a659cd639ca2780b00049d102acd2a783d585Caspar Zhang tst_count = 0; 91205be291c58d45a4844c17b346d16637152037e0Garrett Cooper child_exit_code = lc % RETURN; 92205be291c58d45a4844c17b346d16637152037e0Garrett Cooper switch (pid = fork()) { 93205be291c58d45a4844c17b346d16637152037e0Garrett Cooper case -1: 948b718291663a9d3424967c0767886e5699319959Wanlong Gao tst_brkm(TBROK | TERRNO, cleanup, "fork"); 95205be291c58d45a4844c17b346d16637152037e0Garrett Cooper case 0: 96205be291c58d45a4844c17b346d16637152037e0Garrett Cooper exit(child_exit_code); 97205be291c58d45a4844c17b346d16637152037e0Garrett Cooper default: 98205be291c58d45a4844c17b346d16637152037e0Garrett Cooper if (lc > 0) { 99205be291c58d45a4844c17b346d16637152037e0Garrett Cooper distance = pid_distance(last_pid, pid); 1003f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper if (distance == 0) { 101205be291c58d45a4844c17b346d16637152037e0Garrett Cooper tst_resm(TFAIL, 1028b718291663a9d3424967c0767886e5699319959Wanlong Gao "Unexpected pid sequence: " 1038b718291663a9d3424967c0767886e5699319959Wanlong Gao "previous fork: pid=%d, " 1048b718291663a9d3424967c0767886e5699319959Wanlong Gao "current fork: pid=%d for " 1058b718291663a9d3424967c0767886e5699319959Wanlong Gao "iteration=%ld.", last_pid, 1068b718291663a9d3424967c0767886e5699319959Wanlong Gao pid, lc); 1073f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper return; 1083f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper } 109205be291c58d45a4844c17b346d16637152037e0Garrett Cooper } 110205be291c58d45a4844c17b346d16637152037e0Garrett Cooper last_pid = pid; 111205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 1124cb537aec9dc5683d826dfa9ab953ea9586f10c8tangchen reaped = waitpid(pid, &status, 0); 1133f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper if (reaped != pid) { 114205be291c58d45a4844c17b346d16637152037e0Garrett Cooper tst_resm(TFAIL, 1158b718291663a9d3424967c0767886e5699319959Wanlong Gao "Wait return value: expected pid=%d, " 1168b718291663a9d3424967c0767886e5699319959Wanlong Gao "got %d, iteration %ld.", pid, reaped, 1178b718291663a9d3424967c0767886e5699319959Wanlong Gao lc); 1183f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper return; 1198b718291663a9d3424967c0767886e5699319959Wanlong Gao } else if (WEXITSTATUS(status) != child_exit_code) { 120205be291c58d45a4844c17b346d16637152037e0Garrett Cooper tst_resm(TFAIL, "Unexpected exit status %x, " 1218b718291663a9d3424967c0767886e5699319959Wanlong Gao "iteration %ld.", WEXITSTATUS(status), 1228b718291663a9d3424967c0767886e5699319959Wanlong Gao lc); 1233f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper return; 1243f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper } 125205be291c58d45a4844c17b346d16637152037e0Garrett Cooper } 126205be291c58d45a4844c17b346d16637152037e0Garrett Cooper } 1273f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper tst_resm(TPASS, "%ld pids forked, all passed", lc); 128205be291c58d45a4844c17b346d16637152037e0Garrett Cooper} 129205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 1308b718291663a9d3424967c0767886e5699319959Wanlong Gaostatic void setup(void) 131205be291c58d45a4844c17b346d16637152037e0Garrett Cooper{ 132d1e794d62b1bf619df8390535e4c2a58899b1145Cyril Hrubis tst_require_root(); 133205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 134205be291c58d45a4844c17b346d16637152037e0Garrett Cooper tst_sig(FORK, DEF_HANDLER, cleanup); 135205be291c58d45a4844c17b346d16637152037e0Garrett Cooper TEST_PAUSE; 1362664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis 137205be291c58d45a4844c17b346d16637152037e0Garrett Cooper /* Backup pid_max value. */ 1382664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis SAFE_FILE_SCANF(NULL, PID_MAX_PATH, "%lu", &pid_max); 139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 1402664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis SAFE_FILE_PRINTF(NULL, PID_MAX_PATH, "%d", PID_MAX); 141205be291c58d45a4844c17b346d16637152037e0Garrett Cooper} 142205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 1438b718291663a9d3424967c0767886e5699319959Wanlong Gaostatic void cleanup(void) 144205be291c58d45a4844c17b346d16637152037e0Garrett Cooper{ 1452664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis /* Restore pid_max value. */ 1468bfd7c194d56e2f2ff8bfc14b2824964d3a0e3efLi Wang FILE_PRINTF(PID_MAX_PATH, "%lu", pid_max); 147205be291c58d45a4844c17b346d16637152037e0Garrett Cooper} 148205be291c58d45a4844c17b346d16637152037e0Garrett Cooper 1493f0688d76b18c31fa3d1f36d096b9d1d19ab88ccGarrett Cooper/* The distance mod PIDMAX between two pids, where the first pid is 150205be291c58d45a4844c17b346d16637152037e0Garrett Cooper expected to be smaller than the second. */ 1518b718291663a9d3424967c0767886e5699319959Wanlong Gaostatic int pid_distance(pid_t first, pid_t second) 152205be291c58d45a4844c17b346d16637152037e0Garrett Cooper{ 1532664913bb05558b8bf9ee403311370ed9f4a984fCyril Hrubis return (second + PID_MAX - first) % PID_MAX; 154205be291c58d45a4844c17b346d16637152037e0Garrett Cooper} 155