summaryrefslogtreecommitdiff
path: root/src/random-seed/random-seed.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/random-seed/random-seed.c')
-rw-r--r--src/random-seed/random-seed.c88
1 files changed, 55 insertions, 33 deletions
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
index 223b56306c..d25ee7d80a 100644
--- a/src/random-seed/random-seed.c
+++ b/src/random-seed/random-seed.c
@@ -15,15 +15,17 @@
#include "util.h"
#define POOL_SIZE_MIN 512
+#define POOL_SIZE_MAX (10*1024*1024)
int main(int argc, char *argv[]) {
_cleanup_close_ int seed_fd = -1, random_fd = -1;
+ bool read_seed_file, write_seed_file;
_cleanup_free_ void* buf = NULL;
size_t buf_size = 0;
+ struct stat st;
ssize_t k;
- int r, open_rw_error;
FILE *f;
- bool refresh_seed_file = true;
+ int r;
if (argc != 2) {
log_error("This program requires one argument.");
@@ -46,31 +48,25 @@ int main(int argc, char *argv[]) {
fclose(f);
}
- if (buf_size <= POOL_SIZE_MIN)
+ if (buf_size < POOL_SIZE_MIN)
buf_size = POOL_SIZE_MIN;
- buf = malloc(buf_size);
- if (!buf) {
- r = log_oom();
- goto finish;
- }
-
r = mkdir_parents_label(RANDOM_SEED, 0755);
if (r < 0) {
log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
goto finish;
}
- /* When we load the seed we read it and write it to the device
- * and then immediately update the saved seed with new data,
- * to make sure the next boot gets seeded differently. */
+ /* When we load the seed we read it and write it to the device and then immediately update the saved seed with
+ * new data, to make sure the next boot gets seeded differently. */
if (streq(argv[1], "load")) {
+ int open_rw_error;
seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
open_rw_error = -errno;
if (seed_fd < 0) {
- refresh_seed_file = false;
+ write_seed_file = false;
seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (seed_fd < 0) {
@@ -85,10 +81,13 @@ int main(int argc, char *argv[]) {
goto finish;
}
- }
+ } else
+ write_seed_file = true;
random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
if (random_fd < 0) {
+ write_seed_file = false;
+
random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600);
if (random_fd < 0) {
r = log_error_errno(errno, "Failed to open /dev/urandom: %m");
@@ -96,33 +95,24 @@ int main(int argc, char *argv[]) {
}
}
- k = loop_read(seed_fd, buf, buf_size, false);
- if (k < 0)
- r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
- else if (k == 0) {
- r = 0;
- log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
- } else {
- (void) 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");
- }
+ read_seed_file = true;
} else if (streq(argv[1], "save")) {
+ random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ if (random_fd < 0) {
+ r = log_error_errno(errno, "Failed to open /dev/urandom: %m");
+ goto finish;
+ }
+
seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
if (seed_fd < 0) {
r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
goto finish;
}
- random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (random_fd < 0) {
- r = log_error_errno(errno, "Failed to open /dev/urandom: %m");
- goto finish;
- }
+ read_seed_file = false;
+ write_seed_file = true;
} else {
log_error("Unknown verb '%s'.", argv[1]);
@@ -130,7 +120,39 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if (refresh_seed_file) {
+ if (fstat(seed_fd, &st) < 0) {
+ r = log_error_errno(errno, "Failed to stat() seed file " RANDOM_SEED ": %m");
+ goto finish;
+ }
+
+ /* If the seed file is larger than what we expect, then honour the existing size and save/restore as much as it says */
+ if ((uint64_t) st.st_size > buf_size)
+ buf_size = MIN(st.st_size, POOL_SIZE_MAX);
+
+ buf = malloc(buf_size);
+ if (!buf) {
+ r = log_oom();
+ goto finish;
+ }
+
+ if (read_seed_file) {
+
+ k = loop_read(seed_fd, buf, buf_size, false);
+ if (k < 0)
+ r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
+ else if (k == 0) {
+ r = 0;
+ log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
+ } else {
+ (void) 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 (write_seed_file) {
/* This is just a safety measure. Given that we are root and
* most likely created the file ourselves the mode and owner