diff options
author | Bob Beck <beck@cvs.openbsd.org> | 2014-07-12 13:19:45 +0000 |
---|---|---|
committer | Bob Beck <beck@cvs.openbsd.org> | 2014-07-12 13:19:45 +0000 |
commit | c7531639a6ce8b71f8fac940e4d23c434d879037 (patch) | |
tree | 2fa99adfed42f7e850a8477bed56c093dbb4a2f9 /lib/libcrypto | |
parent | 66ba9535875bd8e69b1d45662734d4bfd3a5c08b (diff) |
Solaris uses a symbolic link for /dev/urandom which harms best practice of
using O_NOFOLLOW - cope with it as best as possible by trying two
different paths. - written by deraadt@ and kettenis@
Diffstat (limited to 'lib/libcrypto')
-rw-r--r-- | lib/libcrypto/crypto/getentropy_solaris.c | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/lib/libcrypto/crypto/getentropy_solaris.c b/lib/libcrypto/crypto/getentropy_solaris.c index 6aeb8713ab2..13afe7e3c9b 100644 --- a/lib/libcrypto/crypto/getentropy_solaris.c +++ b/lib/libcrypto/crypto/getentropy_solaris.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_solaris.c,v 1.1 2014/07/08 10:45:35 beck Exp $ */ +/* $OpenBSD: getentropy_solaris.c,v 1.2 2014/07/12 13:19:44 beck Exp $ */ /* * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> @@ -66,7 +66,8 @@ int getentropy(void *buf, size_t len); extern int main(int, char *argv[]); static int gotdata(char *buf, size_t len); -static int getentropy_urandom(void *buf, size_t len); +static int getentropy_urandom(void *buf, size_t len, const char *path, + int devfscheck); static int getentropy_fallback(void *buf, size_t len); int @@ -80,20 +81,39 @@ getentropy(void *buf, size_t len) } /* - * Try to get entropy with /dev/urandom + * Try to get entropy with /dev/urandom... + * + * Solaris provides /dev/urandom as a symbolic link to + * /devices/pseudo/random@0:urandom which is provided by + * a devfs filesystem. Best practice is to use O_NOFOLLOW, + * so we must try the unpublished name directly. + * + * This can fail if the process is inside a chroot which lacks + * the devfs mount, or if file descriptors are exhausted. + */ + ret = getentropy_urandom(buf, len, + "/devices/pseudo/random@0:urandom", 1); + if (ret != -1) + return (ret); + + /* + * Unfortunately, chroot spaces on Solaris are sometimes setup + * with direct device node of the well-known /dev/urandom name + * (perhaps to avoid dragging all of devfs into the space). * * This can fail if the process is inside a chroot or if file * descriptors are exhausted. */ - ret = getentropy_urandom(buf, len); + ret = getentropy_urandom(buf, len, "/dev/urandom", 0); if (ret != -1) return (ret); + /* - * Entropy collection via /dev/urandom and sysctl have failed. + * Entropy collection via /dev/urandom has failed. * * No other API exists for collecting entropy, and we have - * no failsafe way to get it on Solaris that is not sensitive - * to resource exhaustion. + * no failsafe way to get it on Solaris that is not sensitive + * to resource exhaustion. * * We have very few options: * - Even syslog_r is unsafe to call at this low level, so @@ -141,7 +161,7 @@ gotdata(char *buf, size_t len) } static int -getentropy_urandom(void *buf, size_t len) +getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck) { struct stat st; size_t i; @@ -150,19 +170,14 @@ getentropy_urandom(void *buf, size_t len) start: - flags = O_RDONLY; + flags = O_RDONLY; #ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; + flags |= O_NOFOLLOW; #endif #ifdef O_CLOEXEC - flags |= O_CLOEXEC; + flags |= O_CLOEXEC; #endif - /* - * Solaris provides /dev/urandom as a symbolic link. - * /devices/pseudo/random@0:urandom should be the - * real device path, and we do want O_NOFOLLOW. - */ - fd = open("/devices/pseudo/random@0:urandom", flags, 0); + fd = open(path, flags, 0); if (fd == -1) { if (errno == EINTR) goto start; @@ -173,7 +188,8 @@ start: #endif /* Lightly verify that the device node looks sane */ - if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) { + if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) || + (devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) { close(fd); goto nodevrandom; } |