1228753Smm/* $OpenBSD: arc4random_freebsd.h,v 1.4 2016/06/30 12:19:51 bcook Exp $ */ 2228753Smm 3228753Smm/* 4228753Smm * Copyright (c) 1996, David Mazieres <dm@uun.org> 5228753Smm * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 6228753Smm * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> 7228753Smm * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org> 8228753Smm * 9228753Smm * Permission to use, copy, modify, and distribute this software for any 10228753Smm * purpose with or without fee is hereby granted, provided that the above 11228753Smm * copyright notice and this permission notice appear in all copies. 12228753Smm * 13228753Smm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14228753Smm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15228753Smm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16228753Smm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17228753Smm * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18228753Smm * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19228753Smm * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20228753Smm */ 21228753Smm 22228753Smm/* 23228753Smm * Stub functions for portability. 24228753Smm */ 25228763Smm 26228753Smm#include <sys/mman.h> 27228753Smm 28358090Smm#include <pthread.h> 29358090Smm#include <signal.h> 30358090Smm 31228753Smmstatic pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; 32228753Smm#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx) 33228753Smm#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx) 34228753Smm 35232153Smm/* 36232153Smm * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if 37232153Smm * a program does not link to -lthr. Callbacks registered with pthread_atfork() 38232153Smm * appear to fail silently. So, it is not always possible to detect a PID 39228753Smm * wraparound. 40228753Smm */ 41228753Smm#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f)) 42228753Smm 43228753Smmstatic inline void 44228753Smm_getentropy_fail(void) 45228753Smm{ 46228753Smm raise(SIGKILL); 47228753Smm} 48228753Smm 49228753Smmstatic volatile sig_atomic_t _rs_forked; 50228753Smm 51228753Smmstatic inline void 52228753Smm_rs_forkhandler(void) 53238856Smm{ 54228753Smm _rs_forked = 1; 55228753Smm} 56228753Smm 57228753Smmstatic inline void 58228753Smm_rs_forkdetect(void) 59228753Smm{ 60228753Smm static pid_t _rs_pid = 0; 61232153Smm pid_t pid = getpid(); 62228753Smm 63228753Smm if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) { 64228753Smm _rs_pid = pid; 65228773Smm _rs_forked = 0; 66228753Smm if (rs) 67228753Smm memset(rs, 0, sizeof(*rs)); 68228753Smm } 69228753Smm} 70228753Smm 71228753Smmstatic inline int 72232153Smm_rs_allocate(struct _rs **rsp, struct _rsx **rsxp) 73232153Smm{ 74232153Smm if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, 75232153Smm MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) 76232153Smm return (-1); 77232153Smm 78232153Smm if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, 79232153Smm MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { 80232153Smm munmap(*rsp, sizeof(**rsp)); 81232153Smm *rsp = NULL; 82232153Smm return (-1); 83232153Smm } 84232153Smm 85228753Smm _ARC4_ATFORK(_rs_forkhandler); 86228753Smm return (0); 87232153Smm} 88232153Smm