Rather than having getrandom() be called in a loop that handles EINTR -- which would require more code bloat -- we just limit the maximum seed size to 256 bytes, which the kernel guarantees won't be interrupted. Additionally document the flock() and fsync() usage so that somebody doesn't remove it. Apparently busybox developers like to remove things they don't understand with no regards to security implications, so Denys suggested I leave some comments here.
Cc: Denys Vlasenko <vda.li...@googlemail.com> Cc: Bernhard Reutner-Fischer <rep.dot....@gmail.com> Signed-off-by: Jason A. Donenfeld <ja...@zx2c4.com> --- util-linux/seedrng.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util-linux/seedrng.c b/util-linux/seedrng.c index c42274759..5ee6197e3 100644 --- a/util-linux/seedrng.c +++ b/util-linux/seedrng.c @@ -56,7 +56,7 @@ enum { MIN_SEED_LEN = SHA256_OUTSIZE, - MAX_SEED_LEN = 512 + MAX_SEED_LEN = 256 /* Maximum size of getrandom() call without EINTR. */ }; static size_t determine_optimal_seed_len(void) @@ -142,6 +142,8 @@ static int seed_from_file_if_exists(const char *filename, int dfd, bool credit, bb_perror_msg("can't%s seed", " read"); return -1; } + /* The fsync() here is necessary for safety here, so that power being pulled + * at the wrong moment doesn't result in the seed being used twice by accident. */ if ((unlink(filename) < 0 || fsync(dfd) < 0) && seed_len) { bb_perror_msg("can't%s seed", " remove"); return -1; @@ -190,6 +192,8 @@ int seedrng_main(int argc UNUSED_PARAM, char *argv[]) if (mkdir(seed_dir, 0700) < 0 && errno != EEXIST) bb_perror_msg_and_die("can't %s seed directory", "create"); dfd = open(seed_dir, O_DIRECTORY | O_RDONLY); + /* The flock() here is absolutely necessary, as the consistency of this + * program breaks down with concurrent uses. */ if (dfd < 0 || flock(dfd, LOCK_EX) < 0) bb_perror_msg_and_die("can't %s seed directory", "lock"); xfchdir(dfd); @@ -222,6 +226,8 @@ int seedrng_main(int argc UNUSED_PARAM, char *argv[]) printf("Saving %u bits of %screditable seed for next boot\n", (unsigned)new_seed_len * 8, new_seed_creditable ? "" : "non-"); fd = open(NON_CREDITABLE_SEED_NAME, O_WRONLY | O_CREAT | O_TRUNC, 0400); + /* The fsync() here is necessary to ensure the data is written to disk before + * we attempt to make it creditable. */ if (fd < 0 || full_write(fd, new_seed, new_seed_len) != (ssize_t)new_seed_len || fsync(fd) < 0) { bb_perror_msg("can't%s seed", " write"); return program_ret | (1 << 4); -- 2.35.1 _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox