-/* $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>
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
}
/*
- * 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
}
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;
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;
#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;
}
-/* $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>
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
}
/*
- * 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
}
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;
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;
#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;
}