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