1*ff825849SDag-Erling Smørgrav /* $OpenBSD: getentropy_solaris.c,v 1.3 2014/07/12 14:46:31 deraadt Exp $ */ 2*ff825849SDag-Erling Smørgrav 3*ff825849SDag-Erling Smørgrav /* 4*ff825849SDag-Erling Smørgrav * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> 5*ff825849SDag-Erling Smørgrav * Copyright (c) 2014 Bob Beck <beck@obtuse.com> 6*ff825849SDag-Erling Smørgrav * 7*ff825849SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 8*ff825849SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 9*ff825849SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 10*ff825849SDag-Erling Smørgrav * 11*ff825849SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12*ff825849SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13*ff825849SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14*ff825849SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15*ff825849SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16*ff825849SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17*ff825849SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18*ff825849SDag-Erling Smørgrav */ 19*ff825849SDag-Erling Smørgrav #include "config.h" 20*ff825849SDag-Erling Smørgrav 21*ff825849SDag-Erling Smørgrav #include <sys/types.h> 22*ff825849SDag-Erling Smørgrav #include <sys/param.h> 23*ff825849SDag-Erling Smørgrav #include <sys/ioctl.h> 24*ff825849SDag-Erling Smørgrav #include <sys/resource.h> 25*ff825849SDag-Erling Smørgrav #include <sys/syscall.h> 26*ff825849SDag-Erling Smørgrav #include <sys/statvfs.h> 27*ff825849SDag-Erling Smørgrav #include <sys/socket.h> 28*ff825849SDag-Erling Smørgrav #include <sys/mount.h> 29*ff825849SDag-Erling Smørgrav #include <sys/mman.h> 30*ff825849SDag-Erling Smørgrav #include <sys/stat.h> 31*ff825849SDag-Erling Smørgrav #include <sys/time.h> 32*ff825849SDag-Erling Smørgrav #include <stdlib.h> 33*ff825849SDag-Erling Smørgrav #include <stdint.h> 34*ff825849SDag-Erling Smørgrav #include <stdio.h> 35*ff825849SDag-Erling Smørgrav #include <termios.h> 36*ff825849SDag-Erling Smørgrav #include <fcntl.h> 37*ff825849SDag-Erling Smørgrav #include <signal.h> 38*ff825849SDag-Erling Smørgrav #include <string.h> 39*ff825849SDag-Erling Smørgrav #include <errno.h> 40*ff825849SDag-Erling Smørgrav #include <unistd.h> 41*ff825849SDag-Erling Smørgrav #include <time.h> 42*ff825849SDag-Erling Smørgrav #include <sys/sha2.h> 43*ff825849SDag-Erling Smørgrav #define SHA512_Init SHA512Init 44*ff825849SDag-Erling Smørgrav #define SHA512_Update SHA512Update 45*ff825849SDag-Erling Smørgrav #define SHA512_Final SHA512Final 46*ff825849SDag-Erling Smørgrav 47*ff825849SDag-Erling Smørgrav #include <sys/vfs.h> 48*ff825849SDag-Erling Smørgrav #include <sys/statfs.h> 49*ff825849SDag-Erling Smørgrav #include <sys/loadavg.h> 50*ff825849SDag-Erling Smørgrav 51*ff825849SDag-Erling Smørgrav #define REPEAT 5 52*ff825849SDag-Erling Smørgrav #define min(a, b) (((a) < (b)) ? (a) : (b)) 53*ff825849SDag-Erling Smørgrav 54*ff825849SDag-Erling Smørgrav #define HX(a, b) \ 55*ff825849SDag-Erling Smørgrav do { \ 56*ff825849SDag-Erling Smørgrav if ((a)) \ 57*ff825849SDag-Erling Smørgrav HD(errno); \ 58*ff825849SDag-Erling Smørgrav else \ 59*ff825849SDag-Erling Smørgrav HD(b); \ 60*ff825849SDag-Erling Smørgrav } while (0) 61*ff825849SDag-Erling Smørgrav 62*ff825849SDag-Erling Smørgrav #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) 63*ff825849SDag-Erling Smørgrav #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) 64*ff825849SDag-Erling Smørgrav #define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) 65*ff825849SDag-Erling Smørgrav 66*ff825849SDag-Erling Smørgrav int getentropy(void *buf, size_t len); 67*ff825849SDag-Erling Smørgrav 68*ff825849SDag-Erling Smørgrav #ifdef CAN_REFERENCE_MAIN 69*ff825849SDag-Erling Smørgrav extern int main(int, char *argv[]); 70*ff825849SDag-Erling Smørgrav #endif 71*ff825849SDag-Erling Smørgrav static int gotdata(char *buf, size_t len); 72*ff825849SDag-Erling Smørgrav static int getentropy_urandom(void *buf, size_t len, const char *path, 73*ff825849SDag-Erling Smørgrav int devfscheck); 74*ff825849SDag-Erling Smørgrav static int getentropy_fallback(void *buf, size_t len); 75*ff825849SDag-Erling Smørgrav 76*ff825849SDag-Erling Smørgrav int 77*ff825849SDag-Erling Smørgrav getentropy(void *buf, size_t len) 78*ff825849SDag-Erling Smørgrav { 79*ff825849SDag-Erling Smørgrav int ret = -1; 80*ff825849SDag-Erling Smørgrav 81*ff825849SDag-Erling Smørgrav if (len > 256) { 82*ff825849SDag-Erling Smørgrav errno = EIO; 83*ff825849SDag-Erling Smørgrav return -1; 84*ff825849SDag-Erling Smørgrav } 85*ff825849SDag-Erling Smørgrav 86*ff825849SDag-Erling Smørgrav /* 87*ff825849SDag-Erling Smørgrav * Try to get entropy with /dev/urandom 88*ff825849SDag-Erling Smørgrav * 89*ff825849SDag-Erling Smørgrav * Solaris provides /dev/urandom as a symbolic link to 90*ff825849SDag-Erling Smørgrav * /devices/pseudo/random@0:urandom which is provided by 91*ff825849SDag-Erling Smørgrav * a devfs filesystem. Best practice is to use O_NOFOLLOW, 92*ff825849SDag-Erling Smørgrav * so we must try the unpublished name directly. 93*ff825849SDag-Erling Smørgrav * 94*ff825849SDag-Erling Smørgrav * This can fail if the process is inside a chroot which lacks 95*ff825849SDag-Erling Smørgrav * the devfs mount, or if file descriptors are exhausted. 96*ff825849SDag-Erling Smørgrav */ 97*ff825849SDag-Erling Smørgrav ret = getentropy_urandom(buf, len, 98*ff825849SDag-Erling Smørgrav "/devices/pseudo/random@0:urandom", 1); 99*ff825849SDag-Erling Smørgrav if (ret != -1) 100*ff825849SDag-Erling Smørgrav return (ret); 101*ff825849SDag-Erling Smørgrav 102*ff825849SDag-Erling Smørgrav /* 103*ff825849SDag-Erling Smørgrav * Unfortunately, chroot spaces on Solaris are sometimes setup 104*ff825849SDag-Erling Smørgrav * with direct device node of the well-known /dev/urandom name 105*ff825849SDag-Erling Smørgrav * (perhaps to avoid dragging all of devfs into the space). 106*ff825849SDag-Erling Smørgrav * 107*ff825849SDag-Erling Smørgrav * This can fail if the process is inside a chroot or if file 108*ff825849SDag-Erling Smørgrav * descriptors are exhausted. 109*ff825849SDag-Erling Smørgrav */ 110*ff825849SDag-Erling Smørgrav ret = getentropy_urandom(buf, len, "/dev/urandom", 0); 111*ff825849SDag-Erling Smørgrav if (ret != -1) 112*ff825849SDag-Erling Smørgrav return (ret); 113*ff825849SDag-Erling Smørgrav 114*ff825849SDag-Erling Smørgrav /* 115*ff825849SDag-Erling Smørgrav * Entropy collection via /dev/urandom has failed. 116*ff825849SDag-Erling Smørgrav * 117*ff825849SDag-Erling Smørgrav * No other API exists for collecting entropy, and we have 118*ff825849SDag-Erling Smørgrav * no failsafe way to get it on Solaris that is not sensitive 119*ff825849SDag-Erling Smørgrav * to resource exhaustion. 120*ff825849SDag-Erling Smørgrav * 121*ff825849SDag-Erling Smørgrav * We have very few options: 122*ff825849SDag-Erling Smørgrav * - Even syslog_r is unsafe to call at this low level, so 123*ff825849SDag-Erling Smørgrav * there is no way to alert the user or program. 124*ff825849SDag-Erling Smørgrav * - Cannot call abort() because some systems have unsafe 125*ff825849SDag-Erling Smørgrav * corefiles. 126*ff825849SDag-Erling Smørgrav * - Could raise(SIGKILL) resulting in silent program termination. 127*ff825849SDag-Erling Smørgrav * - Return EIO, to hint that arc4random's stir function 128*ff825849SDag-Erling Smørgrav * should raise(SIGKILL) 129*ff825849SDag-Erling Smørgrav * - Do the best under the circumstances.... 130*ff825849SDag-Erling Smørgrav * 131*ff825849SDag-Erling Smørgrav * This code path exists to bring light to the issue that Solaris 132*ff825849SDag-Erling Smørgrav * does not provide a failsafe API for entropy collection. 133*ff825849SDag-Erling Smørgrav * 134*ff825849SDag-Erling Smørgrav * We hope this demonstrates that Solaris should consider 135*ff825849SDag-Erling Smørgrav * providing a new failsafe API which works in a chroot or 136*ff825849SDag-Erling Smørgrav * when file descriptors are exhausted. 137*ff825849SDag-Erling Smørgrav */ 138*ff825849SDag-Erling Smørgrav #undef FAIL_INSTEAD_OF_TRYING_FALLBACK 139*ff825849SDag-Erling Smørgrav #ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK 140*ff825849SDag-Erling Smørgrav raise(SIGKILL); 141*ff825849SDag-Erling Smørgrav #endif 142*ff825849SDag-Erling Smørgrav ret = getentropy_fallback(buf, len); 143*ff825849SDag-Erling Smørgrav if (ret != -1) 144*ff825849SDag-Erling Smørgrav return (ret); 145*ff825849SDag-Erling Smørgrav 146*ff825849SDag-Erling Smørgrav errno = EIO; 147*ff825849SDag-Erling Smørgrav return (ret); 148*ff825849SDag-Erling Smørgrav } 149*ff825849SDag-Erling Smørgrav 150*ff825849SDag-Erling Smørgrav /* 151*ff825849SDag-Erling Smørgrav * Basic sanity checking; wish we could do better. 152*ff825849SDag-Erling Smørgrav */ 153*ff825849SDag-Erling Smørgrav static int 154*ff825849SDag-Erling Smørgrav gotdata(char *buf, size_t len) 155*ff825849SDag-Erling Smørgrav { 156*ff825849SDag-Erling Smørgrav char any_set = 0; 157*ff825849SDag-Erling Smørgrav size_t i; 158*ff825849SDag-Erling Smørgrav 159*ff825849SDag-Erling Smørgrav for (i = 0; i < len; ++i) 160*ff825849SDag-Erling Smørgrav any_set |= buf[i]; 161*ff825849SDag-Erling Smørgrav if (any_set == 0) 162*ff825849SDag-Erling Smørgrav return -1; 163*ff825849SDag-Erling Smørgrav return 0; 164*ff825849SDag-Erling Smørgrav } 165*ff825849SDag-Erling Smørgrav 166*ff825849SDag-Erling Smørgrav static int 167*ff825849SDag-Erling Smørgrav getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck) 168*ff825849SDag-Erling Smørgrav { 169*ff825849SDag-Erling Smørgrav struct stat st; 170*ff825849SDag-Erling Smørgrav size_t i; 171*ff825849SDag-Erling Smørgrav int fd, flags; 172*ff825849SDag-Erling Smørgrav int save_errno = errno; 173*ff825849SDag-Erling Smørgrav 174*ff825849SDag-Erling Smørgrav start: 175*ff825849SDag-Erling Smørgrav 176*ff825849SDag-Erling Smørgrav flags = O_RDONLY; 177*ff825849SDag-Erling Smørgrav #ifdef O_NOFOLLOW 178*ff825849SDag-Erling Smørgrav flags |= O_NOFOLLOW; 179*ff825849SDag-Erling Smørgrav #endif 180*ff825849SDag-Erling Smørgrav #ifdef O_CLOEXEC 181*ff825849SDag-Erling Smørgrav flags |= O_CLOEXEC; 182*ff825849SDag-Erling Smørgrav #endif 183*ff825849SDag-Erling Smørgrav fd = open(path, flags, 0); 184*ff825849SDag-Erling Smørgrav if (fd == -1) { 185*ff825849SDag-Erling Smørgrav if (errno == EINTR) 186*ff825849SDag-Erling Smørgrav goto start; 187*ff825849SDag-Erling Smørgrav goto nodevrandom; 188*ff825849SDag-Erling Smørgrav } 189*ff825849SDag-Erling Smørgrav #ifndef O_CLOEXEC 190*ff825849SDag-Erling Smørgrav fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 191*ff825849SDag-Erling Smørgrav #endif 192*ff825849SDag-Erling Smørgrav 193*ff825849SDag-Erling Smørgrav /* Lightly verify that the device node looks sane */ 194*ff825849SDag-Erling Smørgrav if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) || 195*ff825849SDag-Erling Smørgrav (devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) { 196*ff825849SDag-Erling Smørgrav close(fd); 197*ff825849SDag-Erling Smørgrav goto nodevrandom; 198*ff825849SDag-Erling Smørgrav } 199*ff825849SDag-Erling Smørgrav for (i = 0; i < len; ) { 200*ff825849SDag-Erling Smørgrav size_t wanted = len - i; 201*ff825849SDag-Erling Smørgrav ssize_t ret = read(fd, (char*)buf + i, wanted); 202*ff825849SDag-Erling Smørgrav 203*ff825849SDag-Erling Smørgrav if (ret == -1) { 204*ff825849SDag-Erling Smørgrav if (errno == EAGAIN || errno == EINTR) 205*ff825849SDag-Erling Smørgrav continue; 206*ff825849SDag-Erling Smørgrav close(fd); 207*ff825849SDag-Erling Smørgrav goto nodevrandom; 208*ff825849SDag-Erling Smørgrav } 209*ff825849SDag-Erling Smørgrav i += ret; 210*ff825849SDag-Erling Smørgrav } 211*ff825849SDag-Erling Smørgrav close(fd); 212*ff825849SDag-Erling Smørgrav if (gotdata(buf, len) == 0) { 213*ff825849SDag-Erling Smørgrav errno = save_errno; 214*ff825849SDag-Erling Smørgrav return 0; /* satisfied */ 215*ff825849SDag-Erling Smørgrav } 216*ff825849SDag-Erling Smørgrav nodevrandom: 217*ff825849SDag-Erling Smørgrav errno = EIO; 218*ff825849SDag-Erling Smørgrav return -1; 219*ff825849SDag-Erling Smørgrav } 220*ff825849SDag-Erling Smørgrav 221*ff825849SDag-Erling Smørgrav static const int cl[] = { 222*ff825849SDag-Erling Smørgrav CLOCK_REALTIME, 223*ff825849SDag-Erling Smørgrav #ifdef CLOCK_MONOTONIC 224*ff825849SDag-Erling Smørgrav CLOCK_MONOTONIC, 225*ff825849SDag-Erling Smørgrav #endif 226*ff825849SDag-Erling Smørgrav #ifdef CLOCK_MONOTONIC_RAW 227*ff825849SDag-Erling Smørgrav CLOCK_MONOTONIC_RAW, 228*ff825849SDag-Erling Smørgrav #endif 229*ff825849SDag-Erling Smørgrav #ifdef CLOCK_TAI 230*ff825849SDag-Erling Smørgrav CLOCK_TAI, 231*ff825849SDag-Erling Smørgrav #endif 232*ff825849SDag-Erling Smørgrav #ifdef CLOCK_VIRTUAL 233*ff825849SDag-Erling Smørgrav CLOCK_VIRTUAL, 234*ff825849SDag-Erling Smørgrav #endif 235*ff825849SDag-Erling Smørgrav #ifdef CLOCK_UPTIME 236*ff825849SDag-Erling Smørgrav CLOCK_UPTIME, 237*ff825849SDag-Erling Smørgrav #endif 238*ff825849SDag-Erling Smørgrav #ifdef CLOCK_PROCESS_CPUTIME_ID 239*ff825849SDag-Erling Smørgrav CLOCK_PROCESS_CPUTIME_ID, 240*ff825849SDag-Erling Smørgrav #endif 241*ff825849SDag-Erling Smørgrav #ifdef CLOCK_THREAD_CPUTIME_ID 242*ff825849SDag-Erling Smørgrav CLOCK_THREAD_CPUTIME_ID, 243*ff825849SDag-Erling Smørgrav #endif 244*ff825849SDag-Erling Smørgrav }; 245*ff825849SDag-Erling Smørgrav 246*ff825849SDag-Erling Smørgrav static int 247*ff825849SDag-Erling Smørgrav getentropy_fallback(void *buf, size_t len) 248*ff825849SDag-Erling Smørgrav { 249*ff825849SDag-Erling Smørgrav uint8_t results[SHA512_DIGEST_LENGTH]; 250*ff825849SDag-Erling Smørgrav int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; 251*ff825849SDag-Erling Smørgrav static int cnt; 252*ff825849SDag-Erling Smørgrav struct timespec ts; 253*ff825849SDag-Erling Smørgrav struct timeval tv; 254*ff825849SDag-Erling Smørgrav double loadavg[3]; 255*ff825849SDag-Erling Smørgrav struct rusage ru; 256*ff825849SDag-Erling Smørgrav sigset_t sigset; 257*ff825849SDag-Erling Smørgrav struct stat st; 258*ff825849SDag-Erling Smørgrav SHA512_CTX ctx; 259*ff825849SDag-Erling Smørgrav static pid_t lastpid; 260*ff825849SDag-Erling Smørgrav pid_t pid; 261*ff825849SDag-Erling Smørgrav size_t i, ii, m; 262*ff825849SDag-Erling Smørgrav char *p; 263*ff825849SDag-Erling Smørgrav 264*ff825849SDag-Erling Smørgrav pid = getpid(); 265*ff825849SDag-Erling Smørgrav if (lastpid == pid) { 266*ff825849SDag-Erling Smørgrav faster = 1; 267*ff825849SDag-Erling Smørgrav repeat = 2; 268*ff825849SDag-Erling Smørgrav } else { 269*ff825849SDag-Erling Smørgrav faster = 0; 270*ff825849SDag-Erling Smørgrav lastpid = pid; 271*ff825849SDag-Erling Smørgrav repeat = REPEAT; 272*ff825849SDag-Erling Smørgrav } 273*ff825849SDag-Erling Smørgrav for (i = 0; i < len; ) { 274*ff825849SDag-Erling Smørgrav int j; 275*ff825849SDag-Erling Smørgrav SHA512_Init(&ctx); 276*ff825849SDag-Erling Smørgrav for (j = 0; j < repeat; j++) { 277*ff825849SDag-Erling Smørgrav HX((e = gettimeofday(&tv, NULL)) == -1, tv); 278*ff825849SDag-Erling Smørgrav if (e != -1) { 279*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_sec; 280*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_usec; 281*ff825849SDag-Erling Smørgrav } 282*ff825849SDag-Erling Smørgrav 283*ff825849SDag-Erling Smørgrav for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) 284*ff825849SDag-Erling Smørgrav HX(clock_gettime(cl[ii], &ts) == -1, ts); 285*ff825849SDag-Erling Smørgrav 286*ff825849SDag-Erling Smørgrav HX((pid = getpid()) == -1, pid); 287*ff825849SDag-Erling Smørgrav HX((pid = getsid(pid)) == -1, pid); 288*ff825849SDag-Erling Smørgrav HX((pid = getppid()) == -1, pid); 289*ff825849SDag-Erling Smørgrav HX((pid = getpgid(0)) == -1, pid); 290*ff825849SDag-Erling Smørgrav HX((e = getpriority(0, 0)) == -1, e); 291*ff825849SDag-Erling Smørgrav HX((getloadavg(loadavg, 3) == -1), loadavg); 292*ff825849SDag-Erling Smørgrav 293*ff825849SDag-Erling Smørgrav if (!faster) { 294*ff825849SDag-Erling Smørgrav ts.tv_sec = 0; 295*ff825849SDag-Erling Smørgrav ts.tv_nsec = 1; 296*ff825849SDag-Erling Smørgrav (void) nanosleep(&ts, NULL); 297*ff825849SDag-Erling Smørgrav } 298*ff825849SDag-Erling Smørgrav 299*ff825849SDag-Erling Smørgrav HX(sigpending(&sigset) == -1, sigset); 300*ff825849SDag-Erling Smørgrav HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, 301*ff825849SDag-Erling Smørgrav sigset); 302*ff825849SDag-Erling Smørgrav 303*ff825849SDag-Erling Smørgrav #ifdef CAN_REFERENCE_MAIN 304*ff825849SDag-Erling Smørgrav HF(main); /* an addr in program */ 305*ff825849SDag-Erling Smørgrav #endif 306*ff825849SDag-Erling Smørgrav HF(getentropy); /* an addr in this library */ 307*ff825849SDag-Erling Smørgrav HF(printf); /* an addr in libc */ 308*ff825849SDag-Erling Smørgrav p = (char *)&p; 309*ff825849SDag-Erling Smørgrav HD(p); /* an addr on stack */ 310*ff825849SDag-Erling Smørgrav p = (char *)&errno; 311*ff825849SDag-Erling Smørgrav HD(p); /* the addr of errno */ 312*ff825849SDag-Erling Smørgrav 313*ff825849SDag-Erling Smørgrav if (i == 0) { 314*ff825849SDag-Erling Smørgrav struct sockaddr_storage ss; 315*ff825849SDag-Erling Smørgrav struct statvfs stvfs; 316*ff825849SDag-Erling Smørgrav struct termios tios; 317*ff825849SDag-Erling Smørgrav socklen_t ssl; 318*ff825849SDag-Erling Smørgrav off_t off; 319*ff825849SDag-Erling Smørgrav 320*ff825849SDag-Erling Smørgrav /* 321*ff825849SDag-Erling Smørgrav * Prime-sized mappings encourage fragmentation; 322*ff825849SDag-Erling Smørgrav * thus exposing some address entropy. 323*ff825849SDag-Erling Smørgrav */ 324*ff825849SDag-Erling Smørgrav struct mm { 325*ff825849SDag-Erling Smørgrav size_t npg; 326*ff825849SDag-Erling Smørgrav void *p; 327*ff825849SDag-Erling Smørgrav } mm[] = { 328*ff825849SDag-Erling Smørgrav { 17, MAP_FAILED }, { 3, MAP_FAILED }, 329*ff825849SDag-Erling Smørgrav { 11, MAP_FAILED }, { 2, MAP_FAILED }, 330*ff825849SDag-Erling Smørgrav { 5, MAP_FAILED }, { 3, MAP_FAILED }, 331*ff825849SDag-Erling Smørgrav { 7, MAP_FAILED }, { 1, MAP_FAILED }, 332*ff825849SDag-Erling Smørgrav { 57, MAP_FAILED }, { 3, MAP_FAILED }, 333*ff825849SDag-Erling Smørgrav { 131, MAP_FAILED }, { 1, MAP_FAILED }, 334*ff825849SDag-Erling Smørgrav }; 335*ff825849SDag-Erling Smørgrav 336*ff825849SDag-Erling Smørgrav for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { 337*ff825849SDag-Erling Smørgrav HX(mm[m].p = mmap(NULL, 338*ff825849SDag-Erling Smørgrav mm[m].npg * pgs, 339*ff825849SDag-Erling Smørgrav PROT_READ|PROT_WRITE, 340*ff825849SDag-Erling Smørgrav MAP_PRIVATE|MAP_ANON, -1, 341*ff825849SDag-Erling Smørgrav (off_t)0), mm[m].p); 342*ff825849SDag-Erling Smørgrav if (mm[m].p != MAP_FAILED) { 343*ff825849SDag-Erling Smørgrav size_t mo; 344*ff825849SDag-Erling Smørgrav 345*ff825849SDag-Erling Smørgrav /* Touch some memory... */ 346*ff825849SDag-Erling Smørgrav p = mm[m].p; 347*ff825849SDag-Erling Smørgrav mo = cnt % 348*ff825849SDag-Erling Smørgrav (mm[m].npg * pgs - 1); 349*ff825849SDag-Erling Smørgrav p[mo] = 1; 350*ff825849SDag-Erling Smørgrav cnt += (int)((long)(mm[m].p) 351*ff825849SDag-Erling Smørgrav / pgs); 352*ff825849SDag-Erling Smørgrav } 353*ff825849SDag-Erling Smørgrav 354*ff825849SDag-Erling Smørgrav /* Check cnts and times... */ 355*ff825849SDag-Erling Smørgrav for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); 356*ff825849SDag-Erling Smørgrav ii++) { 357*ff825849SDag-Erling Smørgrav HX((e = clock_gettime(cl[ii], 358*ff825849SDag-Erling Smørgrav &ts)) == -1, ts); 359*ff825849SDag-Erling Smørgrav if (e != -1) 360*ff825849SDag-Erling Smørgrav cnt += (int)ts.tv_nsec; 361*ff825849SDag-Erling Smørgrav } 362*ff825849SDag-Erling Smørgrav 363*ff825849SDag-Erling Smørgrav HX((e = getrusage(RUSAGE_SELF, 364*ff825849SDag-Erling Smørgrav &ru)) == -1, ru); 365*ff825849SDag-Erling Smørgrav if (e != -1) { 366*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_sec; 367*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_usec; 368*ff825849SDag-Erling Smørgrav } 369*ff825849SDag-Erling Smørgrav } 370*ff825849SDag-Erling Smørgrav 371*ff825849SDag-Erling Smørgrav for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { 372*ff825849SDag-Erling Smørgrav if (mm[m].p != MAP_FAILED) 373*ff825849SDag-Erling Smørgrav munmap(mm[m].p, mm[m].npg * pgs); 374*ff825849SDag-Erling Smørgrav mm[m].p = MAP_FAILED; 375*ff825849SDag-Erling Smørgrav } 376*ff825849SDag-Erling Smørgrav 377*ff825849SDag-Erling Smørgrav HX(stat(".", &st) == -1, st); 378*ff825849SDag-Erling Smørgrav HX(statvfs(".", &stvfs) == -1, stvfs); 379*ff825849SDag-Erling Smørgrav 380*ff825849SDag-Erling Smørgrav HX(stat("/", &st) == -1, st); 381*ff825849SDag-Erling Smørgrav HX(statvfs("/", &stvfs) == -1, stvfs); 382*ff825849SDag-Erling Smørgrav 383*ff825849SDag-Erling Smørgrav HX((e = fstat(0, &st)) == -1, st); 384*ff825849SDag-Erling Smørgrav if (e == -1) { 385*ff825849SDag-Erling Smørgrav if (S_ISREG(st.st_mode) || 386*ff825849SDag-Erling Smørgrav S_ISFIFO(st.st_mode) || 387*ff825849SDag-Erling Smørgrav S_ISSOCK(st.st_mode)) { 388*ff825849SDag-Erling Smørgrav HX(fstatvfs(0, &stvfs) == -1, 389*ff825849SDag-Erling Smørgrav stvfs); 390*ff825849SDag-Erling Smørgrav HX((off = lseek(0, (off_t)0, 391*ff825849SDag-Erling Smørgrav SEEK_CUR)) < 0, off); 392*ff825849SDag-Erling Smørgrav } 393*ff825849SDag-Erling Smørgrav if (S_ISCHR(st.st_mode)) { 394*ff825849SDag-Erling Smørgrav HX(tcgetattr(0, &tios) == -1, 395*ff825849SDag-Erling Smørgrav tios); 396*ff825849SDag-Erling Smørgrav } else if (S_ISSOCK(st.st_mode)) { 397*ff825849SDag-Erling Smørgrav memset(&ss, 0, sizeof ss); 398*ff825849SDag-Erling Smørgrav ssl = sizeof(ss); 399*ff825849SDag-Erling Smørgrav HX(getpeername(0, 400*ff825849SDag-Erling Smørgrav (void *)&ss, &ssl) == -1, 401*ff825849SDag-Erling Smørgrav ss); 402*ff825849SDag-Erling Smørgrav } 403*ff825849SDag-Erling Smørgrav } 404*ff825849SDag-Erling Smørgrav 405*ff825849SDag-Erling Smørgrav HX((e = getrusage(RUSAGE_CHILDREN, 406*ff825849SDag-Erling Smørgrav &ru)) == -1, ru); 407*ff825849SDag-Erling Smørgrav if (e != -1) { 408*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_sec; 409*ff825849SDag-Erling Smørgrav cnt += (int)ru.ru_utime.tv_usec; 410*ff825849SDag-Erling Smørgrav } 411*ff825849SDag-Erling Smørgrav } else { 412*ff825849SDag-Erling Smørgrav /* Subsequent hashes absorb previous result */ 413*ff825849SDag-Erling Smørgrav HD(results); 414*ff825849SDag-Erling Smørgrav } 415*ff825849SDag-Erling Smørgrav 416*ff825849SDag-Erling Smørgrav HX((e = gettimeofday(&tv, NULL)) == -1, tv); 417*ff825849SDag-Erling Smørgrav if (e != -1) { 418*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_sec; 419*ff825849SDag-Erling Smørgrav cnt += (int)tv.tv_usec; 420*ff825849SDag-Erling Smørgrav } 421*ff825849SDag-Erling Smørgrav 422*ff825849SDag-Erling Smørgrav HD(cnt); 423*ff825849SDag-Erling Smørgrav } 424*ff825849SDag-Erling Smørgrav SHA512_Final(results, &ctx); 425*ff825849SDag-Erling Smørgrav memcpy((char*)buf + i, results, min(sizeof(results), len - i)); 426*ff825849SDag-Erling Smørgrav i += min(sizeof(results), len - i); 427*ff825849SDag-Erling Smørgrav } 428*ff825849SDag-Erling Smørgrav memset(results, 0, sizeof results); 429*ff825849SDag-Erling Smørgrav if (gotdata(buf, len) == 0) { 430*ff825849SDag-Erling Smørgrav errno = save_errno; 431*ff825849SDag-Erling Smørgrav return 0; /* satisfied */ 432*ff825849SDag-Erling Smørgrav } 433*ff825849SDag-Erling Smørgrav errno = EIO; 434*ff825849SDag-Erling Smørgrav return -1; 435*ff825849SDag-Erling Smørgrav } 436