12b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes/* $OpenBSD: arc4random_linux.h,v 1.7 2014/07/20 20:51:13 bcook Exp $ */ 22b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 32b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes/* 42b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * Copyright (c) 1996, David Mazieres <dm@uun.org> 52b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 62b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> 72b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * 82b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * Permission to use, copy, modify, and distribute this software for any 92b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * purpose with or without fee is hereby granted, provided that the above 102b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * copyright notice and this permission notice appear in all copies. 112b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * 122b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 132b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 142b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 152b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 162b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 172b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 182b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 192b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes */ 202b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 212b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes/* 222b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes * Stub functions for portability. 232b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes */ 242b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 252b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#include <sys/mman.h> 262b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 272b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#include <pthread.h> 282b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#include <signal.h> 292b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 30516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay#include "private/bionic_prctl.h" 31516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay 322b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes// Android gets these from "thread_private.h". 332b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#include "thread_private.h" 342b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; 352b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes//#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx) 362b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes//#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx) 372b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 382b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#ifdef __GLIBC__ 392b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughesextern void *__dso_handle; 402b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughesextern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); 412b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle) 422b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#else 432b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f)) 442b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes#endif 452b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 462b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughesstatic inline void 472b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes_getentropy_fail(void) 482b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes{ 492b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes raise(SIGKILL); 502b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes} 512b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 522b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughesstatic volatile sig_atomic_t _rs_forked; 532b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 542b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughesstatic inline void 552b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes_rs_forkhandler(void) 562b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes{ 572b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes _rs_forked = 1; 582b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes} 592b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 602b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughesstatic inline void 612b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes_rs_forkdetect(void) 622b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes{ 632b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes static pid_t _rs_pid = 0; 642b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes pid_t pid = getpid(); 652b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 662b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) { 672b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes _rs_pid = pid; 682b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes _rs_forked = 0; 692b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes if (rs) 702b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes memset(rs, 0, sizeof(*rs)); 712b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes } 722b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes} 732b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 742b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughesstatic inline int 752b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes_rs_allocate(struct _rs **rsp, struct _rsx **rsxp) 762b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes{ 772b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, 782b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) 792b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes return (-1); 802b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 81516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsp, sizeof(**rsp), 82516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay "arc4random _rs structure"); 83516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay 842b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, 852b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { 862b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes munmap(*rsxp, sizeof(**rsxp)); 872b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes return (-1); 882b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes } 892b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes 90516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsxp, sizeof(**rsxp), 91516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay "arc4random _rsx structure"); 92516fcb28f2fb591e9ae14f909acf00ca5a8b0dc6Daniel Micay 932b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes _ARC4_ATFORK(_rs_forkhandler); 942b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes return (0); 952b67d7dee09852789d9ac7d8972ed6cdb2c18430Elliott Hughes} 96