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