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