diff options
Diffstat (limited to 'src/lib/libcrypto/arc4random/getentropy_solaris.c')
| -rw-r--r-- | src/lib/libcrypto/arc4random/getentropy_solaris.c | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/src/lib/libcrypto/arc4random/getentropy_solaris.c b/src/lib/libcrypto/arc4random/getentropy_solaris.c index 6aeb8713ab..13afe7e3c9 100644 --- a/src/lib/libcrypto/arc4random/getentropy_solaris.c +++ b/src/lib/libcrypto/arc4random/getentropy_solaris.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: getentropy_solaris.c,v 1.1 2014/07/08 10:45:35 beck Exp $ */ | 1 | /* $OpenBSD: getentropy_solaris.c,v 1.2 2014/07/12 13:19:44 beck Exp $ */ |
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> | 4 | * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> |
| @@ -66,7 +66,8 @@ int getentropy(void *buf, size_t len); | |||
| 66 | 66 | ||
| 67 | extern int main(int, char *argv[]); | 67 | extern int main(int, char *argv[]); |
| 68 | static int gotdata(char *buf, size_t len); | 68 | static int gotdata(char *buf, size_t len); |
| 69 | static int getentropy_urandom(void *buf, size_t len); | 69 | static int getentropy_urandom(void *buf, size_t len, const char *path, |
| 70 | int devfscheck); | ||
| 70 | static int getentropy_fallback(void *buf, size_t len); | 71 | static int getentropy_fallback(void *buf, size_t len); |
| 71 | 72 | ||
| 72 | int | 73 | int |
| @@ -80,20 +81,39 @@ getentropy(void *buf, size_t len) | |||
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | /* | 83 | /* |
| 83 | * Try to get entropy with /dev/urandom | 84 | * Try to get entropy with /dev/urandom... |
| 85 | * | ||
| 86 | * Solaris provides /dev/urandom as a symbolic link to | ||
| 87 | * /devices/pseudo/random@0:urandom which is provided by | ||
| 88 | * a devfs filesystem. Best practice is to use O_NOFOLLOW, | ||
| 89 | * so we must try the unpublished name directly. | ||
| 90 | * | ||
| 91 | * This can fail if the process is inside a chroot which lacks | ||
| 92 | * the devfs mount, or if file descriptors are exhausted. | ||
| 93 | */ | ||
| 94 | ret = getentropy_urandom(buf, len, | ||
| 95 | "/devices/pseudo/random@0:urandom", 1); | ||
| 96 | if (ret != -1) | ||
| 97 | return (ret); | ||
| 98 | |||
| 99 | /* | ||
| 100 | * Unfortunately, chroot spaces on Solaris are sometimes setup | ||
| 101 | * with direct device node of the well-known /dev/urandom name | ||
| 102 | * (perhaps to avoid dragging all of devfs into the space). | ||
| 84 | * | 103 | * |
| 85 | * This can fail if the process is inside a chroot or if file | 104 | * This can fail if the process is inside a chroot or if file |
| 86 | * descriptors are exhausted. | 105 | * descriptors are exhausted. |
| 87 | */ | 106 | */ |
| 88 | ret = getentropy_urandom(buf, len); | 107 | ret = getentropy_urandom(buf, len, "/dev/urandom", 0); |
| 89 | if (ret != -1) | 108 | if (ret != -1) |
| 90 | return (ret); | 109 | return (ret); |
| 110 | |||
| 91 | /* | 111 | /* |
| 92 | * Entropy collection via /dev/urandom and sysctl have failed. | 112 | * Entropy collection via /dev/urandom has failed. |
| 93 | * | 113 | * |
| 94 | * No other API exists for collecting entropy, and we have | 114 | * No other API exists for collecting entropy, and we have |
| 95 | * no failsafe way to get it on Solaris that is not sensitive | 115 | * no failsafe way to get it on Solaris that is not sensitive |
| 96 | * to resource exhaustion. | 116 | * to resource exhaustion. |
| 97 | * | 117 | * |
| 98 | * We have very few options: | 118 | * We have very few options: |
| 99 | * - Even syslog_r is unsafe to call at this low level, so | 119 | * - Even syslog_r is unsafe to call at this low level, so |
| @@ -141,7 +161,7 @@ gotdata(char *buf, size_t len) | |||
| 141 | } | 161 | } |
| 142 | 162 | ||
| 143 | static int | 163 | static int |
| 144 | getentropy_urandom(void *buf, size_t len) | 164 | getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck) |
| 145 | { | 165 | { |
| 146 | struct stat st; | 166 | struct stat st; |
| 147 | size_t i; | 167 | size_t i; |
| @@ -150,19 +170,14 @@ getentropy_urandom(void *buf, size_t len) | |||
| 150 | 170 | ||
| 151 | start: | 171 | start: |
| 152 | 172 | ||
| 153 | flags = O_RDONLY; | 173 | flags = O_RDONLY; |
| 154 | #ifdef O_NOFOLLOW | 174 | #ifdef O_NOFOLLOW |
| 155 | flags |= O_NOFOLLOW; | 175 | flags |= O_NOFOLLOW; |
| 156 | #endif | 176 | #endif |
| 157 | #ifdef O_CLOEXEC | 177 | #ifdef O_CLOEXEC |
| 158 | flags |= O_CLOEXEC; | 178 | flags |= O_CLOEXEC; |
| 159 | #endif | 179 | #endif |
| 160 | /* | 180 | fd = open(path, flags, 0); |
| 161 | * Solaris provides /dev/urandom as a symbolic link. | ||
| 162 | * /devices/pseudo/random@0:urandom should be the | ||
| 163 | * real device path, and we do want O_NOFOLLOW. | ||
| 164 | */ | ||
| 165 | fd = open("/devices/pseudo/random@0:urandom", flags, 0); | ||
| 166 | if (fd == -1) { | 181 | if (fd == -1) { |
| 167 | if (errno == EINTR) | 182 | if (errno == EINTR) |
| 168 | goto start; | 183 | goto start; |
| @@ -173,7 +188,8 @@ start: | |||
| 173 | #endif | 188 | #endif |
| 174 | 189 | ||
| 175 | /* Lightly verify that the device node looks sane */ | 190 | /* Lightly verify that the device node looks sane */ |
| 176 | if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) { | 191 | if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) || |
| 192 | (devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) { | ||
| 177 | close(fd); | 193 | close(fd); |
| 178 | goto nodevrandom; | 194 | goto nodevrandom; |
| 179 | } | 195 | } |
