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