Skip to content

Commit

Permalink
If getrandom syscall is unavailable (ENOSYS), try to fallback on /dev…
Browse files Browse the repository at this point in the history
…/urandom
  • Loading branch information
benjarobin committed Feb 15, 2017
1 parent 0d450dd commit b2e7ce4
Showing 1 changed file with 16 additions and 13 deletions.
29 changes: 16 additions & 13 deletions ext/standard/random.c
Expand Up @@ -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
Expand All @@ -110,11 +109,16 @@ 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) {
/* Try to fallback to /dev/urandom */
read_bytes = 0;
break;
}
else if (errno == EINTR || errno == EAGAIN) {
/* Try again */
continue;
}
Expand All @@ -130,12 +134,11 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, zend_bool should_throw)
}

read_bytes += (size_t) n;
} while (read_bytes < size);
#else
}
#endif
if (read_bytes < size) {
int fd = RANDOM_G(fd);
struct stat st;
size_t read_bytes = 0;
ssize_t n;

if (fd < 0) {
#if HAVE_DEV_URANDOM
Expand Down Expand Up @@ -164,12 +167,11 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, zend_bool should_throw)
RANDOM_G(fd) = fd;
}

while (read_bytes < size) {
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) {
Expand All @@ -178,6 +180,7 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, zend_bool should_throw)
}
return FAILURE;
}
}
#endif

return SUCCESS;
Expand Down

0 comments on commit b2e7ce4

Please sign in to comment.