1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (c) 2015, Joyent, Inc. 14 */ 15 16 /* 17 * Tests to make sure that a parent and child do not get the same arc4random 18 * state across a fork from a signal handler. This source file is used to make 19 * two tests. One which initializes the data in advance, one of which does not. 20 */ 21 22 #include <stdlib.h> 23 #include <sys/mman.h> 24 #include <assert.h> 25 #include <errno.h> 26 #include <sys/types.h> 27 #include <unistd.h> 28 #include <sys/wait.h> 29 #include <signal.h> 30 #include <strings.h> 31 32 typedef struct arc4_fork { 33 uint32_t af_parent; 34 uint32_t af_child; 35 uint8_t af_pbuf[4096]; 36 uint8_t af_cbuf[4096]; 37 } arc4_fork_t; 38 39 arc4_fork_t *fork_data; 40 static pid_t pid; 41 42 /*ARGSUSED*/ 43 static void 44 siguser_fork(int sig, siginfo_t *sip, void *ucp) 45 { 46 pid = fork(); 47 } 48 49 int 50 main(void) 51 { 52 int e, i, ret; 53 pid_t child; 54 struct sigaction sact; 55 56 bzero(&sact, sizeof (struct sigaction)); 57 sact.sa_flags = SA_SIGINFO; 58 sact.sa_sigaction = siguser_fork; 59 60 (void) sigemptyset(&sact.sa_mask); 61 ret = sigaction(SIGUSR1, &sact, NULL); 62 assert(ret == 0); 63 64 #ifdef ARC4_PREINIT 65 (void) arc4random(); 66 #endif 67 68 fork_data = (arc4_fork_t *)mmap(NULL, sizeof (arc4_fork_t), 69 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); 70 assert(fork_data != MAP_FAILED); 71 72 ret = raise(SIGUSR1); 73 assert(ret == 0); 74 assert(pid != -1); 75 if (pid == 0) { 76 fork_data->af_child = arc4random(); 77 arc4random_buf(fork_data->af_cbuf, sizeof (fork_data->af_cbuf)); 78 exit(0); 79 } 80 81 fork_data->af_parent = arc4random(); 82 arc4random_buf(fork_data->af_pbuf, sizeof (fork_data->af_pbuf)); 83 do { 84 child = wait(&e); 85 } while (child == -1 && errno == EINTR); 86 assert(child == pid); 87 88 /* Now verify our data doesn't match */ 89 assert(fork_data->af_parent != fork_data->af_child); 90 91 /* 92 * For the buffer here, we're mostly concerned that they aren't somehow 93 * getting the same stream. 94 */ 95 for (i = 0; i < sizeof (fork_data->af_pbuf); i++) { 96 if (fork_data->af_pbuf[i] != fork_data->af_cbuf[i]) 97 break; 98 } 99 assert(i != sizeof (fork_data->af_pbuf)); 100 101 return (0); 102 } 103