16209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes/*	$OpenBSD: arc4random_linux.h,v 1.7 2014/07/20 20:51:13 bcook Exp $	*/
26209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
36209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes/*
46209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * Copyright (c) 1996, David Mazieres <dm@uun.org>
56209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
66209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
76209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes *
86209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * Permission to use, copy, modify, and distribute this software for any
96209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * purpose with or without fee is hereby granted, provided that the above
106209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * copyright notice and this permission notice appear in all copies.
116209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes *
126209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
136209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
146209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
156209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
166209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
176209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
186209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
196209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes */
206209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
216209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes/*
226209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes * Stub functions for portability.
236209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes */
246209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
256209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#include <sys/mman.h>
266209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
276209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#include <pthread.h>
286209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#include <signal.h>
296209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
306209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes// Android gets these from "thread_private.h".
316209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#include "thread_private.h"
326209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
336209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes//#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
346209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes//#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
356209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
366209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#ifdef __GLIBC__
376209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughesextern void *__dso_handle;
386209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughesextern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
396209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
406209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#else
416209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
426209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes#endif
436209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
446209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughesstatic inline void
456209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes_getentropy_fail(void)
466209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes{
476209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	raise(SIGKILL);
486209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes}
496209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
506209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughesstatic volatile sig_atomic_t _rs_forked;
516209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
526209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughesstatic inline void
536209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes_rs_forkhandler(void)
546209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes{
556209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	_rs_forked = 1;
566209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes}
576209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
586209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughesstatic inline void
596209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes_rs_forkdetect(void)
606209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes{
616209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	static pid_t _rs_pid = 0;
626209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	pid_t pid = getpid();
636209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
646209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
656209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes		_rs_pid = pid;
666209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes		_rs_forked = 0;
676209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes		if (rs)
686209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes			memset(rs, 0, sizeof(*rs));
696209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	}
706209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes}
716209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
726209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughesstatic inline int
736209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
746209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes{
756209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
766209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
776209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes		return (-1);
786209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
796209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
806209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
816209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes		munmap(*rsxp, sizeof(**rsxp));
826209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes		return (-1);
836209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	}
846209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes
856209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	_ARC4_ATFORK(_rs_forkhandler);
866209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes	return (0);
876209c81d40e2b4e129a28bda3259150d79d507e8Elliott Hughes}
88