1*29a36ee6Sbcook /*	$OpenBSD: arc4random_netbsd.h,v 1.1 2015/01/19 20:21:40 bcook Exp $	*/
2*29a36ee6Sbcook 
3*29a36ee6Sbcook /*
4*29a36ee6Sbcook  * Copyright (c) 1996, David Mazieres <dm@uun.org>
5*29a36ee6Sbcook  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6*29a36ee6Sbcook  * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7*29a36ee6Sbcook  * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8*29a36ee6Sbcook  *
9*29a36ee6Sbcook  * Permission to use, copy, modify, and distribute this software for any
10*29a36ee6Sbcook  * purpose with or without fee is hereby granted, provided that the above
11*29a36ee6Sbcook  * copyright notice and this permission notice appear in all copies.
12*29a36ee6Sbcook  *
13*29a36ee6Sbcook  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14*29a36ee6Sbcook  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15*29a36ee6Sbcook  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16*29a36ee6Sbcook  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17*29a36ee6Sbcook  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18*29a36ee6Sbcook  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19*29a36ee6Sbcook  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20*29a36ee6Sbcook  */
21*29a36ee6Sbcook 
22*29a36ee6Sbcook /*
23*29a36ee6Sbcook  * Stub functions for portability.
24*29a36ee6Sbcook  */
25*29a36ee6Sbcook 
26*29a36ee6Sbcook #include <sys/mman.h>
27*29a36ee6Sbcook 
28*29a36ee6Sbcook #include <pthread.h>
29*29a36ee6Sbcook #include <signal.h>
30*29a36ee6Sbcook 
31*29a36ee6Sbcook static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
32*29a36ee6Sbcook #define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
33*29a36ee6Sbcook #define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
34*29a36ee6Sbcook 
35*29a36ee6Sbcook /*
36*29a36ee6Sbcook  * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
37*29a36ee6Sbcook  * a program does not link to -lthr. Callbacks registered with pthread_atfork()
38*29a36ee6Sbcook  * appear to fail silently. So, it is not always possible to detect a PID
39*29a36ee6Sbcook  * wraparound.
40*29a36ee6Sbcook  */
41*29a36ee6Sbcook #define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
42*29a36ee6Sbcook 
43*29a36ee6Sbcook static inline void
44*29a36ee6Sbcook _getentropy_fail(void)
45*29a36ee6Sbcook {
46*29a36ee6Sbcook 	raise(SIGKILL);
47*29a36ee6Sbcook }
48*29a36ee6Sbcook 
49*29a36ee6Sbcook static volatile sig_atomic_t _rs_forked;
50*29a36ee6Sbcook 
51*29a36ee6Sbcook static inline void
52*29a36ee6Sbcook _rs_forkhandler(void)
53*29a36ee6Sbcook {
54*29a36ee6Sbcook 	_rs_forked = 1;
55*29a36ee6Sbcook }
56*29a36ee6Sbcook 
57*29a36ee6Sbcook static inline void
58*29a36ee6Sbcook _rs_forkdetect(void)
59*29a36ee6Sbcook {
60*29a36ee6Sbcook 	static pid_t _rs_pid = 0;
61*29a36ee6Sbcook 	pid_t pid = getpid();
62*29a36ee6Sbcook 
63*29a36ee6Sbcook 	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
64*29a36ee6Sbcook 		_rs_pid = pid;
65*29a36ee6Sbcook 		_rs_forked = 0;
66*29a36ee6Sbcook 		if (rs)
67*29a36ee6Sbcook 			memset(rs, 0, sizeof(*rs));
68*29a36ee6Sbcook 	}
69*29a36ee6Sbcook }
70*29a36ee6Sbcook 
71*29a36ee6Sbcook static inline int
72*29a36ee6Sbcook _rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
73*29a36ee6Sbcook {
74*29a36ee6Sbcook 	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
75*29a36ee6Sbcook 	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
76*29a36ee6Sbcook 		return -1;
77*29a36ee6Sbcook 
78*29a36ee6Sbcook 	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
79*29a36ee6Sbcook 	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
80*29a36ee6Sbcook 		munmap(*rsp, sizeof(**rsp));
81*29a36ee6Sbcook 		return -1;
82*29a36ee6Sbcook 	}
83*29a36ee6Sbcook 
84*29a36ee6Sbcook 	_ARC4_ATFORK(_rs_forkhandler);
85*29a36ee6Sbcook 	return 0;
86*29a36ee6Sbcook }
87