summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2017-02-17 18:44:10 +0100
committerNikita Popov <nikita.ppv@gmail.com>2017-02-17 18:44:10 +0100
commit5da004cc759f81b5c07ea8798c76fdd305411354 (patch)
treec79bf76dadd412ccbf104272547c265d0ec2bd4b
parentdf3ee2bb2fea1d0ab3a79950f521285f6c46f2a1 (diff)
parentc240feb7f4471d26b9622f48990e78203145fca6 (diff)
downloadphp-git-5da004cc759f81b5c07ea8798c76fdd305411354.tar.gz
Merge branch 'PHP-7.1'
-rw-r--r--ext/standard/random.c86
1 files changed, 45 insertions, 41 deletions
diff --git a/ext/standard/random.c b/ext/standard/random.c
index 5896b3171b..1fd424738c 100644
--- a/ext/standard/random.c
+++ b/ext/standard/random.c
@@ -93,14 +93,13 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, zend_bool should_throw)
}
#elif HAVE_DECL_ARC4RANDOM_BUF && ((defined(__OpenBSD__) && OpenBSD >= 201405) || (defined(__NetBSD__) && __NetBSD_Version__ >= 700000001))
arc4random_buf(bytes, size);
-#elif defined(__linux__) && defined(SYS_getrandom)
- /* Linux getrandom(2) syscall */
+#else
size_t read_bytes = 0;
- size_t amount_to_read = 0;
ssize_t n;
-
+#if defined(__linux__) && defined(SYS_getrandom)
+ /* Linux getrandom(2) syscall */
/* Keep reading until we get enough entropy */
- do {
+ while (read_bytes < size) {
/* Below, (bytes + read_bytes) is pointer arithmetic.
bytes read_bytes size
@@ -110,11 +109,17 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, zend_bool should_throw)
amount_to_read
*/
- amount_to_read = size - read_bytes;
+ size_t amount_to_read = size - read_bytes;
n = syscall(SYS_getrandom, bytes + read_bytes, amount_to_read, 0);
if (n == -1) {
- if (errno == EINTR || errno == EAGAIN) {
+ if (errno == ENOSYS) {
+ /* This can happen if PHP was compiled against a newer kernel where getrandom()
+ * is available, but then runs on an older kernel without getrandom(). If this
+ * happens we simply fall back to reading from /dev/urandom. */
+ ZEND_ASSERT(read_bytes == 0);
+ break;
+ } else if (errno == EINTR || errno == EAGAIN) {
/* Try again */
continue;
}
@@ -130,53 +135,52 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, zend_bool should_throw)
}
read_bytes += (size_t) n;
- } while (read_bytes < size);
-#else
- int fd = RANDOM_G(fd);
- struct stat st;
- size_t read_bytes = 0;
- ssize_t n;
+ }
+#endif
+ if (read_bytes < size) {
+ int fd = RANDOM_G(fd);
+ struct stat st;
- if (fd < 0) {
+ if (fd < 0) {
#if HAVE_DEV_URANDOM
- fd = open("/dev/urandom", O_RDONLY);
+ fd = open("/dev/urandom", O_RDONLY);
#endif
- if (fd < 0) {
- if (should_throw) {
- zend_throw_exception(zend_ce_exception, "Cannot open source device", 0);
+ if (fd < 0) {
+ if (should_throw) {
+ zend_throw_exception(zend_ce_exception, "Cannot open source device", 0);
+ }
+ return FAILURE;
}
- return FAILURE;
- }
- /* Does the file exist and is it a character device? */
- if (fstat(fd, &st) != 0 ||
+ /* Does the file exist and is it a character device? */
+ if (fstat(fd, &st) != 0 ||
# ifdef S_ISNAM
- !(S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
+ !(S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
# else
- !S_ISCHR(st.st_mode)
+ !S_ISCHR(st.st_mode)
# endif
- ) {
- close(fd);
- if (should_throw) {
- zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
+ ) {
+ close(fd);
+ if (should_throw) {
+ zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
+ }
+ return FAILURE;
}
- return FAILURE;
+ RANDOM_G(fd) = fd;
}
- RANDOM_G(fd) = fd;
- }
- while (read_bytes < size) {
- n = read(fd, bytes + read_bytes, size - read_bytes);
- if (n <= 0) {
- break;
+ for (read_bytes = 0; read_bytes < size; read_bytes += (size_t) n) {
+ n = read(fd, bytes + read_bytes, size - read_bytes);
+ if (n <= 0) {
+ break;
+ }
}
- read_bytes += n;
- }
- if (read_bytes < size) {
- if (should_throw) {
- zend_throw_exception(zend_ce_exception, "Could not gather sufficient random data", 0);
+ if (read_bytes < size) {
+ if (should_throw) {
+ zend_throw_exception(zend_ce_exception, "Could not gather sufficient random data", 0);
+ }
+ return FAILURE;
}
- return FAILURE;
}
#endif