random-util: our baseline includes getrandom() (v3.17) now (#35816)
This commit is contained in:
@@ -41,7 +41,9 @@ REQUIREMENTS:
|
||||
≥ 5.2 for cgroup freezer
|
||||
≥ 5.3 for bounded loops in BPF program
|
||||
≥ 5.4 for pidfd, new mount API, and signed Verity images
|
||||
≥ 5.6 for getrandom() GRND_INSECURE
|
||||
≥ 5.7 for CLONE_INTO_CGROUP, BPF links and the BPF LSM hook
|
||||
≥ 5.9 for close_range()
|
||||
≥ 5.8 for LOOP_CONFIGURE and STATX_ATTR_MOUNT_ROOT
|
||||
≥ 6.3 for MFD_EXEC/MFD_NOEXEC_SEAL and tmpfs noswap option
|
||||
≥ 6.5 for name_to_handle_at() AT_HANDLE_FID, SO_PEERPIDFD/SO_PASSPIDFD,
|
||||
@@ -49,8 +51,8 @@ REQUIREMENTS:
|
||||
≥ 6.9 for pidfs
|
||||
|
||||
⛔ Kernel versions below 4.3 ("minimum baseline") are not supported at
|
||||
all, and are missing required functionality (e.g. CLOCK_BOOTTIME
|
||||
support for timerfd_create(), ambient capabilities, or memfd_create()).
|
||||
all, and are missing required functionality (e.g. CLOCK_BOOTTIME support
|
||||
for timerfd_create(), getrandom(), ambient capabilities, or memfd_create()).
|
||||
|
||||
⚠️ Kernel versions below 5.4 ("recommended baseline") have significant
|
||||
gaps in functionality and are not recommended for use with this version
|
||||
|
||||
+1
-10
@@ -676,21 +676,13 @@ foreach ident : [
|
||||
['getdents64', '''#include <dirent.h>'''],
|
||||
['pidfd_spawn', '''#include <spawn.h>'''],
|
||||
['strerrorname_np', '''#include <string.h>'''],
|
||||
['getrandom', '''#include <sys/random.h>'''],
|
||||
]
|
||||
|
||||
have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
|
||||
conf.set10('HAVE_' + ident[0].to_upper(), have)
|
||||
endforeach
|
||||
|
||||
if cc.has_function('getrandom', prefix : '''#include <sys/random.h>''', args : '-D_GNU_SOURCE')
|
||||
conf.set10('USE_SYS_RANDOM_H', true)
|
||||
conf.set10('HAVE_GETRANDOM', true)
|
||||
else
|
||||
have = cc.has_function('getrandom', prefix : '''#include <linux/random.h>''')
|
||||
conf.set10('USE_SYS_RANDOM_H', false)
|
||||
conf.set10('HAVE_GETRANDOM', have)
|
||||
endif
|
||||
|
||||
#####################################################################
|
||||
|
||||
sh = find_program('sh')
|
||||
@@ -773,7 +765,6 @@ endif
|
||||
foreach header : ['crypt.h',
|
||||
'linux/ioprio.h',
|
||||
'linux/time_types.h',
|
||||
'sys/auxv.h',
|
||||
'sys/sdt.h',
|
||||
'threads.h',
|
||||
'valgrind/memcheck.h',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
#if USE_SYS_RANDOM_H
|
||||
#if HAVE_GETRANDOM
|
||||
# include <sys/random.h>
|
||||
#else
|
||||
# include <linux/random.h>
|
||||
|
||||
@@ -80,12 +80,7 @@ static inline int missing_ioprio_set(int which, int who, int ioprio) {
|
||||
|
||||
#if !HAVE_MEMFD_CREATE
|
||||
static inline int missing_memfd_create(const char *name, unsigned int flags) {
|
||||
# ifdef __NR_memfd_create
|
||||
return syscall(__NR_memfd_create, name, flags);
|
||||
# else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
# endif
|
||||
}
|
||||
|
||||
# define memfd_create missing_memfd_create
|
||||
@@ -96,12 +91,7 @@ static inline int missing_memfd_create(const char *name, unsigned int flags) {
|
||||
#if !HAVE_GETRANDOM
|
||||
/* glibc says getrandom() returns ssize_t */
|
||||
static inline ssize_t missing_getrandom(void *buffer, size_t count, unsigned flags) {
|
||||
# ifdef __NR_getrandom
|
||||
return syscall(__NR_getrandom, buffer, count, flags);
|
||||
# else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
# endif
|
||||
}
|
||||
|
||||
# define getrandom missing_getrandom
|
||||
|
||||
+31
-65
@@ -8,13 +8,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#if HAVE_SYS_AUXV_H
|
||||
# include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-util.h"
|
||||
#include "errno-util.h"
|
||||
@@ -31,7 +28,7 @@
|
||||
#include "sha256.h"
|
||||
#include "time-util.h"
|
||||
|
||||
/* This is a "best effort" kind of thing, but has no real security value. So, this should only be used by
|
||||
/* This is a "best effort" kind of thing, but has no real security value. So, this should only be used by
|
||||
* random_bytes(), which is not meant for crypto. This could be made better, but we're *not* trying to roll a
|
||||
* userspace prng here, or even have forward secrecy, but rather just do the shortest thing that is at least
|
||||
* better than libc rand(). */
|
||||
@@ -53,9 +50,7 @@ static void fallback_random_bytes(void *p, size_t n) {
|
||||
.tid = gettid(),
|
||||
};
|
||||
|
||||
#if HAVE_SYS_AUXV_H
|
||||
memcpy(state.auxval, ULONG_TO_PTR(getauxval(AT_RANDOM)), sizeof(state.auxval));
|
||||
#endif
|
||||
|
||||
while (n > 0) {
|
||||
struct sha256_ctx ctx;
|
||||
@@ -76,8 +71,9 @@ static void fallback_random_bytes(void *p, size_t n) {
|
||||
}
|
||||
|
||||
void random_bytes(void *p, size_t n) {
|
||||
static bool have_getrandom = true, have_grndinsecure = true;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
static bool have_grndinsecure = true;
|
||||
|
||||
assert(p || n == 0);
|
||||
|
||||
if (n == 0)
|
||||
return;
|
||||
@@ -85,32 +81,26 @@ void random_bytes(void *p, size_t n) {
|
||||
for (;;) {
|
||||
ssize_t l;
|
||||
|
||||
if (!have_getrandom)
|
||||
break;
|
||||
|
||||
l = getrandom(p, n, have_grndinsecure ? GRND_INSECURE : GRND_NONBLOCK);
|
||||
if (l > 0) {
|
||||
if ((size_t) l == n)
|
||||
return; /* Done reading, success. */
|
||||
p = (uint8_t *) p + l;
|
||||
n -= l;
|
||||
continue; /* Interrupted by a signal; keep going. */
|
||||
} else if (l == 0)
|
||||
break; /* Weird, so fallback to /dev/urandom. */
|
||||
else if (ERRNO_IS_NOT_SUPPORTED(errno)) {
|
||||
have_getrandom = false;
|
||||
break; /* No syscall, so fallback to /dev/urandom. */
|
||||
} else if (errno == EINVAL && have_grndinsecure) {
|
||||
if (l < 0 && errno == EINVAL && have_grndinsecure) {
|
||||
/* No GRND_INSECURE; fallback to GRND_NONBLOCK. */
|
||||
have_grndinsecure = false;
|
||||
continue; /* No GRND_INSECURE; fallback to GRND_NONBLOCK. */
|
||||
} else if (errno == EAGAIN && !have_grndinsecure)
|
||||
break; /* Will block, but no GRND_INSECURE, so fallback to /dev/urandom. */
|
||||
continue;
|
||||
}
|
||||
if (l <= 0)
|
||||
break; /* Will block (with GRND_NONBLOCK), or unexpected error. Give up and fallback
|
||||
to /dev/urandom. */
|
||||
|
||||
break; /* Unexpected, so just give up and fallback to /dev/urandom. */
|
||||
if ((size_t) l == n)
|
||||
return; /* Done reading, success. */
|
||||
|
||||
p = (uint8_t *) p + l;
|
||||
n -= l;
|
||||
/* Interrupted by a signal; keep going. */
|
||||
}
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd >= 0 && loop_read_exact(fd, p, n, false) == 0)
|
||||
_cleanup_close_ int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd >= 0 && loop_read_exact(fd, p, n, false) >= 0)
|
||||
return;
|
||||
|
||||
/* This is a terrible fallback. Oh well. */
|
||||
@@ -118,8 +108,7 @@ void random_bytes(void *p, size_t n) {
|
||||
}
|
||||
|
||||
int crypto_random_bytes(void *p, size_t n) {
|
||||
static bool have_getrandom = true, seen_initialized = false;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
assert(p || n == 0);
|
||||
|
||||
if (n == 0)
|
||||
return 0;
|
||||
@@ -127,42 +116,19 @@ int crypto_random_bytes(void *p, size_t n) {
|
||||
for (;;) {
|
||||
ssize_t l;
|
||||
|
||||
if (!have_getrandom)
|
||||
break;
|
||||
|
||||
l = getrandom(p, n, 0);
|
||||
if (l > 0) {
|
||||
if ((size_t) l == n)
|
||||
return 0; /* Done reading, success. */
|
||||
p = (uint8_t *) p + l;
|
||||
n -= l;
|
||||
continue; /* Interrupted by a signal; keep going. */
|
||||
} else if (l == 0)
|
||||
return -EIO; /* Weird, should never happen. */
|
||||
else if (ERRNO_IS_NOT_SUPPORTED(errno)) {
|
||||
have_getrandom = false;
|
||||
break; /* No syscall, so fallback to /dev/urandom. */
|
||||
}
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!seen_initialized) {
|
||||
_cleanup_close_ int ready_fd = -EBADF;
|
||||
int r;
|
||||
|
||||
ready_fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (ready_fd < 0)
|
||||
if (l < 0)
|
||||
return -errno;
|
||||
r = fd_wait_for_event(ready_fd, POLLIN, USEC_INFINITY);
|
||||
if (r < 0)
|
||||
return r;
|
||||
seen_initialized = true;
|
||||
}
|
||||
if (l == 0)
|
||||
return -EIO; /* Weird, should never happen. */
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
return loop_read_exact(fd, p, n, false);
|
||||
if ((size_t) l == n)
|
||||
return 0; /* Done reading, success. */
|
||||
|
||||
p = (uint8_t *) p + l;
|
||||
n -= l;
|
||||
/* Interrupted by a signal; keep going. */
|
||||
}
|
||||
}
|
||||
|
||||
int crypto_random_bytes_allocate_iovec(size_t n, struct iovec *ret) {
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
#include <getopt.h>
|
||||
#include <linux/random.h>
|
||||
#include <sys/ioctl.h>
|
||||
#if USE_SYS_RANDOM_H
|
||||
# include <sys/random.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Reference in New Issue
Block a user