≥ 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
['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')
}
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;
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. */
}
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;
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)
+ if (l < 0)
+ return -errno;
+ 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;
+ if ((size_t) l == n)
+ return 0; /* Done reading, success. */
- ready_fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (ready_fd < 0)
- return -errno;
- r = fd_wait_for_event(ready_fd, POLLIN, USEC_INFINITY);
- if (r < 0)
- return r;
- seen_initialized = true;
+ 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)
- return -errno;
- return loop_read_exact(fd, p, n, false);
}
int crypto_random_bytes_allocate_iovec(size_t n, struct iovec *ret) {