1*545f6b86Sbcook /*	$OpenBSD: arc4random_netbsd.h,v 1.3 2016/06/30 12:19:51 bcook Exp $	*/
229a36ee6Sbcook 
329a36ee6Sbcook /*
429a36ee6Sbcook  * Copyright (c) 1996, David Mazieres <dm@uun.org>
529a36ee6Sbcook  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
629a36ee6Sbcook  * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
729a36ee6Sbcook  * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
829a36ee6Sbcook  *
929a36ee6Sbcook  * Permission to use, copy, modify, and distribute this software for any
1029a36ee6Sbcook  * purpose with or without fee is hereby granted, provided that the above
1129a36ee6Sbcook  * copyright notice and this permission notice appear in all copies.
1229a36ee6Sbcook  *
1329a36ee6Sbcook  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1429a36ee6Sbcook  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1529a36ee6Sbcook  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1629a36ee6Sbcook  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1729a36ee6Sbcook  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1829a36ee6Sbcook  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1929a36ee6Sbcook  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2029a36ee6Sbcook  */
2129a36ee6Sbcook 
2229a36ee6Sbcook /*
2329a36ee6Sbcook  * Stub functions for portability.
2429a36ee6Sbcook  */
2529a36ee6Sbcook 
2629a36ee6Sbcook #include <sys/mman.h>
2729a36ee6Sbcook 
2829a36ee6Sbcook #include <pthread.h>
2929a36ee6Sbcook #include <signal.h>
3029a36ee6Sbcook 
3129a36ee6Sbcook static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
3229a36ee6Sbcook #define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
3329a36ee6Sbcook #define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
3429a36ee6Sbcook 
3529a36ee6Sbcook /*
3629a36ee6Sbcook  * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
3729a36ee6Sbcook  * a program does not link to -lthr. Callbacks registered with pthread_atfork()
3829a36ee6Sbcook  * appear to fail silently. So, it is not always possible to detect a PID
3929a36ee6Sbcook  * wraparound.
4029a36ee6Sbcook  */
4129a36ee6Sbcook #define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
4229a36ee6Sbcook 
4329a36ee6Sbcook static inline void
_getentropy_fail(void)4429a36ee6Sbcook _getentropy_fail(void)
4529a36ee6Sbcook {
4629a36ee6Sbcook 	raise(SIGKILL);
4729a36ee6Sbcook }
4829a36ee6Sbcook 
4929a36ee6Sbcook static volatile sig_atomic_t _rs_forked;
5029a36ee6Sbcook 
5129a36ee6Sbcook static inline void
_rs_forkhandler(void)5229a36ee6Sbcook _rs_forkhandler(void)
5329a36ee6Sbcook {
5429a36ee6Sbcook 	_rs_forked = 1;
5529a36ee6Sbcook }
5629a36ee6Sbcook 
5729a36ee6Sbcook static inline void
_rs_forkdetect(void)5829a36ee6Sbcook _rs_forkdetect(void)
5929a36ee6Sbcook {
6029a36ee6Sbcook 	static pid_t _rs_pid = 0;
6129a36ee6Sbcook 	pid_t pid = getpid();
6229a36ee6Sbcook 
6329a36ee6Sbcook 	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
6429a36ee6Sbcook 		_rs_pid = pid;
6529a36ee6Sbcook 		_rs_forked = 0;
6629a36ee6Sbcook 		if (rs)
6729a36ee6Sbcook 			memset(rs, 0, sizeof(*rs));
6829a36ee6Sbcook 	}
6929a36ee6Sbcook }
7029a36ee6Sbcook 
7129a36ee6Sbcook static inline int
_rs_allocate(struct _rs ** rsp,struct _rsx ** rsxp)7229a36ee6Sbcook _rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
7329a36ee6Sbcook {
7429a36ee6Sbcook 	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
7529a36ee6Sbcook 	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
76044fc755Sderaadt 		return (-1);
7729a36ee6Sbcook 
7829a36ee6Sbcook 	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
7929a36ee6Sbcook 	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
8029a36ee6Sbcook 		munmap(*rsp, sizeof(**rsp));
81*545f6b86Sbcook 		*rsp = NULL;
82044fc755Sderaadt 		return (-1);
8329a36ee6Sbcook 	}
8429a36ee6Sbcook 
8529a36ee6Sbcook 	_ARC4_ATFORK(_rs_forkhandler);
86044fc755Sderaadt 	return (0);
8729a36ee6Sbcook }
88