#include "alloc-util.h"
#include "build.h"
-#include "chase-symlinks.h"
-#include "efi-loader.h"
#include "fd-util.h"
-#include "find-esp.h"
#include "fs-util.h"
#include "io-util.h"
#include "log.h"
#include "missing_random.h"
#include "missing_syscall.h"
#include "mkdir.h"
-#include "parse-argument.h"
#include "parse-util.h"
-#include "path-util.h"
#include "pretty-print.h"
#include "random-util.h"
#include "string-table.h"
#include "string-util.h"
-#include "strv.h"
#include "sync-util.h"
#include "sha256.h"
-#include "terminal-util.h"
#include "xattr-util.h"
typedef enum SeedAction {
}
/* Don't credit the random seed if we are in first-boot mode, because we are supposed to start from
- * scratch. This is a safety precaution for cases where we people ship "golden" images with empty
+ * scratch. This is a safety precaution for cases where people ship "golden" images with empty
* /etc but populated /var that contains a random seed. */
r = RET_NERRNO(access("/run/systemd/first-boot", F_OK));
if (r == -ENOENT)
return log_oom();
sha256_init_ctx(hash_state);
- sha256_process_bytes(&k, sizeof(k), hash_state); /* Hash length to distinguish from new seed. */
- sha256_process_bytes(buf, k, hash_state);
+ sha256_process_bytes_and_size(buf, k, hash_state); /* Hash with length to distinguish from new seed. */
*ret_hash_state = hash_state;
}
if (hash_state) {
uint8_t hash[SHA256_DIGEST_SIZE];
- sha256_process_bytes(&k, sizeof(k), hash_state); /* Hash length to distinguish from old seed. */
- sha256_process_bytes(buf, k, hash_state);
+ sha256_process_bytes_and_size(buf, k, hash_state); /* Hash with length to distinguish from old seed. */
sha256_finish_ctx(hash_state, hash);
l = MIN((size_t)k, sizeof(hash));
memcpy((uint8_t *)buf + k - l, hash, l);
}
- r = loop_write(seed_fd, buf, (size_t) k, false);
+ r = loop_write(seed_fd, buf, (size_t) k);
if (r < 0)
return log_error_errno(r, "Failed to write new random seed file: %m");
return 0;
}
-static int refresh_boot_seed(void) {
- uint8_t buffer[RANDOM_EFI_SEED_SIZE];
- struct sha256_ctx hash_state;
- _cleanup_free_ void *seed_file_bytes = NULL;
- _cleanup_free_ char *esp_path = NULL;
- _cleanup_close_ int seed_fd = -1;
- size_t len;
- ssize_t r;
-
- assert_cc(RANDOM_EFI_SEED_SIZE == SHA256_DIGEST_SIZE);
-
- r = find_esp_and_warn(NULL, NULL, /* unprivileged_mode= */ false, &esp_path,
- NULL, NULL, NULL, NULL, NULL);
- if (r < 0) {
- if (r == -ENOKEY) {
- log_debug_errno(r, "Couldn't find any ESP, so not updating ESP random seed.");
- return 0;
- }
- return r; /* find_esp_and_warn() already logged */
- }
-
- seed_fd = chase_symlinks_and_open("/loader/random-seed", esp_path,
- CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS,
- O_RDWR|O_CLOEXEC|O_NOCTTY, NULL);
- if (seed_fd == -ENOENT) {
- uint64_t features;
-
- r = efi_loader_get_features(&features);
- if (r == 0 && FLAGS_SET(features, EFI_LOADER_FEATURE_RANDOM_SEED)) {
- int dir_fd = chase_symlinks_and_open("/loader", esp_path,
- CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS,
- O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL);
- if (dir_fd >= 0) {
- seed_fd = openat(dir_fd, "random-seed", O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
- close(dir_fd);
- }
- }
- }
- if (seed_fd < 0) {
- log_debug_errno(seed_fd, "Failed to open EFI seed path: %m");
- return 0;
- }
- r = random_seed_size(seed_fd, &len);
- if (r < 0)
- return log_error_errno(r, "Failed to determine EFI seed path length: %m");
- seed_file_bytes = malloc(len);
- if (!seed_file_bytes)
- return log_oom();
- r = loop_read(seed_fd, seed_file_bytes, len, false);
- if (r < 0)
- return log_error_errno(r, "Failed to read EFI seed file: %m");
-
- /* Hash the old seed in so that we never regress in entropy. */
- sha256_init_ctx(&hash_state);
- sha256_process_bytes(&r, sizeof(r), &hash_state);
- sha256_process_bytes(seed_file_bytes, r, &hash_state);
-
- /* We're doing this opportunistically, so if the seeding dance before didn't manage to initialize the
- * RNG, there's no point in doing it here. Secondly, getrandom(GRND_NONBLOCK) has been around longer
- * than EFI seeding anyway, so there's no point in having non-getrandom() fallbacks here. So if this
- * fails, just return early to cut our losses. */
- r = getrandom(buffer, sizeof(buffer), GRND_NONBLOCK);
- if (r < 0) {
- if (errno == EAGAIN) {
- log_debug_errno(errno, "Random pool not initialized yet, so skipping EFI seed update");
- return 0;
- }
- if (errno == ENOSYS) {
- log_debug_errno(errno, "getrandom() not available, so skipping EFI seed update");
- return 0;
- }
- return log_error_errno(errno, "Failed to generate random bytes for EFI seed: %m");
- }
- assert(r == sizeof(buffer));
-
- /* Hash the new seed into the state containing the old one to generate our final seed. */
- sha256_process_bytes(&r, sizeof(r), &hash_state);
- sha256_process_bytes(buffer, r, &hash_state);
- sha256_finish_ctx(&hash_state, buffer);
-
- if (lseek(seed_fd, 0, SEEK_SET) < 0)
- return log_error_errno(errno, "Failed to seek to beginning of EFI seed file: %m");
- r = loop_write(seed_fd, buffer, sizeof(buffer), false);
- if (r < 0)
- return log_error_errno(r, "Failed to write new EFI seed file: %m");
- if (ftruncate(seed_fd, sizeof(buffer)) < 0)
- return log_error_errno(errno, "Failed to truncate EFI seed file: %m");
- r = fsync_full(seed_fd);
- if (r < 0)
- return log_error_errno(errno, "Failed to fsync EFI seed file: %m");
-
- log_debug("Updated random seed in ESP");
- return 0;
-}
-
static int help(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *link = NULL;
int r;
static int run(int argc, char *argv[]) {
_cleanup_free_ struct sha256_ctx *hash_state = NULL;
- _cleanup_close_ int seed_fd = -1, random_fd = -1;
+ _cleanup_close_ int seed_fd = -EBADF, random_fd = -EBADF;
bool read_seed_file, write_seed_file, synchronous;
size_t seed_size;
int r;
log_full_errno(level, open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m");
log_full_errno(level, errno, "Failed to open " RANDOM_SEED " for reading: %m");
- r = -errno;
-
- (void) refresh_boot_seed();
- return missing ? 0 : r;
+ return missing ? 0 : -errno;
}
} else
write_seed_file = true;
break;
case ACTION_SAVE:
- (void) refresh_boot_seed();
seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
if (seed_fd < 0)
return log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
if (r < 0)
return r;
- if (read_seed_file) {
+ if (read_seed_file)
r = load_seed_file(seed_fd, random_fd, seed_size,
write_seed_file ? &hash_state : NULL);
- (void) refresh_boot_seed();
- }
if (r >= 0 && write_seed_file)
r = save_seed_file(seed_fd, random_fd, seed_size, synchronous, hash_state);