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