From 57ee010ff2beb93f2353668a8e347981a8d46ff2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 10 May 2020 11:13:49 +0200 Subject: [PATCH 1/4] random-util: actually encode our expectations on RAND_MAX --- src/basic/random-util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/basic/random-util.c b/src/basic/random-util.c index eae488ae5d..363a1f7151 100644 --- a/src/basic/random-util.c +++ b/src/basic/random-util.c @@ -325,9 +325,11 @@ void initialize_srand(void) { /* INT_MAX gives us only 31 bits, so use 24 out of that. */ #if RAND_MAX >= INT_MAX +assert_cc(RAND_MAX >= 16777215); # define RAND_STEP 3 #else -/* SHORT_INT_MAX or lower gives at most 15 bits, we just just 8 out of that. */ +/* SHORT_INT_MAX or lower gives at most 15 bits, we just use 8 out of that. */ +assert_cc(RAND_MAX >= 255); # define RAND_STEP 1 #endif From e2b55464523adbb3732eb632ac2a21b685935642 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 10 May 2020 11:14:10 +0200 Subject: [PATCH 2/4] random-util: use ERRNO_IS_NOT_SUPPORTED() macro Some container mgr or sandbox solution might block it with an unexpected error code, hence let's be tolerant here. --- src/basic/random-util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basic/random-util.c b/src/basic/random-util.c index 363a1f7151..c32e6e2aac 100644 --- a/src/basic/random-util.c +++ b/src/basic/random-util.c @@ -19,6 +19,7 @@ #endif #include "alloc-util.h" +#include "errno-util.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" @@ -237,7 +238,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { have_syscall = true; return -EIO; - } else if (errno == ENOSYS) { + } else if (ERRNO_IS_NOT_SUPPORTED(errno)) { /* We lack the syscall, continue with reading from /dev/urandom. */ have_syscall = false; break; From 0497c4c28ae2446a58ec0869f5993305bc8e29e0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 10 May 2020 11:15:16 +0200 Subject: [PATCH 3/4] random-util: make use of GRND_INSECURE when it is defined kernel 5.6 added support for a new flag for getrandom(): GRND_INSECURE. If we set it we can get some random data out of the kernel random pool, even if it is not yet initializated. This is great for us to initialize hash table seeds and such, where it is OK if they are crap initially. We used RDRAND for these cases so far, but RDRAND is only available on newer CPUs and some archs. Let's now use GRND_INSECURE for these cases as well, which means we won't needlessly delay boot anymore even on archs/CPUs that do not have RDRAND. Of course we never set this flag when generating crypto keys or uuids. Which makes it different from RDRAND for us (and is the reason I think we should keep explicit RDRAND support in): RDRAND we don't trust enough for crypto keys. But we do trust it enough for UUIDs. --- src/basic/missing_random.h | 4 ++++ src/basic/random-util.c | 18 ++++++++++++++++-- src/basic/random-util.h | 1 + src/test/test-random-util.c | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/basic/missing_random.h b/src/basic/missing_random.h index 2e76031b32..17af87a3ae 100644 --- a/src/basic/missing_random.h +++ b/src/basic/missing_random.h @@ -14,3 +14,7 @@ #ifndef GRND_RANDOM #define GRND_RANDOM 0x0002 #endif + +#ifndef GRND_INSECURE +#define GRND_INSECURE 0x0004 +#endif diff --git a/src/basic/random-util.c b/src/basic/random-util.c index c32e6e2aac..73cc7272db 100644 --- a/src/basic/random-util.c +++ b/src/basic/random-util.c @@ -208,7 +208,9 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) { for (;;) { - r = getrandom(p, n, FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK); + r = getrandom(p, n, + (FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK) | + (FLAGS_SET(flags, RANDOM_ALLOW_INSECURE) ? GRND_INSECURE : 0)); if (r > 0) { have_syscall = true; @@ -264,6 +266,18 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { /* Use /dev/urandom instead */ break; + + } else if (errno == EINVAL) { + + /* Most likely: unknown flag. We know that GRND_INSECURE might cause this, + * hence try without. */ + + if (FLAGS_SET(flags, RANDOM_ALLOW_INSECURE)) { + flags = flags &~ RANDOM_ALLOW_INSECURE; + continue; + } + + return -errno; } else return -errno; } @@ -395,7 +409,7 @@ void random_bytes(void *p, size_t n) { * This function is hence not useful for generating UUIDs or cryptographic key material. */ - if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0) + if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND|RANDOM_ALLOW_INSECURE) >= 0) return; /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */ diff --git a/src/basic/random-util.h b/src/basic/random-util.h index facc11b976..d8e067d96e 100644 --- a/src/basic/random-util.h +++ b/src/basic/random-util.h @@ -10,6 +10,7 @@ typedef enum RandomFlags { RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */ RANDOM_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */ RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */ + RANDOM_ALLOW_INSECURE = 1 << 4, /* Allow usage of GRND_INSECURE flag to kernel's getrandom() API */ } RandomFlags; int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */ diff --git a/src/test/test-random-util.c b/src/test/test-random-util.c index 94c431f7e6..ad5bc72a4e 100644 --- a/src/test/test-random-util.c +++ b/src/test/test-random-util.c @@ -58,6 +58,7 @@ int main(int argc, char **argv) { test_genuine_random_bytes(0); test_genuine_random_bytes(RANDOM_BLOCK); test_genuine_random_bytes(RANDOM_ALLOW_RDRAND); + test_genuine_random_bytes(RANDOM_ALLOW_INSECURE); test_pseudo_random_bytes(); From 82c8bda1f17c655774ac04b6bcb2052d8103fc0a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 10 May 2020 11:20:01 +0200 Subject: [PATCH 4/4] update TODO --- TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO b/TODO index ab4550f658..acb695bfe7 100644 --- a/TODO +++ b/TODO @@ -22,8 +22,6 @@ Janitorial Clean-ups: Features: -* random-util: make user of new GRND_INSECURE flag wherever possible - * nspawn: support time namespaces * pid1: Move to tracking of main pid/control pid of units per pidfd