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