Simply writing /var/lib/systemd/random-seed back to /dev/(u)random does not increase the entropy bit count. Therefore use the RNDADDENTROPY ioctl to write back the bytes and increase the entropy bit counter. Related to bnc#892096 --- src/random-seed/random-seed.c | 65 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) Index: systemd-218/src/random-seed/random-seed.c =================================================================== --- systemd-218.orig/src/random-seed/random-seed.c +++ systemd-218/src/random-seed/random-seed.c @@ -22,7 +22,9 @@ #include #include #include +#include #include +#include #include #include "log.h" @@ -32,8 +34,9 @@ #define POOL_SIZE_MIN 512 int main(int argc, char *argv[]) { - _cleanup_close_ int seed_fd = -1, random_fd = -1; + _cleanup_close_ int seed_fd = -1, random_fd = -1, entropy_fd = -1; _cleanup_free_ void* buf = NULL; + size_t entropy_count = 0; size_t buf_size = 0; ssize_t k; int r; @@ -82,6 +85,23 @@ int main(int argc, char *argv[]) { if (streq(argv[1], "load")) { + entropy_fd = open(RANDOM_SEED_DIR "entropy_count", O_RDONLY|O_CLOEXEC|O_NOCTTY, 0600); + if (entropy_fd < 0) { + entropy_count = 0; + if (errno != ENOENT) { + log_error("Failed to open " RANDOM_SEED "/entropy_count: %m"); + r = -errno; + goto finish; + } + } else { + r = read(entropy_fd, &entropy_count, sizeof(entropy_count)); + if (r < 0) { + log_error("Failed to read entropy count file: %m"); + r = -errno; + goto finish; + } + } + seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); if (seed_fd < 0) { seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY); @@ -113,12 +133,34 @@ int main(int argc, char *argv[]) { } else { lseek(seed_fd, 0, SEEK_SET); - r = loop_write(random_fd, buf, (size_t) k, false); - if (r < 0) - log_error_errno(r, "Failed to write seed to /dev/urandom: %m"); + if (entropy_count && (size_t) k == buf_size) { + struct rand_pool_info entropy = { + .entropy_count = entropy_count, + .buf_size = buf_size, + }; + entropy.buf[0] = ((__u32*)buf)[0]; + r = ioctl(random_fd, RNDADDENTROPY, &entropy); + if (r < 0) { + log_error("Failed to write seed to /dev/urandom: %m"); + r = -errno; + } + } else { + k = loop_write(random_fd, buf, (size_t) k, false); + if (k <= 0) { + log_error("Failed to write seed to /dev/urandom: %s", r < 0 ? strerror(-r) : "short write"); + r = k == 0 ? -EIO : (int) k; + } + } } } else if (streq(argv[1], "save")) { + /* Read available entropy count, if possible */ + f = fopen("/proc/sys/kernel/random/entropy_avail", "re"); + if (f) { + if (fscanf(f, "%zu", &entropy_count) < 0) + entropy_count = 0; + fclose(f); + } seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); if (seed_fd < 0) { @@ -134,6 +176,21 @@ int main(int argc, char *argv[]) { goto finish; } + if (entropy_count) { + entropy_fd = open(RANDOM_SEED_DIR "entropy_count", O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); + if (seed_fd < 0) { + log_error("Failed to open " RANDOM_SEED_DIR "entropy_count: %m"); + r = -errno; + goto finish; + } + r = write(entropy_fd, &entropy_count, sizeof(entropy_count)); + if (r < 0) { + log_error("Failed to write entropy count file: %m"); + r = -errno; + goto finish; + } + } + } else { log_error("Unknown verb %s.", argv[1]); r = -EINVAL;