Skip to content

Commit 508daeb

Browse files
committed
merge revision(s) 1181a68, d84a811: [Backport #21448]
[Bug #21448] Use `getentropy(2)` only on macOS If this is not a system call, then it is using getrandom (which would have been tried already), and cannot be used as a replacement for the random devices. [Bug #21448] Reorder trials in `fill_random_bytes` First try dedicated system calls, such as `getrandom` or `getentropy`, next possible libraries, then fallback to `/dev/urandom`.
1 parent f0f9788 commit 508daeb

File tree

2 files changed

+48
-30
lines changed

2 files changed

+48
-30
lines changed

random.c

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -438,23 +438,17 @@ random_init(int argc, VALUE *argv, VALUE obj)
438438
# define USE_DEV_URANDOM 0
439439
#endif
440440

441-
#ifdef HAVE_GETENTROPY
442-
# define MAX_SEED_LEN_PER_READ 256
443-
static int
444-
fill_random_bytes_urandom(void *seed, size_t size)
445-
{
446-
unsigned char *p = (unsigned char *)seed;
447-
while (size) {
448-
size_t len = size < MAX_SEED_LEN_PER_READ ? size : MAX_SEED_LEN_PER_READ;
449-
if (getentropy(p, len) != 0) {
450-
return -1;
451-
}
452-
p += len;
453-
size -= len;
454-
}
455-
return 0;
456-
}
457-
#elif USE_DEV_URANDOM
441+
#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom
442+
# ifndef GRND_NONBLOCK
443+
# define GRND_NONBLOCK 0x0001 /* not defined in musl libc */
444+
# endif
445+
# define getrandom(ptr, size, flags) \
446+
(ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
447+
# define HAVE_GETRANDOM 1
448+
#endif
449+
450+
/* fill random bytes by reading random device directly */
451+
#if USE_DEV_URANDOM
458452
static int
459453
fill_random_bytes_urandom(void *seed, size_t size)
460454
{
@@ -494,15 +488,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
494488
# define fill_random_bytes_urandom(seed, size) -1
495489
#endif
496490

497-
#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom
498-
# ifndef GRND_NONBLOCK
499-
# define GRND_NONBLOCK 0x0001 /* not defined in musl libc */
500-
# endif
501-
# define getrandom(ptr, size, flags) \
502-
(ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
503-
# define HAVE_GETRANDOM 1
504-
#endif
505-
491+
/* fill random bytes by library */
506492
#if 0
507493
#elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
508494

@@ -520,7 +506,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
520506
# endif
521507

522508
static int
523-
fill_random_bytes_syscall(void *seed, size_t size, int unused)
509+
fill_random_bytes_lib(void *seed, size_t size)
524510
{
525511
#if USE_COMMON_RANDOM
526512
CCRNGStatus status = CCRandomGenerateBytes(seed, size);
@@ -549,7 +535,7 @@ fill_random_bytes_syscall(void *seed, size_t size, int unused)
549535
}
550536
#elif defined(HAVE_ARC4RANDOM_BUF)
551537
static int
552-
fill_random_bytes_syscall(void *buf, size_t size, int unused)
538+
fill_random_bytes_lib(void *buf, size_t size)
553539
{
554540
#if (defined(__OpenBSD__) && OpenBSD >= 201411) || \
555541
(defined(__NetBSD__) && __NetBSD_Version__ >= 700000000) || \
@@ -638,11 +624,17 @@ fill_random_bytes_bcrypt(void *seed, size_t size)
638624
}
639625

640626
static int
641-
fill_random_bytes_syscall(void *seed, size_t size, int unused)
627+
fill_random_bytes_lib(void *seed, size_t size)
642628
{
643629
if (fill_random_bytes_bcrypt(seed, size) == 0) return 0;
644630
return fill_random_bytes_crypt(seed, size);
645631
}
632+
#else
633+
# define fill_random_bytes_lib(seed, size) -1
634+
#endif
635+
636+
/* fill random bytes by dedicated syscall */
637+
#if 0
646638
#elif defined HAVE_GETRANDOM
647639
static int
648640
fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
@@ -666,6 +658,31 @@ fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
666658
}
667659
return -1;
668660
}
661+
#elif defined(HAVE_GETENTROPY)
662+
/*
663+
* The Open Group Base Specifications Issue 8 - IEEE Std 1003.1-2024
664+
* https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
665+
*
666+
* NOTE: `getentropy`(3) on Linux is implemented using `getrandom`(2),
667+
* prefer the latter over this if both are defined.
668+
*/
669+
#ifndef GETENTROPY_MAX
670+
# define GETENTROPY_MAX 256
671+
#endif
672+
static int
673+
fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
674+
{
675+
unsigned char *p = (unsigned char *)seed;
676+
while (size) {
677+
size_t len = size < GETENTROPY_MAX ? size : GETENTROPY_MAX;
678+
if (getentropy(p, len) != 0) {
679+
return -1;
680+
}
681+
p += len;
682+
size -= len;
683+
}
684+
return 0;
685+
}
669686
#else
670687
# define fill_random_bytes_syscall(seed, size, need_secure) -1
671688
#endif
@@ -675,6 +692,7 @@ ruby_fill_random_bytes(void *seed, size_t size, int need_secure)
675692
{
676693
int ret = fill_random_bytes_syscall(seed, size, need_secure);
677694
if (ret == 0) return ret;
695+
if (fill_random_bytes_lib(seed, size) == 0) return 0;
678696
return fill_random_bytes_urandom(seed, size);
679697
}
680698

version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
1212
#define RUBY_VERSION_TEENY 4
1313
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
14-
#define RUBY_PATCHLEVEL 46
14+
#define RUBY_PATCHLEVEL 47
1515

1616
#include "ruby/version.h"
1717
#include "ruby/internal/abi.h"

0 commit comments

Comments
 (0)