1 /*
2  * Copyright (c) 2014 Google Inc.
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <sys/mman.h>
18 #include <sys/wait.h>
19 #include <assert.h>
20 #include <err.h>
21 #include <errno.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <stdint.h>
27 
28 #define CHECK(x) assert(x)
29 #define CHECK_EQ(a, b) assert((a) == (b))
30 #define CHECK_NE(a, b) assert((a) != (b))
31 #define CHECK_GE(a, b) assert((a) >= (b))
32 #define CHECK_LE(a, b) assert((a) <= (b))
33 
34 /* Test arc4random_buf(3) instead of arc4random(3). */
35 static int flagbuf;
36 
37 /* Initialize arc4random(3) before forking. */
38 static int flagprefork;
39 
40 enum {
41 	N = 4096
42 };
43 
44 typedef struct {
45 	uint32_t x[N];
46 } Buf;
47 
48 static int
isfullbuf(const Buf * buf)49 isfullbuf(const Buf *buf)
50 {
51 	size_t i;
52 	for (i = 0; i < N; i++)
53 		if (buf->x[i])
54 			return (1);
55 	return (0);
56 }
57 
58 static void
fillbuf(Buf * buf)59 fillbuf(Buf *buf)
60 {
61 	if (flagbuf) {
62 		arc4random_buf(buf->x, sizeof(buf->x));
63 	} else {
64 		size_t i;
65 		for (i = 0; i < N; i++)
66 			buf->x[i] = arc4random();
67 	}
68 }
69 
70 static void
usage()71 usage()
72 {
73 	errx(1, "usage: arc4random-fork [-bp]");
74 }
75 
76 static pid_t
safewaitpid(pid_t pid,int * status,int options)77 safewaitpid(pid_t pid, int *status, int options)
78 {
79 	pid_t ret;
80 	do {
81 		ret = waitpid(pid, status, options);
82 	} while (ret == -1 && errno == EINTR);
83 	return (ret);
84 }
85 
86 int
main(int argc,char * argv[])87 main(int argc, char *argv[])
88 {
89 	int opt, status;
90 	Buf *bufparent, *bufchildone, *bufchildtwo;
91 	pid_t pidone, pidtwo;
92 	size_t i, countone = 0, counttwo = 0, countkids = 0;
93 
94 	/* Ensure SIGCHLD isn't set to SIG_IGN. */
95 	const struct sigaction sa = {
96 		.sa_handler = SIG_DFL,
97 	};
98 	CHECK_EQ(0, sigaction(SIGCHLD, &sa, NULL));
99 
100 	while ((opt = getopt(argc, argv, "bp")) != -1) {
101 		switch (opt) {
102 		case 'b':
103 			flagbuf = 1;
104 			break;
105 		case 'p':
106 			flagprefork = 1;
107 			break;
108 		default:
109 			usage();
110 		}
111 	}
112 
113 	if (flagprefork)
114 		arc4random();
115 
116 	bufparent = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
117 	    MAP_ANON|MAP_PRIVATE, -1, 0);
118 	CHECK_NE(MAP_FAILED, bufparent);
119 
120 	bufchildone = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
121 	    MAP_ANON|MAP_SHARED, -1, 0);
122 	CHECK_NE(MAP_FAILED, bufchildone);
123 
124 	bufchildtwo = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
125 	    MAP_ANON|MAP_SHARED, -1, 0);
126 	CHECK_NE(MAP_FAILED, bufchildtwo);
127 
128 	pidone = fork();
129 	CHECK_GE(pidone, 0);
130 	if (pidone == 0) {
131 		fillbuf(bufchildone);
132 		_exit(0);
133 	}
134 
135 	pidtwo = fork();
136 	CHECK_GE(pidtwo, 0);
137 	if (pidtwo == 0) {
138 		fillbuf(bufchildtwo);
139 		_exit(0);
140 	}
141 
142 	fillbuf(bufparent);
143 
144 	CHECK_EQ(pidone, safewaitpid(pidone, &status, 0));
145 	CHECK(WIFEXITED(status));
146 	CHECK_EQ(0, WEXITSTATUS(status));
147 
148 	CHECK_EQ(pidtwo, safewaitpid(pidtwo, &status, 0));
149 	CHECK(WIFEXITED(status));
150 	CHECK_EQ(0, WEXITSTATUS(status));
151 
152 	CHECK(isfullbuf(bufchildone));
153 	CHECK(isfullbuf(bufchildtwo));
154 
155 	for (i = 0; i < N; i++) {
156 		countone += bufparent->x[i] == bufchildone->x[i];
157 		counttwo += bufparent->x[i] == bufchildtwo->x[i];
158 		countkids += bufchildone->x[i] == bufchildtwo->x[i];
159 	}
160 
161 	/*
162 	 * These checks are inherently probabilistic and theoretically risk
163 	 * flaking, but there's less than a 1 in 2^40 chance of more than
164 	 * one pairwise match between two vectors of 4096 32-bit integers.
165 	 */
166 	CHECK_LE(countone, 1);
167 	CHECK_LE(counttwo, 1);
168 	CHECK_LE(countkids, 1);
169 
170 	return (0);
171 }
172