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 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 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 71 usage() 72 { 73 errx(1, "usage: arc4random-fork [-bp]"); 74 } 75 76 static pid_t 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 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