mirror of
https://github.com/systemd/systemd
synced 2026-04-22 23:15:20 +02:00
Compare commits
3 Commits
c10caebb98
...
a5a316e7a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5a316e7a7 | ||
|
|
31234fbeec | ||
|
|
d15e1a29e3 |
@ -13,6 +13,7 @@ downstream_package_name: systemd
|
|||||||
# `git describe` returns in systemd's case 'v245-xxx' which breaks RPM version
|
# `git describe` returns in systemd's case 'v245-xxx' which breaks RPM version
|
||||||
# detection (that expects 245-xxxx'). Let's tweak the version string accordingly
|
# detection (that expects 245-xxxx'). Let's tweak the version string accordingly
|
||||||
upstream_tag_template: "v{version}"
|
upstream_tag_template: "v{version}"
|
||||||
|
srpm_build_deps: []
|
||||||
|
|
||||||
actions:
|
actions:
|
||||||
post-upstream-clone:
|
post-upstream-clone:
|
||||||
|
|||||||
3
TODO
3
TODO
@ -81,6 +81,9 @@ Features:
|
|||||||
* doc: prep a document explaining resolved's internal objects, i.e. Query
|
* doc: prep a document explaining resolved's internal objects, i.e. Query
|
||||||
vs. Question vs. Transaction vs. Stream and so on.
|
vs. Question vs. Transaction vs. Stream and so on.
|
||||||
|
|
||||||
|
* doc: prep a document explaining PID 1's internal logic, i.e. transactions,
|
||||||
|
jobs, units
|
||||||
|
|
||||||
* userbdctl: show user types via colors, also display UID range info in some way
|
* userbdctl: show user types via colors, also display UID range info in some way
|
||||||
|
|
||||||
* bootspec: remove tries counter from boot entry ids
|
* bootspec: remove tries counter from boot entry ids
|
||||||
|
|||||||
@ -160,27 +160,59 @@ int rdrand(unsigned long *ret) {
|
|||||||
int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||||
static int have_syscall = -1;
|
static int have_syscall = -1;
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
bool got_some = false;
|
|
||||||
|
if (FLAGS_SET(flags, RANDOM_BLOCK | RANDOM_ALLOW_RDRAND))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Gathers some high-quality randomness from the kernel (or potentially mid-quality randomness from
|
/* Gathers some high-quality randomness from the kernel (or potentially mid-quality randomness from
|
||||||
* the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't block, unless the RANDOM_BLOCK
|
* the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't block, unless the RANDOM_BLOCK
|
||||||
* flag is set. If RANDOM_MAY_FAIL is set, an error is returned if the random pool is not
|
* flag is set. If it doesn't block, it will still always return some data from the kernel, regardless
|
||||||
* initialized. Otherwise it will always return some data from the kernel, regardless of whether the
|
* of whether the random pool is fully initialized or not. When creating cryptographic key material you
|
||||||
* random pool is fully initialized or not. If RANDOM_EXTEND_WITH_PSEUDO is set, and some but not
|
* should always use RANDOM_BLOCK. */
|
||||||
* enough better quality randomness could be acquired, the rest is filled up with low quality
|
|
||||||
* randomness.
|
|
||||||
*
|
|
||||||
* Of course, when creating cryptographic key material you really shouldn't use RANDOM_ALLOW_DRDRAND
|
|
||||||
* or even RANDOM_EXTEND_WITH_PSEUDO.
|
|
||||||
*
|
|
||||||
* When generating UUIDs it's fine to use RANDOM_ALLOW_RDRAND but not OK to use
|
|
||||||
* RANDOM_EXTEND_WITH_PSEUDO. In fact RANDOM_EXTEND_WITH_PSEUDO is only really fine when invoked via
|
|
||||||
* an "all bets are off" wrapper, such as random_bytes(), see below. */
|
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND))
|
/* Use the getrandom() syscall unless we know we don't have it. */
|
||||||
|
if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
|
||||||
|
for (;;) {
|
||||||
|
ssize_t l = getrandom(p, n, FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_INSECURE);
|
||||||
|
|
||||||
|
if (l > 0) {
|
||||||
|
have_syscall = true;
|
||||||
|
|
||||||
|
if ((size_t) l == n)
|
||||||
|
return 0; /* Yay, success! */
|
||||||
|
|
||||||
|
/* We didn't get enough data, so try again */
|
||||||
|
assert((size_t) l < n);
|
||||||
|
p = (uint8_t*) p + l;
|
||||||
|
n -= l;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else if (l == 0) {
|
||||||
|
have_syscall = true;
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
} else if (ERRNO_IS_NOT_SUPPORTED(errno)) {
|
||||||
|
/* We lack the syscall, continue with reading from /dev/urandom. */
|
||||||
|
have_syscall = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (errno == EINVAL) {
|
||||||
|
/* If we previously passed GRND_INSECURE, and this flag isn't known, then
|
||||||
|
* we're likely running an old kernel which has getrandom() but not
|
||||||
|
* GRND_INSECURE. In this case, fall back to /dev/urandom. */
|
||||||
|
if (!FLAGS_SET(flags, RANDOM_BLOCK))
|
||||||
|
break;
|
||||||
|
|
||||||
|
return -errno;
|
||||||
|
} else
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND)) {
|
||||||
/* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is
|
/* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is
|
||||||
* not required, as we don't trust it (who does?). Note that we only do a single iteration of
|
* not required, as we don't trust it (who does?). Note that we only do a single iteration of
|
||||||
* RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10
|
* RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10
|
||||||
@ -193,13 +225,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
|||||||
size_t m;
|
size_t m;
|
||||||
|
|
||||||
if (rdrand(&u) < 0) {
|
if (rdrand(&u) < 0) {
|
||||||
if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
|
/* OK, this didn't work, let's go with /dev/urandom instead */
|
||||||
/* Fill in the remaining bytes using pseudo-random values */
|
|
||||||
pseudo_random_bytes(p, n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, this didn't work, let's go to getrandom() + /dev/urandom instead */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,87 +237,6 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
|||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 0; /* Yay, success! */
|
return 0; /* Yay, success! */
|
||||||
|
|
||||||
got_some = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use the getrandom() syscall unless we know we don't have it. */
|
|
||||||
if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
ssize_t l;
|
|
||||||
l = getrandom(p, n,
|
|
||||||
(FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK) |
|
|
||||||
(FLAGS_SET(flags, RANDOM_ALLOW_INSECURE) ? GRND_INSECURE : 0));
|
|
||||||
if (l > 0) {
|
|
||||||
have_syscall = true;
|
|
||||||
|
|
||||||
if ((size_t) l == n)
|
|
||||||
return 0; /* Yay, success! */
|
|
||||||
|
|
||||||
assert((size_t) l < n);
|
|
||||||
p = (uint8_t*) p + l;
|
|
||||||
n -= l;
|
|
||||||
|
|
||||||
if (FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
|
|
||||||
/* Fill in the remaining bytes using pseudo-random values */
|
|
||||||
pseudo_random_bytes(p, n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
got_some = true;
|
|
||||||
|
|
||||||
/* Hmm, we didn't get enough good data but the caller insists on good data? Then try again */
|
|
||||||
if (FLAGS_SET(flags, RANDOM_BLOCK))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Fill in the rest with /dev/urandom */
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else if (l == 0) {
|
|
||||||
have_syscall = true;
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
} else if (ERRNO_IS_NOT_SUPPORTED(errno)) {
|
|
||||||
/* We lack the syscall, continue with reading from /dev/urandom. */
|
|
||||||
have_syscall = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else if (errno == EAGAIN) {
|
|
||||||
/* The kernel has no entropy whatsoever. Let's remember to use the syscall
|
|
||||||
* the next time again though.
|
|
||||||
*
|
|
||||||
* If RANDOM_MAY_FAIL is set, return an error so that random_bytes() can
|
|
||||||
* produce some pseudo-random bytes instead. Otherwise, fall back to
|
|
||||||
* /dev/urandom, which we know is empty, but the kernel will produce some
|
|
||||||
* bytes for us on a best-effort basis. */
|
|
||||||
have_syscall = true;
|
|
||||||
|
|
||||||
if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
|
|
||||||
/* Fill in the remaining bytes using pseudorandom values */
|
|
||||||
pseudo_random_bytes(p, n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLAGS_SET(flags, RANDOM_MAY_FAIL))
|
|
||||||
return -ENODATA;
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,7 +366,7 @@ void random_bytes(void *p, size_t n) {
|
|||||||
* This function is hence not useful for generating UUIDs or cryptographic key material.
|
* 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|RANDOM_ALLOW_INSECURE) >= 0)
|
if (genuine_random_bytes(p, n, RANDOM_ALLOW_RDRAND) >= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
|
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
|
||||||
|
|||||||
@ -6,11 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef enum RandomFlags {
|
typedef enum RandomFlags {
|
||||||
RANDOM_EXTEND_WITH_PSEUDO = 1 << 0, /* If we can't get enough genuine randomness, but some, fill up the rest with pseudo-randomness */
|
RANDOM_BLOCK = 1 << 0, /* Rather block than return crap randomness (only if the kernel supports that) */
|
||||||
RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
|
RANDOM_ALLOW_RDRAND = 1 << 1, /* Allow usage of the CPU RNG */
|
||||||
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;
|
} 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 */
|
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 */
|
||||||
|
|||||||
@ -24,11 +24,9 @@ static void test_genuine_random_bytes_one(RandomFlags flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(genuine_random_bytes) {
|
TEST(genuine_random_bytes) {
|
||||||
test_genuine_random_bytes_one(RANDOM_EXTEND_WITH_PSEUDO);
|
|
||||||
test_genuine_random_bytes_one(0);
|
test_genuine_random_bytes_one(0);
|
||||||
test_genuine_random_bytes_one(RANDOM_BLOCK);
|
test_genuine_random_bytes_one(RANDOM_BLOCK);
|
||||||
test_genuine_random_bytes_one(RANDOM_ALLOW_RDRAND);
|
test_genuine_random_bytes_one(RANDOM_ALLOW_RDRAND);
|
||||||
test_genuine_random_bytes_one(RANDOM_ALLOW_INSECURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pseudo_random_bytes) {
|
TEST(pseudo_random_bytes) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user