Skip to content

Commit d84a811

Browse files
committed
[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 ec20f7f commit d84a811

File tree

1 file changed

+38
-27
lines changed

1 file changed

+38
-27
lines changed

random.c

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -447,30 +447,8 @@ random_init(int argc, VALUE *argv, VALUE obj)
447447
# define HAVE_GETRANDOM 1
448448
#endif
449449

450-
#if defined(HAVE_GETENTROPY) && !defined(HAVE_GETRANDOM)
451-
/*
452-
* In the case both `getentropy` and `getrandom` are defined, assume
453-
* that the former is implemented using the latter, and use the latter
454-
* in the `syscall` version.
455-
* Otherwise, in the case only `getentropy`, assume it is defined as
456-
* the replacement for security purpose of `/dev/urandom`.
457-
*/
458-
# define MAX_SEED_LEN_PER_READ 256
459-
static int
460-
fill_random_bytes_urandom(void *seed, size_t size)
461-
{
462-
unsigned char *p = (unsigned char *)seed;
463-
while (size) {
464-
size_t len = size < MAX_SEED_LEN_PER_READ ? size : MAX_SEED_LEN_PER_READ;
465-
if (getentropy(p, len) != 0) {
466-
return -1;
467-
}
468-
p += len;
469-
size -= len;
470-
}
471-
return 0;
472-
}
473-
#elif USE_DEV_URANDOM
450+
/* fill random bytes by reading random device directly */
451+
#if USE_DEV_URANDOM
474452
static int
475453
fill_random_bytes_urandom(void *seed, size_t size)
476454
{
@@ -510,6 +488,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
510488
# define fill_random_bytes_urandom(seed, size) -1
511489
#endif
512490

491+
/* fill random bytes by library */
513492
#if 0
514493
#elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
515494

@@ -527,7 +506,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
527506
# endif
528507

529508
static int
530-
fill_random_bytes_syscall(void *seed, size_t size, int unused)
509+
fill_random_bytes_lib(void *seed, size_t size)
531510
{
532511
#if USE_COMMON_RANDOM
533512
CCRNGStatus status = CCRandomGenerateBytes(seed, size);
@@ -560,7 +539,7 @@ fill_random_bytes_syscall(void *seed, size_t size, int unused)
560539
(defined(__FreeBSD__) && __FreeBSD_version >= 1200079))
561540
// [Bug #15039] arc4random_buf(3) should used only if we know it is fork-safe
562541
static int
563-
fill_random_bytes_syscall(void *buf, size_t size, int unused)
542+
fill_random_bytes_lib(void *buf, size_t size)
564543
{
565544
arc4random_buf(buf, size);
566545
return 0;
@@ -643,11 +622,17 @@ fill_random_bytes_bcrypt(void *seed, size_t size)
643622
}
644623

645624
static int
646-
fill_random_bytes_syscall(void *seed, size_t size, int unused)
625+
fill_random_bytes_lib(void *seed, size_t size)
647626
{
648627
if (fill_random_bytes_bcrypt(seed, size) == 0) return 0;
649628
return fill_random_bytes_crypt(seed, size);
650629
}
630+
#else
631+
# define fill_random_bytes_lib(seed, size) -1
632+
#endif
633+
634+
/* fill random bytes by dedicated syscall */
635+
#if 0
651636
#elif defined HAVE_GETRANDOM
652637
static int
653638
fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
@@ -671,6 +656,31 @@ fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
671656
}
672657
return -1;
673658
}
659+
#elif defined(HAVE_GETENTROPY)
660+
/*
661+
* The Open Group Base Specifications Issue 8 - IEEE Std 1003.1-2024
662+
* https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
663+
*
664+
* NOTE: `getentropy`(3) on Linux is implemented using `getrandom`(2),
665+
* prefer the latter over this if both are defined.
666+
*/
667+
#ifndef GETENTROPY_MAX
668+
# define GETENTROPY_MAX 256
669+
#endif
670+
static int
671+
fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
672+
{
673+
unsigned char *p = (unsigned char *)seed;
674+
while (size) {
675+
size_t len = size < GETENTROPY_MAX ? size : GETENTROPY_MAX;
676+
if (getentropy(p, len) != 0) {
677+
return -1;
678+
}
679+
p += len;
680+
size -= len;
681+
}
682+
return 0;
683+
}
674684
#else
675685
# define fill_random_bytes_syscall(seed, size, need_secure) -1
676686
#endif
@@ -680,6 +690,7 @@ ruby_fill_random_bytes(void *seed, size_t size, int need_secure)
680690
{
681691
int ret = fill_random_bytes_syscall(seed, size, need_secure);
682692
if (ret == 0) return ret;
693+
if (fill_random_bytes_lib(seed, size) == 0) return 0;
683694
return fill_random_bytes_urandom(seed, size);
684695
}
685696

0 commit comments

Comments
 (0)