13f15e290Smatthew /*
23f15e290Smatthew  * Copyright (c) 2014 Google Inc.
33f15e290Smatthew  *
43f15e290Smatthew  * Permission to use, copy, modify, and distribute this software for any
53f15e290Smatthew  * purpose with or without fee is hereby granted, provided that the above
63f15e290Smatthew  * copyright notice and this permission notice appear in all copies.
73f15e290Smatthew  *
83f15e290Smatthew  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
93f15e290Smatthew  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
103f15e290Smatthew  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
113f15e290Smatthew  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
123f15e290Smatthew  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
133f15e290Smatthew  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
143f15e290Smatthew  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
153f15e290Smatthew  */
163f15e290Smatthew 
173f15e290Smatthew #include <sys/mman.h>
183f15e290Smatthew #include <sys/wait.h>
193f15e290Smatthew #include <assert.h>
203f15e290Smatthew #include <err.h>
21*6f639c86Sbcook #include <errno.h>
223f15e290Smatthew #include <stdlib.h>
233f15e290Smatthew #include <string.h>
243f15e290Smatthew #include <unistd.h>
253f15e290Smatthew 
263f15e290Smatthew #define CHECK(x) assert(x)
273f15e290Smatthew #define CHECK_EQ(a, b) assert((a) == (b))
283f15e290Smatthew #define CHECK_NE(a, b) assert((a) != (b))
293f15e290Smatthew #define CHECK_GE(a, b) assert((a) >= (b))
303f15e290Smatthew #define CHECK_LE(a, b) assert((a) <= (b))
313f15e290Smatthew 
323f15e290Smatthew /* Test arc4random_buf(3) instead of arc4random(3). */
333f15e290Smatthew static int flagbuf;
343f15e290Smatthew 
353f15e290Smatthew /* Initialize arc4random(3) before forking. */
363f15e290Smatthew static int flagprefork;
373f15e290Smatthew 
383f15e290Smatthew enum {
393f15e290Smatthew 	N = 4096
403f15e290Smatthew };
413f15e290Smatthew 
423f15e290Smatthew typedef struct {
433f15e290Smatthew 	uint32_t x[N];
443f15e290Smatthew } Buf;
453f15e290Smatthew 
463f15e290Smatthew static int
473f15e290Smatthew isfullbuf(const Buf *buf)
483f15e290Smatthew {
493f15e290Smatthew 	size_t i;
503f15e290Smatthew 	for (i = 0; i < N; i++)
513f15e290Smatthew 		if (buf->x[i])
523f15e290Smatthew 			return (1);
533f15e290Smatthew 	return (0);
543f15e290Smatthew }
553f15e290Smatthew 
563f15e290Smatthew static void
573f15e290Smatthew fillbuf(Buf *buf)
583f15e290Smatthew {
593f15e290Smatthew 	if (flagbuf) {
603f15e290Smatthew 		arc4random_buf(buf->x, sizeof(buf->x));
613f15e290Smatthew 	} else {
623f15e290Smatthew 		size_t i;
633f15e290Smatthew 		for (i = 0; i < N; i++)
643f15e290Smatthew 			buf->x[i] = arc4random();
653f15e290Smatthew 	}
663f15e290Smatthew }
673f15e290Smatthew 
683f15e290Smatthew static void
693f15e290Smatthew usage()
703f15e290Smatthew {
713f15e290Smatthew 	extern const char *__progname;
723f15e290Smatthew 	errx(1, "usage: %s [-bp]", __progname);
733f15e290Smatthew }
743f15e290Smatthew 
75*6f639c86Sbcook static pid_t
76*6f639c86Sbcook _waitpid(pid_t pid, int *stat_loc, int options)
77*6f639c86Sbcook {
78*6f639c86Sbcook 	pid_t ret;
79*6f639c86Sbcook 	do {
80*6f639c86Sbcook 		ret = waitpid(pid, stat_loc, options);
81*6f639c86Sbcook 	} while (ret == -1 && errno == EINTR);
82*6f639c86Sbcook 	return ret;
83*6f639c86Sbcook }
84*6f639c86Sbcook 
853f15e290Smatthew int
863f15e290Smatthew main(int argc, char *argv[])
873f15e290Smatthew {
883f15e290Smatthew 	int opt, status;
893f15e290Smatthew 	Buf *bufparent, *bufchildone, *bufchildtwo;
903f15e290Smatthew 	pid_t pidone, pidtwo;
913f15e290Smatthew 	size_t i, countone = 0, counttwo = 0, countkids = 0;
923f15e290Smatthew 
933f15e290Smatthew 	while ((opt = getopt(argc, argv, "bp")) != -1) {
943f15e290Smatthew 		switch (opt) {
953f15e290Smatthew 		case 'b':
963f15e290Smatthew 			flagbuf = 1;
973f15e290Smatthew 			break;
983f15e290Smatthew 		case 'p':
993f15e290Smatthew 			flagprefork = 1;
1003f15e290Smatthew 			break;
1013f15e290Smatthew 		default:
1023f15e290Smatthew 			usage();
1033f15e290Smatthew 		}
1043f15e290Smatthew 	}
1053f15e290Smatthew 
1063f15e290Smatthew 	if (flagprefork)
1073f15e290Smatthew 		arc4random();
1083f15e290Smatthew 
1093f15e290Smatthew 	bufparent = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
1103f15e290Smatthew 	    MAP_ANON|MAP_PRIVATE, -1, 0);
1113f15e290Smatthew 	CHECK_NE(MAP_FAILED, bufparent);
1123f15e290Smatthew 
1133f15e290Smatthew 	bufchildone = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
1143f15e290Smatthew 	    MAP_ANON|MAP_SHARED, -1, 0);
1153f15e290Smatthew 	CHECK_NE(MAP_FAILED, bufchildone);
1163f15e290Smatthew 
1173f15e290Smatthew 	bufchildtwo = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
1183f15e290Smatthew 	    MAP_ANON|MAP_SHARED, -1, 0);
1193f15e290Smatthew 	CHECK_NE(MAP_FAILED, bufchildtwo);
1203f15e290Smatthew 
1213f15e290Smatthew 	pidone = fork();
1223f15e290Smatthew 	CHECK_GE(pidone, 0);
1233f15e290Smatthew 	if (pidone == 0) {
1243f15e290Smatthew 		fillbuf(bufchildone);
1253f15e290Smatthew 		_exit(0);
1263f15e290Smatthew 	}
1273f15e290Smatthew 
1283f15e290Smatthew 	pidtwo = fork();
1293f15e290Smatthew 	CHECK_GE(pidtwo, 0);
1303f15e290Smatthew 	if (pidtwo == 0) {
1313f15e290Smatthew 		fillbuf(bufchildtwo);
1323f15e290Smatthew 		_exit(0);
1333f15e290Smatthew 	}
1343f15e290Smatthew 
1353f15e290Smatthew 	fillbuf(bufparent);
1363f15e290Smatthew 
137*6f639c86Sbcook 	CHECK_EQ(pidone, _waitpid(pidone, &status, 0));
1383f15e290Smatthew 	CHECK(WIFEXITED(status));
1393f15e290Smatthew 	CHECK_EQ(0, WEXITSTATUS(status));
1403f15e290Smatthew 
141*6f639c86Sbcook 	CHECK_EQ(pidtwo, _waitpid(pidtwo, &status, 0));
1423f15e290Smatthew 	CHECK(WIFEXITED(status));
1433f15e290Smatthew 	CHECK_EQ(0, WEXITSTATUS(status));
1443f15e290Smatthew 
1453f15e290Smatthew 	CHECK(isfullbuf(bufchildone));
1463f15e290Smatthew 	CHECK(isfullbuf(bufchildtwo));
1473f15e290Smatthew 
1483f15e290Smatthew 	for (i = 0; i < N; i++) {
1493f15e290Smatthew 		countone += bufparent->x[i] == bufchildone->x[i];
1503f15e290Smatthew 		counttwo += bufparent->x[i] == bufchildtwo->x[i];
1513f15e290Smatthew 		countkids += bufchildone->x[i] == bufchildtwo->x[i];
1523f15e290Smatthew 	}
1533f15e290Smatthew 
1543f15e290Smatthew 	/*
1553f15e290Smatthew 	 * These checks are inherently probabilistic and theoretically risk
1563f15e290Smatthew 	 * flaking, but there's less than a 1 in 2^40 chance of more than
1573f15e290Smatthew 	 * one pairwise match between two vectors of 4096 32-bit integers.
1583f15e290Smatthew 	 */
1593f15e290Smatthew 	CHECK_LE(countone, 1);
1603f15e290Smatthew 	CHECK_LE(counttwo, 1);
1613f15e290Smatthew 	CHECK_LE(countkids, 1);
1623f15e290Smatthew 
1633f15e290Smatthew 	return (0);
1643f15e290Smatthew }
165