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