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