@@ -361,6 +361,24 @@ static void __init efi_debugfs_init(void)
static inline void efi_debugfs_init(void) {}
#endif
+static void refresh_nv_rng_seed(struct work_struct *work)
+{
+ u8 seed[EFI_RANDOM_SEED_SIZE];
+
+ get_random_bytes(seed, sizeof(seed));
+ efi.set_variable(L"RandomSeed", &LINUX_EFI_RANDOM_SEED_TABLE_GUID,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS, sizeof(seed), seed);
+ memzero_explicit(seed, sizeof(seed));
+}
+static int refresh_nv_rng_seed_notification(struct notifier_block *nb, unsigned long action, void *data)
+{
+ static DECLARE_WORK(work, refresh_nv_rng_seed);
+ schedule_work(&work);
+ return NOTIFY_DONE;
+}
+static struct notifier_block refresh_nv_rng_seed_nb = { .notifier_call = refresh_nv_rng_seed_notification };
+
/*
* We register the efi subsystem with the firmware subsystem and the
* efivars subsystem with the efi subsystem, if the system was booted with
@@ -433,6 +451,10 @@ static int __init efisubsys_init(void)
platform_device_register_simple("efi_secret", 0, NULL, 0);
#endif
+ if (efi.runtime_version >= EFI_2_40_SYSTEM_TABLE_REVISION &&
+ efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE))
+ execute_with_initialized_rng(&refresh_nv_rng_seed_nb);
+
return 0;
err_remove_group:
@@ -462,6 +462,7 @@ typedef struct {
#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
#define EFI_DXE_SERVICES_TABLE_SIGNATURE ((u64)0x565245535f455844ULL)
+#define EFI_2_40_SYSTEM_TABLE_REVISION ((2 << 16) | (40))
#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30))
#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20))
#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10))
EFI has a rather unique benefit that it has access to some limited non-volatile storage, where the kernel can store a random seed. Register a notification for when the RNG is initialized, and at that point, store a new random seed. This was previously reverted in 69cbeb61ff90 because it caused hangs on very old EFI implementations. This time, restrict it to only modern EFIs with a more recent revision number. Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Bagas Sanjaya <bagasdotme@gmail.com> Cc: Sami Korkalainen <sami.korkalainen@proton.me> Fixes: 69cbeb61ff90 ("Revert "efi: random: refresh non-volatile random seed when RNG is initialized"") Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> --- drivers/firmware/efi/efi.c | 22 ++++++++++++++++++++++ include/linux/efi.h | 1 + 2 files changed, 23 insertions(+)