aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBrent Cook <bcook@openbsd.org>2014-07-15 16:43:00 -0500
committerBrent Cook <bcook@openbsd.org>2014-07-15 16:43:00 -0500
commit477f1f018792ddb15a34926910d2f70bb2590cbd (patch)
tree8776b44b2f9bfa8b655be0ed1b550993d1a750e4 /tests
parentc41fb098b98c1c792a9b86a22f1ba7a51adcc144 (diff)
downloadportable-477f1f018792ddb15a34926910d2f70bb2590cbd.tar.gz
portable-477f1f018792ddb15a34926910d2f70bb2590cbd.tar.bz2
portable-477f1f018792ddb15a34926910d2f70bb2590cbd.zip
added fork_rand test to check for PID wraparound
ok beck@
Diffstat (limited to 'tests')
-rw-r--r--tests/fork_rand.c81
-rwxr-xr-xtests/fork_rand.sh10
2 files changed, 91 insertions, 0 deletions
diff --git a/tests/fork_rand.c b/tests/fork_rand.c
new file mode 100644
index 0000000..75f2cc2
--- /dev/null
+++ b/tests/fork_rand.c
@@ -0,0 +1,81 @@
1/*
2 * Checks if LibreSSL's PRNG is fork-safe on Linux.
3 * From https://www.agwa.name/blog/post/libressls_prng_is_unsafe_on_linux
4 */
5
6#include <openssl/rand.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <sys/wait.h>
11
12static void random_bytes (unsigned char* p, size_t len)
13{
14 if (RAND_bytes(p, len) != 1) {
15 fprintf(stderr, "RAND_bytes failed\n");
16 abort();
17 }
18}
19
20static void random_stir (void)
21{
22 if (RAND_poll() != 1) {
23 fprintf(stderr, "RAND_poll failed\n");
24 abort();
25 }
26}
27
28static void print_buffer (unsigned char* p, size_t len)
29{
30 while (len--) {
31 printf("%02x", (unsigned int)*p++);
32 }
33}
34
35int main ()
36{
37 char c = 0;
38 int pipefd[2];
39 pipe(pipefd);
40 setbuf(stdout, NULL);
41
42 if (fork() == 0) {
43 unsigned char buffer[32];
44 pid_t grandparent_pid = getpid();
45
46 random_bytes(buffer, sizeof(buffer));
47
48 if (fork() == 0) {
49 random_stir();
50 setsid();
51 while (1) {
52 pid_t grandchild_pid = fork();
53 if (grandchild_pid == 0) {
54 random_stir();
55 if (getpid() == grandparent_pid) {
56 random_bytes(buffer, sizeof(buffer));
57 print_buffer(buffer, sizeof(buffer));
58 printf("\n");
59 }
60 _exit(0);
61 }
62 wait(NULL);
63 if (grandchild_pid == grandparent_pid) {
64 break;
65 }
66 }
67 write(pipefd[1], &c, 1);
68 _exit(0);
69 }
70
71 random_bytes(buffer, sizeof(buffer));
72 print_buffer(buffer, sizeof(buffer));
73 printf(" ");
74 _exit(0);
75 }
76 wait(NULL);
77 close(pipefd[1]);
78 read(pipefd[0], &c, 1);
79 return 0;
80}
81
diff --git a/tests/fork_rand.sh b/tests/fork_rand.sh
new file mode 100755
index 0000000..333516e
--- /dev/null
+++ b/tests/fork_rand.sh
@@ -0,0 +1,10 @@
1#!/usr/bin/env bash
2./fork_rand > fork_rand.txt
3while read -r a b;
4do
5 if [ "$a" = "$b" ]; then
6 echo "FAIL: $a = $b"
7 else
8 echo "PASS: $a != $b"
9 fi
10done < fork_rand.txt