too), which should be safe even with FAT file system drivers built into
low-quality EFI firmwares.
+ If the random seed file has the read-only FAT file attribute set, or if the
+ ESP file system is read-only as a whole, the seed is neither updated nor
+ used: a seed that cannot be updated would be identical on every boot, and
+ hence must not be credited. Setting the read-only file attribute on
+ `/loader/random-seed` may thus be used to explicitly turn off random seed
+ handling, for example in OS images that are replicated to multiple systems.
+
4. A kernel command line option `systemd.random_seed=` may be used to pass in a
base64 encoded seed to initialize the kernel's entropy pool from during
early service manager initialization.
<filename>/EFI/Linux/</filename> on the ESP and the Extended Boot Loader partition.</para>
<para>Optionally, a random seed for early boot entropy pool provisioning is stored in
- <filename>/loader/random-seed</filename> in the ESP.</para>
+ <filename>/loader/random-seed</filename> in the ESP. If the read-only file attribute is set on this
+ file, it is neither updated nor used: a seed that cannot be updated would be identical on every boot,
+ and hence must not be credited. The file attribute may thus be used to explicitly turn off random seed
+ handling, for example in OS images that are replicated to multiple systems.</para>
<para>During initialization, <command>systemd-boot</command> automatically loads all driver files placed
in the <filename>/EFI/systemd/drivers/</filename> directory of the ESP. The files placed there must have
/* Some basic domain separation in case somebody uses this data elsewhere */
#define HASH_LABEL "systemd-boot random seed label v1"
+#define RANDOM_SEED_PATH u"\\loader\\random-seed"
+
static EFI_STATUS acquire_rng(void *ret, size_t size) {
EFI_RNG_PROTOCOL *rng;
EFI_STATUS err;
#endif
}
+static bool random_seed_file_read_only(EFI_FILE *root_dir) {
+ _cleanup_file_close_ EFI_FILE *handle = NULL;
+ _cleanup_free_ EFI_FILE_INFO *info = NULL;
+ EFI_STATUS err;
+
+ assert(root_dir);
+
+ /* Checks whether the random seed file exists and has the read-only file attribute set. */
+
+ err = root_dir->Open(root_dir, &handle, (char16_t *) RANDOM_SEED_PATH, EFI_FILE_MODE_READ, 0);
+ if (err != EFI_SUCCESS) {
+ if (err != EFI_NOT_FOUND)
+ log_debug_status(err, "Failed to open random seed file for reading, ignoring: %m");
+ return false;
+ }
+
+ err = get_file_info(handle, &info, /* ret_size= */ NULL);
+ if (err != EFI_SUCCESS) {
+ log_debug_status(err, "Failed to get file info of random seed file, ignoring: %m");
+ return false;
+ }
+
+ return FLAGS_SET(info->Attribute, EFI_FILE_READ_ONLY);
+}
+
EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
uint8_t random_bytes[DESIRED_SEED_SIZE], hash_key[HASH_VALUE_SIZE];
_cleanup_free_ struct linux_efi_random_seed *new_seed_table = NULL;
return EFI_SUCCESS;
}
+ /* Similarly, if the random seed file is marked read-only, take this as a hint that the seed shall
+ * not be updated — and hence not be used either, since a seed we cannot update would be the same on
+ * every boot. This provides a way to explicitly turn off random seed handling, for example for
+ * pre-built OS images replicated to many systems. */
+ if (random_seed_file_read_only(root_dir))
+ goto read_only;
+
/* hash = LABEL || sizeof(input1) || input1 || ... || sizeof(inputN) || inputN */
sha256_init_ctx(&hash);
err = root_dir->Open(
root_dir,
&handle,
- (char16_t *) u"\\loader\\random-seed",
+ (char16_t *) RANDOM_SEED_PATH,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
0);
if (err == EFI_NOT_FOUND && seeded_by_efi) {
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to get file info for random seed: %m");
+ if (FLAGS_SET(info->Attribute, EFI_FILE_READ_ONLY))
+ goto read_only;
+
/* Treat a short file just like a freshly created one for robustness reasons: consider a case
* where in a previous run a file was just created and the system was then powered off. In
* such a case the file will already exist, but be too short. */
}
return EFI_SUCCESS;
+
+read_only:
+ log_debug("Random seed file is read-only, not updating random seed.");
+ return EFI_SUCCESS;
}