1 /*
2 * Checks if LibreSSL's PRNG is fork-safe.
3 * From https://www.agwa.name/blog/post/libressls_prng_is_unsafe_on_linux
4 * This code is in the public domain.
5 *
6 * Original source: https://gist.github.com/AGWA/eb84e55ca25a7da1deb0
7 */
8
9 #undef LIBRESSL_INTERNAL
10 #include <openssl/rand.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/wait.h>
15
random_bytes(unsigned char * p,size_t len)16 static void random_bytes (unsigned char* p, size_t len)
17 {
18 if (RAND_bytes(p, len) != 1) {
19 fprintf(stderr, "RAND_bytes failed\n");
20 abort();
21 }
22 }
23
random_stir(void)24 static void random_stir (void)
25 {
26 if (RAND_poll() != 1) {
27 fprintf(stderr, "RAND_poll failed\n");
28 abort();
29 }
30 }
31
print_buffer(unsigned char * p,size_t len)32 static void print_buffer (unsigned char* p, size_t len)
33 {
34 while (len--) {
35 printf("%02x", (unsigned int)*p++);
36 }
37 }
38
main()39 int main ()
40 {
41 char c = 0;
42 int pipefd[2];
43 pipe(pipefd);
44 setbuf(stdout, NULL);
45
46 if (fork() == 0) {
47 unsigned char buffer[32];
48 pid_t grandparent_pid = getpid();
49
50 random_bytes(buffer, sizeof(buffer));
51
52 if (fork() == 0) {
53 random_stir();
54 setsid();
55 while (1) {
56 pid_t grandchild_pid = fork();
57 if (grandchild_pid == 0) {
58 random_stir();
59 if (getpid() == grandparent_pid) {
60 random_bytes(buffer, sizeof(buffer));
61 print_buffer(buffer, sizeof(buffer));
62 printf("\n");
63 }
64 _exit(0);
65 }
66 wait(NULL);
67 if (grandchild_pid == grandparent_pid) {
68 break;
69 }
70 }
71 write(pipefd[1], &c, 1);
72 _exit(0);
73 }
74
75 random_bytes(buffer, sizeof(buffer));
76 print_buffer(buffer, sizeof(buffer));
77 printf(" ");
78 _exit(0);
79 }
80 wait(NULL);
81 close(pipefd[1]);
82 read(pipefd[0], &c, 1);
83 return 0;
84 }
85
86