summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormatthew <>2014-06-18 08:24:00 +0000
committermatthew <>2014-06-18 08:24:00 +0000
commit067b361c7dbce14db401c57d13ca4e1146dedc3c (patch)
tree2ebd193036aaa17c6541fe588d07d51ab0565947 /src
parent55ad4aef932036908afcad6f20ae13f48e12db53 (diff)
downloadopenbsd-067b361c7dbce14db401c57d13ca4e1146dedc3c.tar.gz
openbsd-067b361c7dbce14db401c57d13ca4e1146dedc3c.tar.bz2
openbsd-067b361c7dbce14db401c57d13ca4e1146dedc3c.zip
Add regress tests to make sure arc4random(3) is reinitialized
correctly in fork children.
Diffstat (limited to 'src')
-rw-r--r--src/regress/lib/libc/Makefile5
-rw-r--r--src/regress/lib/libc/arc4random-fork/Makefile25
-rw-r--r--src/regress/lib/libc/arc4random-fork/arc4random-fork.c153
3 files changed, 181 insertions, 2 deletions
diff --git a/src/regress/lib/libc/Makefile b/src/regress/lib/libc/Makefile
index e7a96f1ece..06c09d35cd 100644
--- a/src/regress/lib/libc/Makefile
+++ b/src/regress/lib/libc/Makefile
@@ -1,6 +1,7 @@
1# $OpenBSD: Makefile,v 1.41 2014/06/13 01:55:02 matthew Exp $ 1# $OpenBSD: Makefile,v 1.42 2014/06/18 08:24:00 matthew Exp $
2 2
3SUBDIR+= _setjmp alloca atexit basename cephes cxa-atexit db dirname env 3SUBDIR+= _setjmp alloca arc4random-fork
4SUBDIR+= atexit basename cephes cxa-atexit db dirname env
4SUBDIR+= explicit_bzero fmemopen fnmatch fpclassify getcap getopt_long glob 5SUBDIR+= explicit_bzero fmemopen fnmatch fpclassify getcap getopt_long glob
5SUBDIR+= hsearch longjmp locale malloc mkstemp modf netdb open_memstream 6SUBDIR+= hsearch longjmp locale malloc mkstemp modf netdb open_memstream
6SUBDIR+= orientation popen printf 7SUBDIR+= orientation popen printf
diff --git a/src/regress/lib/libc/arc4random-fork/Makefile b/src/regress/lib/libc/arc4random-fork/Makefile
new file mode 100644
index 0000000000..05762e33ff
--- /dev/null
+++ b/src/regress/lib/libc/arc4random-fork/Makefile
@@ -0,0 +1,25 @@
1# $OpenBSD: Makefile,v 1.1 2014/06/18 08:24:00 matthew Exp $
2
3PROG= arc4random-fork
4
5REGRESS_TARGETS= \
6 run \
7 run-buf \
8 run-prefork \
9 run-buf-prefork
10
11run: ${PROG}
12 ./${PROG}
13
14run-buf: ${PROG}
15 ./${PROG} -b
16
17run-prefork: ${PROG}
18 ./${PROG} -p
19
20run-buf-prefork: ${PROG}
21 ./${PROG} -bp
22
23.PHONY: ${REGRESS_TARGETS}
24
25.include <bsd.regress.mk>
diff --git a/src/regress/lib/libc/arc4random-fork/arc4random-fork.c b/src/regress/lib/libc/arc4random-fork/arc4random-fork.c
new file mode 100644
index 0000000000..35a9ea6a98
--- /dev/null
+++ b/src/regress/lib/libc/arc4random-fork/arc4random-fork.c
@@ -0,0 +1,153 @@
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 <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24
25#define CHECK(x) assert(x)
26#define CHECK_EQ(a, b) assert((a) == (b))
27#define CHECK_NE(a, b) assert((a) != (b))
28#define CHECK_GE(a, b) assert((a) >= (b))
29#define CHECK_LE(a, b) assert((a) <= (b))
30
31/* Test arc4random_buf(3) instead of arc4random(3). */
32static int flagbuf;
33
34/* Initialize arc4random(3) before forking. */
35static int flagprefork;
36
37enum {
38 N = 4096
39};
40
41typedef struct {
42 uint32_t x[N];
43} Buf;
44
45static int
46isfullbuf(const Buf *buf)
47{
48 size_t i;
49 for (i = 0; i < N; i++)
50 if (buf->x[i])
51 return (1);
52 return (0);
53}
54
55static void
56fillbuf(Buf *buf)
57{
58 if (flagbuf) {
59 arc4random_buf(buf->x, sizeof(buf->x));
60 } else {
61 size_t i;
62 for (i = 0; i < N; i++)
63 buf->x[i] = arc4random();
64 }
65}
66
67static void
68usage()
69{
70 extern const char *__progname;
71 errx(1, "usage: %s [-bp]", __progname);
72}
73
74int
75main(int argc, char *argv[])
76{
77 int opt, status;
78 Buf *bufparent, *bufchildone, *bufchildtwo;
79 pid_t pidone, pidtwo;
80 size_t i, countone = 0, counttwo = 0, countkids = 0;
81
82 while ((opt = getopt(argc, argv, "bp")) != -1) {
83 switch (opt) {
84 case 'b':
85 flagbuf = 1;
86 break;
87 case 'p':
88 flagprefork = 1;
89 break;
90 default:
91 usage();
92 }
93 }
94
95 if (flagprefork)
96 arc4random();
97
98 bufparent = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
99 MAP_ANON|MAP_PRIVATE, -1, 0);
100 CHECK_NE(MAP_FAILED, bufparent);
101
102 bufchildone = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
103 MAP_ANON|MAP_SHARED, -1, 0);
104 CHECK_NE(MAP_FAILED, bufchildone);
105
106 bufchildtwo = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
107 MAP_ANON|MAP_SHARED, -1, 0);
108 CHECK_NE(MAP_FAILED, bufchildtwo);
109
110 pidone = fork();
111 CHECK_GE(pidone, 0);
112 if (pidone == 0) {
113 fillbuf(bufchildone);
114 _exit(0);
115 }
116
117 pidtwo = fork();
118 CHECK_GE(pidtwo, 0);
119 if (pidtwo == 0) {
120 fillbuf(bufchildtwo);
121 _exit(0);
122 }
123
124 fillbuf(bufparent);
125
126 CHECK_EQ(pidone, waitpid(pidone, &status, 0));
127 CHECK(WIFEXITED(status));
128 CHECK_EQ(0, WEXITSTATUS(status));
129
130 CHECK_EQ(pidtwo, waitpid(pidtwo, &status, 0));
131 CHECK(WIFEXITED(status));
132 CHECK_EQ(0, WEXITSTATUS(status));
133
134 CHECK(isfullbuf(bufchildone));
135 CHECK(isfullbuf(bufchildtwo));
136
137 for (i = 0; i < N; i++) {
138 countone += bufparent->x[i] == bufchildone->x[i];
139 counttwo += bufparent->x[i] == bufchildtwo->x[i];
140 countkids += bufchildone->x[i] == bufchildtwo->x[i];
141 }
142
143 /*
144 * These checks are inherently probabilistic and theoretically risk
145 * flaking, but there's less than a 1 in 2^40 chance of more than
146 * one pairwise match between two vectors of 4096 32-bit integers.
147 */
148 CHECK_LE(countone, 1);
149 CHECK_LE(counttwo, 1);
150 CHECK_LE(countkids, 1);
151
152 return (0);
153}