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