Home | History | Annotate | Line # | Download | only in compat
      1  1.1.1.3  christos /*	$OpenBSD: getentropy_linux.c,v 1.46 2018/11/20 08:04:28 deraadt Exp $	*/
      2      1.1  christos 
      3      1.1  christos /*
      4      1.1  christos  * Copyright (c) 2014 Theo de Raadt <deraadt (at) openbsd.org>
      5      1.1  christos  * Copyright (c) 2014 Bob Beck <beck (at) obtuse.com>
      6      1.1  christos  *
      7      1.1  christos  * Permission to use, copy, modify, and distribute this software for any
      8      1.1  christos  * purpose with or without fee is hereby granted, provided that the above
      9      1.1  christos  * copyright notice and this permission notice appear in all copies.
     10      1.1  christos  *
     11      1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12      1.1  christos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13      1.1  christos  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14      1.1  christos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15      1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16      1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17      1.1  christos  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  1.1.1.3  christos  *
     19  1.1.1.3  christos  * Emulation of getentropy(2) as documented at:
     20  1.1.1.3  christos  * http://man.openbsd.org/getentropy.2
     21      1.1  christos  */
     22      1.1  christos 
     23  1.1.1.3  christos #include "config.h"
     24      1.1  christos /*
     25  1.1.1.3  christos #define	_POSIX_C_SOURCE	199309L
     26  1.1.1.3  christos #define	_GNU_SOURCE	1
     27      1.1  christos */
     28      1.1  christos #include <sys/types.h>
     29      1.1  christos #include <sys/param.h>
     30      1.1  christos #include <sys/ioctl.h>
     31      1.1  christos #include <sys/resource.h>
     32  1.1.1.4  christos #ifndef __QNX__
     33      1.1  christos #include <sys/syscall.h>
     34  1.1.1.4  christos #endif /* !__QNX__ */
     35  1.1.1.3  christos #ifdef SYS__sysctl
     36  1.1.1.3  christos #include <linux/sysctl.h>
     37      1.1  christos #endif
     38      1.1  christos #include <sys/statvfs.h>
     39      1.1  christos #include <sys/socket.h>
     40      1.1  christos #include <sys/mount.h>
     41      1.1  christos #include <sys/mman.h>
     42      1.1  christos #include <sys/stat.h>
     43      1.1  christos #include <sys/time.h>
     44      1.1  christos #include <stdlib.h>
     45      1.1  christos #include <stdint.h>
     46      1.1  christos #include <stdio.h>
     47  1.1.1.4  christos #ifndef __QNX__
     48  1.1.1.3  christos #include <link.h>
     49  1.1.1.4  christos #endif /* __QNX__ */
     50      1.1  christos #include <termios.h>
     51      1.1  christos #include <fcntl.h>
     52      1.1  christos #include <signal.h>
     53      1.1  christos #include <string.h>
     54      1.1  christos #include <errno.h>
     55      1.1  christos #include <unistd.h>
     56      1.1  christos #include <time.h>
     57  1.1.1.3  christos #ifndef HAVE_NETTLE
     58      1.1  christos #include <openssl/sha.h>
     59  1.1.1.3  christos #else
     60      1.1  christos #include <nettle/sha.h>
     61  1.1.1.3  christos #define SHA512_CTX		struct sha512_ctx
     62  1.1.1.3  christos #define SHA512_Init(x)		sha512_init(x)
     63  1.1.1.3  christos #define SHA512_Update(x, b, s)	sha512_update(x, s, b)
     64  1.1.1.3  christos #define SHA512_Final(r, c)	sha512_digest(c, SHA512_DIGEST_SIZE, r)
     65      1.1  christos #endif
     66      1.1  christos 
     67  1.1.1.4  christos #ifndef __QNX__
     68      1.1  christos #include <linux/types.h>
     69      1.1  christos #include <linux/random.h>
     70      1.1  christos #ifdef HAVE_GETAUXVAL
     71      1.1  christos #include <sys/auxv.h>
     72      1.1  christos #endif
     73      1.1  christos #include <sys/vfs.h>
     74  1.1.1.4  christos #endif /* !__QNX__ */
     75  1.1.1.2  christos #ifndef MAP_ANON
     76  1.1.1.2  christos #define MAP_ANON MAP_ANONYMOUS
     77  1.1.1.2  christos #endif
     78      1.1  christos 
     79      1.1  christos #define REPEAT 5
     80      1.1  christos #define min(a, b) (((a) < (b)) ? (a) : (b))
     81      1.1  christos 
     82      1.1  christos #define HX(a, b) \
     83      1.1  christos 	do { \
     84      1.1  christos 		if ((a)) \
     85      1.1  christos 			HD(errno); \
     86      1.1  christos 		else \
     87      1.1  christos 			HD(b); \
     88      1.1  christos 	} while (0)
     89      1.1  christos 
     90      1.1  christos #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
     91      1.1  christos #define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
     92      1.1  christos #define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
     93      1.1  christos 
     94      1.1  christos int	getentropy(void *buf, size_t len);
     95      1.1  christos 
     96  1.1.1.3  christos #if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
     97      1.1  christos static int getentropy_getrandom(void *buf, size_t len);
     98      1.1  christos #endif
     99      1.1  christos static int getentropy_urandom(void *buf, size_t len);
    100      1.1  christos #ifdef SYS__sysctl
    101      1.1  christos static int getentropy_sysctl(void *buf, size_t len);
    102      1.1  christos #endif
    103  1.1.1.4  christos #ifndef __QNX__
    104      1.1  christos static int getentropy_fallback(void *buf, size_t len);
    105  1.1.1.3  christos static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
    106  1.1.1.4  christos #endif /* !__QNX__ */
    107      1.1  christos 
    108      1.1  christos int
    109      1.1  christos getentropy(void *buf, size_t len)
    110      1.1  christos {
    111      1.1  christos 	int ret = -1;
    112      1.1  christos 
    113      1.1  christos 	if (len > 256) {
    114      1.1  christos 		errno = EIO;
    115  1.1.1.3  christos 		return (-1);
    116      1.1  christos 	}
    117      1.1  christos 
    118  1.1.1.3  christos #if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
    119      1.1  christos 	/*
    120  1.1.1.3  christos 	 * Try descriptor-less getrandom(), in non-blocking mode.
    121  1.1.1.3  christos 	 *
    122  1.1.1.3  christos 	 * The design of Linux getrandom is broken.  It has an
    123  1.1.1.3  christos 	 * uninitialized phase coupled with blocking behaviour, which
    124  1.1.1.3  christos 	 * is unacceptable from within a library at boot time without
    125  1.1.1.3  christos 	 * possible recovery. See http://bugs.python.org/issue26839#msg267745
    126      1.1  christos 	 */
    127      1.1  christos 	ret = getentropy_getrandom(buf, len);
    128      1.1  christos 	if (ret != -1)
    129      1.1  christos 		return (ret);
    130      1.1  christos #endif
    131      1.1  christos 
    132      1.1  christos 	/*
    133      1.1  christos 	 * Try to get entropy with /dev/urandom
    134      1.1  christos 	 *
    135      1.1  christos 	 * This can fail if the process is inside a chroot or if file
    136      1.1  christos 	 * descriptors are exhausted.
    137      1.1  christos 	 */
    138      1.1  christos 	ret = getentropy_urandom(buf, len);
    139      1.1  christos 	if (ret != -1)
    140      1.1  christos 		return (ret);
    141      1.1  christos 
    142      1.1  christos #ifdef SYS__sysctl
    143      1.1  christos 	/*
    144      1.1  christos 	 * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
    145      1.1  christos 	 * sysctl is a failsafe API, so it guarantees a result.  This
    146      1.1  christos 	 * should work inside a chroot, or when file descriptors are
    147      1.1  christos 	 * exhausted.
    148      1.1  christos 	 *
    149      1.1  christos 	 * However this can fail if the Linux kernel removes support
    150      1.1  christos 	 * for sysctl.  Starting in 2007, there have been efforts to
    151      1.1  christos 	 * deprecate the sysctl API/ABI, and push callers towards use
    152      1.1  christos 	 * of the chroot-unavailable fd-using /proc mechanism --
    153      1.1  christos 	 * essentially the same problems as /dev/urandom.
    154      1.1  christos 	 *
    155      1.1  christos 	 * Numerous setbacks have been encountered in their deprecation
    156      1.1  christos 	 * schedule, so as of June 2014 the kernel ABI still exists on
    157      1.1  christos 	 * most Linux architectures. The sysctl() stub in libc is missing
    158      1.1  christos 	 * on some systems.  There are also reports that some kernels
    159      1.1  christos 	 * spew messages to the console.
    160      1.1  christos 	 */
    161      1.1  christos 	ret = getentropy_sysctl(buf, len);
    162      1.1  christos 	if (ret != -1)
    163      1.1  christos 		return (ret);
    164      1.1  christos #endif /* SYS__sysctl */
    165      1.1  christos 
    166      1.1  christos 	/*
    167      1.1  christos 	 * Entropy collection via /dev/urandom and sysctl have failed.
    168      1.1  christos 	 *
    169      1.1  christos 	 * No other API exists for collecting entropy.  See the large
    170      1.1  christos 	 * comment block above.
    171      1.1  christos 	 *
    172      1.1  christos 	 * We have very few options:
    173      1.1  christos 	 *     - Even syslog_r is unsafe to call at this low level, so
    174      1.1  christos 	 *	 there is no way to alert the user or program.
    175      1.1  christos 	 *     - Cannot call abort() because some systems have unsafe
    176      1.1  christos 	 *	 corefiles.
    177      1.1  christos 	 *     - Could raise(SIGKILL) resulting in silent program termination.
    178      1.1  christos 	 *     - Return EIO, to hint that arc4random's stir function
    179      1.1  christos 	 *       should raise(SIGKILL)
    180      1.1  christos 	 *     - Do the best under the circumstances....
    181      1.1  christos 	 *
    182      1.1  christos 	 * This code path exists to bring light to the issue that Linux
    183  1.1.1.3  christos 	 * still does not provide a failsafe API for entropy collection.
    184      1.1  christos 	 *
    185      1.1  christos 	 * We hope this demonstrates that Linux should either retain their
    186      1.1  christos 	 * sysctl ABI, or consider providing a new failsafe API which
    187      1.1  christos 	 * works in a chroot or when file descriptors are exhausted.
    188      1.1  christos 	 */
    189  1.1.1.4  christos #ifndef __QNX__
    190      1.1  christos #undef FAIL_INSTEAD_OF_TRYING_FALLBACK
    191      1.1  christos #ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
    192      1.1  christos 	raise(SIGKILL);
    193      1.1  christos #endif
    194      1.1  christos 	ret = getentropy_fallback(buf, len);
    195      1.1  christos 	if (ret != -1)
    196      1.1  christos 		return (ret);
    197  1.1.1.4  christos #else /* !__QNX__ */
    198  1.1.1.4  christos 	fatal_exit("failed to read from /dev/urandom");
    199  1.1.1.4  christos #endif /* __QNX__ */
    200      1.1  christos 
    201      1.1  christos 	errno = EIO;
    202      1.1  christos 	return (ret);
    203      1.1  christos }
    204      1.1  christos 
    205  1.1.1.3  christos #if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
    206      1.1  christos static int
    207      1.1  christos getentropy_getrandom(void *buf, size_t len)
    208      1.1  christos {
    209      1.1  christos 	int pre_errno = errno;
    210      1.1  christos 	int ret;
    211      1.1  christos 	if (len > 256)
    212      1.1  christos 		return (-1);
    213      1.1  christos 	do {
    214  1.1.1.3  christos 		ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
    215      1.1  christos 	} while (ret == -1 && errno == EINTR);
    216      1.1  christos 
    217      1.1  christos 	if (ret != (int)len)
    218      1.1  christos 		return (-1);
    219      1.1  christos 	errno = pre_errno;
    220      1.1  christos 	return (0);
    221      1.1  christos }
    222      1.1  christos #endif
    223      1.1  christos 
    224      1.1  christos static int
    225      1.1  christos getentropy_urandom(void *buf, size_t len)
    226      1.1  christos {
    227      1.1  christos 	struct stat st;
    228      1.1  christos 	size_t i;
    229  1.1.1.4  christos #ifndef __QNX__
    230      1.1  christos 	int fd, cnt, flags;
    231  1.1.1.4  christos #else /* !__QNX__ */
    232  1.1.1.4  christos 	int fd, flags;
    233  1.1.1.4  christos #endif /* __QNX__ */
    234      1.1  christos 	int save_errno = errno;
    235      1.1  christos 
    236      1.1  christos start:
    237      1.1  christos 
    238      1.1  christos 	flags = O_RDONLY;
    239      1.1  christos #ifdef O_NOFOLLOW
    240      1.1  christos 	flags |= O_NOFOLLOW;
    241      1.1  christos #endif
    242      1.1  christos #ifdef O_CLOEXEC
    243      1.1  christos 	flags |= O_CLOEXEC;
    244      1.1  christos #endif
    245      1.1  christos 	fd = open("/dev/urandom", flags, 0);
    246      1.1  christos 	if (fd == -1) {
    247      1.1  christos 		if (errno == EINTR)
    248      1.1  christos 			goto start;
    249      1.1  christos 		goto nodevrandom;
    250      1.1  christos 	}
    251      1.1  christos #ifndef O_CLOEXEC
    252      1.1  christos 	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
    253      1.1  christos #endif
    254      1.1  christos 
    255      1.1  christos 	/* Lightly verify that the device node looks sane */
    256      1.1  christos 	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
    257      1.1  christos 		close(fd);
    258      1.1  christos 		goto nodevrandom;
    259      1.1  christos 	}
    260  1.1.1.4  christos #ifndef __QNX__
    261      1.1  christos 	if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
    262      1.1  christos 		close(fd);
    263      1.1  christos 		goto nodevrandom;
    264      1.1  christos 	}
    265  1.1.1.4  christos #endif /* !__QNX__ */
    266      1.1  christos 	for (i = 0; i < len; ) {
    267      1.1  christos 		size_t wanted = len - i;
    268  1.1.1.3  christos 		ssize_t ret = read(fd, (char *)buf + i, wanted);
    269      1.1  christos 
    270      1.1  christos 		if (ret == -1) {
    271      1.1  christos 			if (errno == EAGAIN || errno == EINTR)
    272      1.1  christos 				continue;
    273      1.1  christos 			close(fd);
    274      1.1  christos 			goto nodevrandom;
    275      1.1  christos 		}
    276      1.1  christos 		i += ret;
    277      1.1  christos 	}
    278      1.1  christos 	close(fd);
    279  1.1.1.3  christos 	errno = save_errno;
    280  1.1.1.3  christos 	return (0);		/* satisfied */
    281      1.1  christos nodevrandom:
    282      1.1  christos 	errno = EIO;
    283  1.1.1.3  christos 	return (-1);
    284      1.1  christos }
    285      1.1  christos 
    286  1.1.1.4  christos #ifndef __QNX__
    287      1.1  christos #ifdef SYS__sysctl
    288      1.1  christos static int
    289      1.1  christos getentropy_sysctl(void *buf, size_t len)
    290      1.1  christos {
    291      1.1  christos 	static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
    292      1.1  christos 	size_t i;
    293      1.1  christos 	int save_errno = errno;
    294      1.1  christos 
    295      1.1  christos 	for (i = 0; i < len; ) {
    296      1.1  christos 		size_t chunk = min(len - i, 16);
    297      1.1  christos 
    298      1.1  christos 		/* SYS__sysctl because some systems already removed sysctl() */
    299      1.1  christos 		struct __sysctl_args args = {
    300      1.1  christos 			.name = mib,
    301      1.1  christos 			.nlen = 3,
    302      1.1  christos 			.oldval = (char *)buf + i,
    303      1.1  christos 			.oldlenp = &chunk,
    304      1.1  christos 		};
    305      1.1  christos 		if (syscall(SYS__sysctl, &args) != 0)
    306      1.1  christos 			goto sysctlfailed;
    307      1.1  christos 		i += chunk;
    308      1.1  christos 	}
    309  1.1.1.3  christos 	errno = save_errno;
    310  1.1.1.3  christos 	return (0);			/* satisfied */
    311      1.1  christos sysctlfailed:
    312      1.1  christos 	errno = EIO;
    313  1.1.1.3  christos 	return (-1);
    314      1.1  christos }
    315      1.1  christos #endif /* SYS__sysctl */
    316      1.1  christos 
    317  1.1.1.3  christos static const int cl[] = {
    318      1.1  christos 	CLOCK_REALTIME,
    319      1.1  christos #ifdef CLOCK_MONOTONIC
    320      1.1  christos 	CLOCK_MONOTONIC,
    321      1.1  christos #endif
    322      1.1  christos #ifdef CLOCK_MONOTONIC_RAW
    323      1.1  christos 	CLOCK_MONOTONIC_RAW,
    324      1.1  christos #endif
    325      1.1  christos #ifdef CLOCK_TAI
    326      1.1  christos 	CLOCK_TAI,
    327      1.1  christos #endif
    328      1.1  christos #ifdef CLOCK_VIRTUAL
    329      1.1  christos 	CLOCK_VIRTUAL,
    330      1.1  christos #endif
    331      1.1  christos #ifdef CLOCK_UPTIME
    332      1.1  christos 	CLOCK_UPTIME,
    333      1.1  christos #endif
    334      1.1  christos #ifdef CLOCK_PROCESS_CPUTIME_ID
    335      1.1  christos 	CLOCK_PROCESS_CPUTIME_ID,
    336      1.1  christos #endif
    337      1.1  christos #ifdef CLOCK_THREAD_CPUTIME_ID
    338      1.1  christos 	CLOCK_THREAD_CPUTIME_ID,
    339      1.1  christos #endif
    340      1.1  christos };
    341      1.1  christos 
    342      1.1  christos static int
    343  1.1.1.3  christos getentropy_phdr(struct dl_phdr_info *info, size_t ATTR_UNUSED(size), void *data)
    344  1.1.1.3  christos {
    345  1.1.1.3  christos 	SHA512_CTX *ctx = data;
    346  1.1.1.3  christos 
    347  1.1.1.3  christos 	SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
    348  1.1.1.3  christos 	return (0);
    349  1.1.1.3  christos }
    350  1.1.1.3  christos 
    351  1.1.1.3  christos static int
    352      1.1  christos getentropy_fallback(void *buf, size_t len)
    353      1.1  christos {
    354      1.1  christos 	uint8_t results[SHA512_DIGEST_LENGTH];
    355      1.1  christos 	int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
    356      1.1  christos 	static int cnt;
    357      1.1  christos 	struct timespec ts;
    358      1.1  christos 	struct timeval tv;
    359      1.1  christos 	struct rusage ru;
    360      1.1  christos 	sigset_t sigset;
    361      1.1  christos 	struct stat st;
    362  1.1.1.3  christos 	SHA512_CTX ctx;
    363      1.1  christos 	static pid_t lastpid;
    364      1.1  christos 	pid_t pid;
    365      1.1  christos 	size_t i, ii, m;
    366      1.1  christos 	char *p;
    367      1.1  christos 
    368      1.1  christos 	pid = getpid();
    369      1.1  christos 	if (lastpid == pid) {
    370      1.1  christos 		faster = 1;
    371      1.1  christos 		repeat = 2;
    372      1.1  christos 	} else {
    373      1.1  christos 		faster = 0;
    374      1.1  christos 		lastpid = pid;
    375      1.1  christos 		repeat = REPEAT;
    376      1.1  christos 	}
    377      1.1  christos 	for (i = 0; i < len; ) {
    378      1.1  christos 		int j;
    379  1.1.1.3  christos 		SHA512_Init(&ctx);
    380      1.1  christos 		for (j = 0; j < repeat; j++) {
    381      1.1  christos 			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
    382      1.1  christos 			if (e != -1) {
    383      1.1  christos 				cnt += (int)tv.tv_sec;
    384      1.1  christos 				cnt += (int)tv.tv_usec;
    385      1.1  christos 			}
    386      1.1  christos 
    387  1.1.1.3  christos 			dl_iterate_phdr(getentropy_phdr, &ctx);
    388  1.1.1.3  christos 
    389      1.1  christos 			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
    390      1.1  christos 				HX(clock_gettime(cl[ii], &ts) == -1, ts);
    391      1.1  christos 
    392      1.1  christos 			HX((pid = getpid()) == -1, pid);
    393      1.1  christos 			HX((pid = getsid(pid)) == -1, pid);
    394      1.1  christos 			HX((pid = getppid()) == -1, pid);
    395      1.1  christos 			HX((pid = getpgid(0)) == -1, pid);
    396      1.1  christos 			HX((e = getpriority(0, 0)) == -1, e);
    397      1.1  christos 
    398      1.1  christos 			if (!faster) {
    399      1.1  christos 				ts.tv_sec = 0;
    400      1.1  christos 				ts.tv_nsec = 1;
    401      1.1  christos 				(void) nanosleep(&ts, NULL);
    402      1.1  christos 			}
    403      1.1  christos 
    404      1.1  christos 			HX(sigpending(&sigset) == -1, sigset);
    405      1.1  christos 			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
    406      1.1  christos 			    sigset);
    407      1.1  christos 
    408      1.1  christos 			HF(getentropy);	/* an addr in this library */
    409      1.1  christos 			HF(printf);		/* an addr in libc */
    410      1.1  christos 			p = (char *)&p;
    411      1.1  christos 			HD(p);		/* an addr on stack */
    412      1.1  christos 			p = (char *)&errno;
    413      1.1  christos 			HD(p);		/* the addr of errno */
    414      1.1  christos 
    415      1.1  christos 			if (i == 0) {
    416      1.1  christos 				struct sockaddr_storage ss;
    417      1.1  christos 				struct statvfs stvfs;
    418      1.1  christos 				struct termios tios;
    419      1.1  christos 				struct statfs stfs;
    420      1.1  christos 				socklen_t ssl;
    421      1.1  christos 				off_t off;
    422      1.1  christos 
    423      1.1  christos 				/*
    424      1.1  christos 				 * Prime-sized mappings encourage fragmentation;
    425      1.1  christos 				 * thus exposing some address entropy.
    426      1.1  christos 				 */
    427      1.1  christos 				struct mm {
    428      1.1  christos 					size_t	npg;
    429      1.1  christos 					void	*p;
    430      1.1  christos 				} mm[] =	 {
    431      1.1  christos 					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
    432      1.1  christos 					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
    433      1.1  christos 					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
    434      1.1  christos 					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
    435      1.1  christos 					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
    436      1.1  christos 					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
    437      1.1  christos 				};
    438      1.1  christos 
    439      1.1  christos 				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
    440      1.1  christos 					HX(mm[m].p = mmap(NULL,
    441      1.1  christos 					    mm[m].npg * pgs,
    442      1.1  christos 					    PROT_READ|PROT_WRITE,
    443      1.1  christos 					    MAP_PRIVATE|MAP_ANON, -1,
    444      1.1  christos 					    (off_t)0), mm[m].p);
    445      1.1  christos 					if (mm[m].p != MAP_FAILED) {
    446      1.1  christos 						size_t mo;
    447      1.1  christos 
    448      1.1  christos 						/* Touch some memory... */
    449      1.1  christos 						p = mm[m].p;
    450      1.1  christos 						mo = cnt %
    451      1.1  christos 						    (mm[m].npg * pgs - 1);
    452      1.1  christos 						p[mo] = 1;
    453      1.1  christos 						cnt += (int)((long)(mm[m].p)
    454      1.1  christos 						    / pgs);
    455      1.1  christos 					}
    456      1.1  christos 
    457      1.1  christos 					/* Check cnts and times... */
    458      1.1  christos 					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
    459      1.1  christos 					    ii++) {
    460      1.1  christos 						HX((e = clock_gettime(cl[ii],
    461      1.1  christos 						    &ts)) == -1, ts);
    462      1.1  christos 						if (e != -1)
    463      1.1  christos 							cnt += (int)ts.tv_nsec;
    464      1.1  christos 					}
    465      1.1  christos 
    466      1.1  christos 					HX((e = getrusage(RUSAGE_SELF,
    467      1.1  christos 					    &ru)) == -1, ru);
    468      1.1  christos 					if (e != -1) {
    469      1.1  christos 						cnt += (int)ru.ru_utime.tv_sec;
    470      1.1  christos 						cnt += (int)ru.ru_utime.tv_usec;
    471      1.1  christos 					}
    472      1.1  christos 				}
    473      1.1  christos 
    474      1.1  christos 				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
    475      1.1  christos 					if (mm[m].p != MAP_FAILED)
    476      1.1  christos 						munmap(mm[m].p, mm[m].npg * pgs);
    477      1.1  christos 					mm[m].p = MAP_FAILED;
    478      1.1  christos 				}
    479      1.1  christos 
    480      1.1  christos 				HX(stat(".", &st) == -1, st);
    481      1.1  christos 				HX(statvfs(".", &stvfs) == -1, stvfs);
    482      1.1  christos 				HX(statfs(".", &stfs) == -1, stfs);
    483      1.1  christos 
    484      1.1  christos 				HX(stat("/", &st) == -1, st);
    485      1.1  christos 				HX(statvfs("/", &stvfs) == -1, stvfs);
    486      1.1  christos 				HX(statfs("/", &stfs) == -1, stfs);
    487      1.1  christos 
    488      1.1  christos 				HX((e = fstat(0, &st)) == -1, st);
    489      1.1  christos 				if (e == -1) {
    490      1.1  christos 					if (S_ISREG(st.st_mode) ||
    491      1.1  christos 					    S_ISFIFO(st.st_mode) ||
    492      1.1  christos 					    S_ISSOCK(st.st_mode)) {
    493      1.1  christos 						HX(fstatvfs(0, &stvfs) == -1,
    494      1.1  christos 						    stvfs);
    495      1.1  christos 						HX(fstatfs(0, &stfs) == -1,
    496      1.1  christos 						    stfs);
    497      1.1  christos 						HX((off = lseek(0, (off_t)0,
    498      1.1  christos 						    SEEK_CUR)) < 0, off);
    499      1.1  christos 					}
    500      1.1  christos 					if (S_ISCHR(st.st_mode)) {
    501      1.1  christos 						HX(tcgetattr(0, &tios) == -1,
    502      1.1  christos 						    tios);
    503      1.1  christos 					} else if (S_ISSOCK(st.st_mode)) {
    504      1.1  christos 						memset(&ss, 0, sizeof ss);
    505      1.1  christos 						ssl = sizeof(ss);
    506      1.1  christos 						HX(getpeername(0,
    507      1.1  christos 						    (void *)&ss, &ssl) == -1,
    508      1.1  christos 						    ss);
    509      1.1  christos 					}
    510      1.1  christos 				}
    511      1.1  christos 
    512      1.1  christos 				HX((e = getrusage(RUSAGE_CHILDREN,
    513      1.1  christos 				    &ru)) == -1, ru);
    514      1.1  christos 				if (e != -1) {
    515      1.1  christos 					cnt += (int)ru.ru_utime.tv_sec;
    516      1.1  christos 					cnt += (int)ru.ru_utime.tv_usec;
    517      1.1  christos 				}
    518      1.1  christos 			} else {
    519      1.1  christos 				/* Subsequent hashes absorb previous result */
    520      1.1  christos 				HD(results);
    521      1.1  christos 			}
    522      1.1  christos 
    523      1.1  christos 			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
    524      1.1  christos 			if (e != -1) {
    525      1.1  christos 				cnt += (int)tv.tv_sec;
    526      1.1  christos 				cnt += (int)tv.tv_usec;
    527      1.1  christos 			}
    528      1.1  christos 
    529      1.1  christos 			HD(cnt);
    530      1.1  christos 		}
    531      1.1  christos #ifdef HAVE_GETAUXVAL
    532  1.1.1.3  christos #ifdef AT_RANDOM
    533      1.1  christos 		/* Not as random as you think but we take what we are given */
    534      1.1  christos 		p = (char *) getauxval(AT_RANDOM);
    535      1.1  christos 		if (p)
    536      1.1  christos 			HR(p, 16);
    537  1.1.1.3  christos #endif
    538  1.1.1.3  christos #ifdef AT_SYSINFO_EHDR
    539      1.1  christos 		p = (char *) getauxval(AT_SYSINFO_EHDR);
    540      1.1  christos 		if (p)
    541      1.1  christos 			HR(p, pgs);
    542  1.1.1.3  christos #endif
    543  1.1.1.3  christos #ifdef AT_BASE
    544      1.1  christos 		p = (char *) getauxval(AT_BASE);
    545      1.1  christos 		if (p)
    546      1.1  christos 			HD(p);
    547  1.1.1.3  christos #endif
    548  1.1.1.3  christos #endif
    549      1.1  christos 
    550  1.1.1.3  christos 		SHA512_Final(results, &ctx);
    551  1.1.1.3  christos 		memcpy((char *)buf + i, results, min(sizeof(results), len - i));
    552      1.1  christos 		i += min(sizeof(results), len - i);
    553      1.1  christos 	}
    554  1.1.1.3  christos 	explicit_bzero(&ctx, sizeof ctx);
    555  1.1.1.3  christos 	explicit_bzero(results, sizeof results);
    556  1.1.1.3  christos 	errno = save_errno;
    557  1.1.1.3  christos 	return (0);		/* satisfied */
    558      1.1  christos }
    559  1.1.1.4  christos #endif /* !__QNX__ */
    560