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