From 3df3e884ae1237ef0d4d23b0e80f4ffda95ac135 Mon Sep 17 00:00:00 2001 From: Ronny Chevalier Date: Fri, 10 Apr 2015 22:27:10 +0200 Subject: [PATCH] shared: add random-util.[ch] --- Makefile.am | 2 + src/firstboot/firstboot.c | 1 + src/journal/journal-file.c | 1 + src/journal/journald-rate-limit.c | 1 + src/journal/test-compress.c | 1 + src/libsystemd-network/sd-dhcp-client.c | 1 + src/libsystemd-network/sd-dhcp6-client.c | 1 + src/libsystemd-network/sd-ipv4ll.c | 1 + src/libsystemd-network/sd-pppoe.c | 1 + src/libsystemd-terminal/modeset.c | 2 + src/libsystemd/sd-id128/sd-id128.c | 1 + src/nspawn/nspawn.c | 1 + src/resolve/resolved-dns-scope.c | 1 + src/resolve/resolved-dns-transaction.c | 1 + src/resolve/resolved-manager.c | 1 + src/shared/ask-password-api.c | 1 + src/shared/hashmap.c | 1 + src/shared/random-util.c | 127 +++++++++++++++++++++++ src/shared/random-util.h | 38 +++++++ src/shared/util.c | 96 +---------------- src/shared/util.h | 16 --- src/udev/cdrom_id/cdrom_id.c | 1 + src/udev/net/link-config.c | 1 + src/udev/scsi_id/scsi_serial.c | 1 + 24 files changed, 188 insertions(+), 111 deletions(-) create mode 100644 src/shared/random-util.c create mode 100644 src/shared/random-util.h diff --git a/Makefile.am b/Makefile.am index ceb1d7d565f..f348ef90f36 100644 --- a/Makefile.am +++ b/Makefile.am @@ -901,6 +901,8 @@ libsystemd_shared_la_SOURCES = \ src/shared/memfd-util.h \ src/shared/process-util.c \ src/shared/process-util.h \ + src/shared/random-util.c \ + src/shared/random-util.h \ src/shared/uid-range.c \ src/shared/uid-range.h \ src/shared/nss-util.h \ diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index a37ca170fb5..c92f379806d 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -32,6 +32,7 @@ #include "mkdir.h" #include "time-util.h" #include "path-util.h" +#include "random-util.h" #include "locale-util.h" #include "ask-password-api.h" diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 6bbcc6d777d..a432eb08a61 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -34,6 +34,7 @@ #include "journal-authenticate.h" #include "lookup3.h" #include "compress.h" +#include "random-util.h" #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem)) #define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem)) diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c index 6d779d2966a..6f83035a4ee 100644 --- a/src/journal/journald-rate-limit.c +++ b/src/journal/journald-rate-limit.c @@ -26,6 +26,7 @@ #include "list.h" #include "util.h" #include "hashmap.h" +#include "random-util.h" #define POOLS_MAX 5 #define BUCKETS_MAX 127 diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index ae41c0c4c79..41a566d7144 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -20,6 +20,7 @@ #include "compress.h" #include "util.h" #include "macro.h" +#include "random-util.h" #ifdef HAVE_XZ # define XZ_OK 0 diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 4224e0197cd..c44392eb81d 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -28,6 +28,7 @@ #include "util.h" #include "refcnt.h" +#include "random-util.h" #include "async.h" #include "dhcp-protocol.h" diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 3db1cb09dbe..9d88d469f37 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -28,6 +28,7 @@ #include "udev-util.h" #include "util.h" #include "refcnt.h" +#include "random-util.h" #include "network-internal.h" #include "sd-dhcp6-client.h" diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index 02f2f9e0a91..9e04db96bb6 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -27,6 +27,7 @@ #include "siphash24.h" #include "list.h" #include "refcnt.h" +#include "random-util.h" #include "ipv4ll-internal.h" #include "sd-ipv4ll.h" diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c index 601f3bd400a..1de8a5e8bf1 100644 --- a/src/libsystemd-network/sd-pppoe.c +++ b/src/libsystemd-network/sd-pppoe.c @@ -33,6 +33,7 @@ #include "event-util.h" #include "util.h" +#include "random-util.h" #include "socket-util.h" #include "async.h" #include "refcnt.h" diff --git a/src/libsystemd-terminal/modeset.c b/src/libsystemd-terminal/modeset.c index cccaabaa062..621d6c4fa3d 100644 --- a/src/libsystemd-terminal/modeset.c +++ b/src/libsystemd-terminal/modeset.c @@ -40,11 +40,13 @@ #include #include #include + #include "build.h" #include "grdev.h" #include "macro.h" #include "sysview.h" #include "util.h" +#include "random-util.h" typedef struct Modeset Modeset; diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index f0ffedc38b3..46f2181ea80 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -26,6 +26,7 @@ #include "util.h" #include "macro.h" #include "sd-id128.h" +#include "random-util.h" _public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) { unsigned n; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 96075327df4..6417a8c3b3b 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -52,6 +52,7 @@ #include #endif +#include "random-util.h" #include "sd-daemon.h" #include "sd-bus.h" #include "sd-id128.h" diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index ba116de6f5a..b2bc09266ce 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -27,6 +27,7 @@ #include "af-list.h" #include "resolved-dns-domain.h" #include "resolved-dns-scope.h" +#include "random-util.h" #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC) #define MULTICAST_RATELIMIT_BURST 1000 diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index bc1a90db1bb..214938986d1 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -22,6 +22,7 @@ #include "af-list.h" #include "resolved-dns-transaction.h" +#include "random-util.h" DnsTransaction* dns_transaction_free(DnsTransaction *t) { DnsQuery *q; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index adaa6c6e7f0..a10a3277bef 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -31,6 +31,7 @@ #include "utf8.h" #include "fileio-label.h" #include "ordered-set.h" +#include "random-util.h" #include "resolved-dns-domain.h" #include "resolved-conf.h" diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index dfc89d23fd9..ad1a7731ff1 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -35,6 +35,7 @@ #include "formats-util.h" #include "mkdir.h" #include "strv.h" +#include "random-util.h" #include "ask-password-api.h" diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c index 48d75023918..d8ea9d5aa8f 100644 --- a/src/shared/hashmap.c +++ b/src/shared/hashmap.c @@ -30,6 +30,7 @@ #include "siphash24.h" #include "strv.h" #include "mempool.h" +#include "random-util.h" #ifdef ENABLE_DEBUG_HASHMAP #include "list.h" diff --git a/src/shared/random-util.c b/src/shared/random-util.c new file mode 100644 index 00000000000..88f5182508e --- /dev/null +++ b/src/shared/random-util.c @@ -0,0 +1,127 @@ +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "random-util.h" +#include "time-util.h" +#include "missing.h" +#include "util.h" + +int dev_urandom(void *p, size_t n) { + static int have_syscall = -1; + + _cleanup_close_ int fd = -1; + int r; + + /* Gathers some randomness from the kernel. This call will + * never block, and will always return some data from the + * kernel, regardless if the random pool is fully initialized + * or not. It thus makes no guarantee for the quality of the + * returned entropy, but is good enough for or usual usecases + * of seeding the hash functions for hashtable */ + + /* Use the getrandom() syscall unless we know we don't have + * it, or when the requested size is too large for it. */ + if (have_syscall != 0 || (size_t) (int) n != n) { + r = getrandom(p, n, GRND_NONBLOCK); + if (r == (int) n) { + have_syscall = true; + return 0; + } + + if (r < 0) { + if (errno == ENOSYS) + /* we lack the syscall, continue with + * reading from /dev/urandom */ + have_syscall = false; + else if (errno == EAGAIN) + /* not enough entropy for now. Let's + * remember to use the syscall the + * next time, again, but also read + * from /dev/urandom for now, which + * doesn't care about the current + * amount of entropy. */ + have_syscall = true; + else + return -errno; + } else + /* too short read? */ + return -ENODATA; + } + + fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return errno == ENOENT ? -ENOSYS : -errno; + + return loop_read_exact(fd, p, n, true); +} + +void initialize_srand(void) { + static bool srand_called = false; + unsigned x; +#ifdef HAVE_SYS_AUXV_H + void *auxv; +#endif + + if (srand_called) + return; + + x = 0; + +#ifdef HAVE_SYS_AUXV_H + /* The kernel provides us with a bit of entropy in auxv, so + * let's try to make use of that to seed the pseudo-random + * generator. It's better than nothing... */ + + auxv = (void*) getauxval(AT_RANDOM); + if (auxv) + x ^= *(unsigned*) auxv; +#endif + + x ^= (unsigned) now(CLOCK_REALTIME); + x ^= (unsigned) gettid(); + + srand(x); + srand_called = true; +} + +void random_bytes(void *p, size_t n) { + uint8_t *q; + int r; + + r = dev_urandom(p, n); + if (r >= 0) + return; + + /* If some idiot made /dev/urandom unavailable to us, he'll + * get a PRNG instead. */ + + initialize_srand(); + + for (q = p; q < (uint8_t*) p + n; q ++) + *q = rand(); +} diff --git a/src/shared/random-util.h b/src/shared/random-util.h new file mode 100644 index 00000000000..f7862c8c8b5 --- /dev/null +++ b/src/shared/random-util.h @@ -0,0 +1,38 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +int dev_urandom(void *p, size_t n); +void random_bytes(void *p, size_t n); +void initialize_srand(void); + +static inline uint64_t random_u64(void) { + uint64_t u; + random_bytes(&u, sizeof(u)); + return u; +} + +static inline uint32_t random_u32(void) { + uint32_t u; + random_bytes(&u, sizeof(u)); + return u; +} diff --git a/src/shared/util.c b/src/shared/util.c index d4753f1ee87..e4c4dd92f13 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -94,6 +94,7 @@ #include "sparse-endian.h" #include "formats-util.h" #include "process-util.h" +#include "random-util.h" /* Put this test here for a lack of better place */ assert_cc(EAGAIN == EWOULDBLOCK); @@ -2387,101 +2388,6 @@ char* dirname_malloc(const char *path) { return dir; } -int dev_urandom(void *p, size_t n) { - static int have_syscall = -1; - - _cleanup_close_ int fd = -1; - int r; - - /* Gathers some randomness from the kernel. This call will - * never block, and will always return some data from the - * kernel, regardless if the random pool is fully initialized - * or not. It thus makes no guarantee for the quality of the - * returned entropy, but is good enough for or usual usecases - * of seeding the hash functions for hashtable */ - - /* Use the getrandom() syscall unless we know we don't have - * it, or when the requested size is too large for it. */ - if (have_syscall != 0 || (size_t) (int) n != n) { - r = getrandom(p, n, GRND_NONBLOCK); - if (r == (int) n) { - have_syscall = true; - return 0; - } - - if (r < 0) { - if (errno == ENOSYS) - /* we lack the syscall, continue with - * reading from /dev/urandom */ - have_syscall = false; - else if (errno == EAGAIN) - /* not enough entropy for now. Let's - * remember to use the syscall the - * next time, again, but also read - * from /dev/urandom for now, which - * doesn't care about the current - * amount of entropy. */ - have_syscall = true; - else - return -errno; - } else - /* too short read? */ - return -ENODATA; - } - - fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0) - return errno == ENOENT ? -ENOSYS : -errno; - - return loop_read_exact(fd, p, n, true); -} - -void initialize_srand(void) { - static bool srand_called = false; - unsigned x; -#ifdef HAVE_SYS_AUXV_H - void *auxv; -#endif - - if (srand_called) - return; - - x = 0; - -#ifdef HAVE_SYS_AUXV_H - /* The kernel provides us with a bit of entropy in auxv, so - * let's try to make use of that to seed the pseudo-random - * generator. It's better than nothing... */ - - auxv = (void*) getauxval(AT_RANDOM); - if (auxv) - x ^= *(unsigned*) auxv; -#endif - - x ^= (unsigned) now(CLOCK_REALTIME); - x ^= (unsigned) gettid(); - - srand(x); - srand_called = true; -} - -void random_bytes(void *p, size_t n) { - uint8_t *q; - int r; - - r = dev_urandom(p, n); - if (r >= 0) - return; - - /* If some idiot made /dev/urandom unavailable to us, he'll - * get a PRNG instead. */ - - initialize_srand(); - - for (q = p; q < (uint8_t*) p + n; q ++) - *q = rand(); -} - void rename_process(const char name[8]) { assert(name); diff --git a/src/shared/util.h b/src/shared/util.h index b939d7f67ee..4d5162f4ca1 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -283,22 +283,6 @@ int make_stdio(int fd); int make_null_stdio(void); int make_console_stdio(void); -int dev_urandom(void *p, size_t n); -void random_bytes(void *p, size_t n); -void initialize_srand(void); - -static inline uint64_t random_u64(void) { - uint64_t u; - random_bytes(&u, sizeof(u)); - return u; -} - -static inline uint32_t random_u32(void) { - uint32_t u; - random_bytes(&u, sizeof(u)); - return u; -} - /* For basic lookup tables with strictly enumerated entries */ #define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ scope const char *name##_to_string(type i) { \ diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c index 54a50756a8d..3d74ae50f1b 100644 --- a/src/udev/cdrom_id/cdrom_id.c +++ b/src/udev/cdrom_id/cdrom_id.c @@ -36,6 +36,7 @@ #include "libudev.h" #include "libudev-private.h" +#include "random-util.h" /* device info */ static unsigned int cd_cd_rom; diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 86d09bbff21..00052dd8c18 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -37,6 +37,7 @@ #include "conf-files.h" #include "rtnl-util.h" #include "network-internal.h" +#include "random-util.h" struct link_config_ctx { LIST_HEAD(link_config, links); diff --git a/src/udev/scsi_id/scsi_serial.c b/src/udev/scsi_id/scsi_serial.c index dcfff1d4ea0..3691a69d48e 100644 --- a/src/udev/scsi_id/scsi_serial.c +++ b/src/udev/scsi_id/scsi_serial.c @@ -37,6 +37,7 @@ #include "libudev-private.h" #include "scsi.h" #include "scsi_id.h" +#include "random-util.h" /* * A priority based list of id, naa, and binary/ascii for the identifier -- 2.39.2