]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Jan 2023 16:53:22 +0000 (17:53 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Jan 2023 16:53:22 +0000 (17:53 +0100)
added patches:
efi-random-combine-bootloader-provided-rng-seed-with-rng-protocol-output.patch
mbcache-avoid-nesting-of-cache-c_list_lock-under-bit-locks.patch

queue-5.10/efi-random-combine-bootloader-provided-rng-seed-with-rng-protocol-output.patch [new file with mode: 0644]
queue-5.10/mbcache-avoid-nesting-of-cache-c_list_lock-under-bit-locks.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/efi-random-combine-bootloader-provided-rng-seed-with-rng-protocol-output.patch b/queue-5.10/efi-random-combine-bootloader-provided-rng-seed-with-rng-protocol-output.patch
new file mode 100644 (file)
index 0000000..2ae6a9d
--- /dev/null
@@ -0,0 +1,180 @@
+From 196dff2712ca5a2e651977bb2fe6b05474111a83 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Thu, 20 Oct 2022 10:39:10 +0200
+Subject: efi: random: combine bootloader provided RNG seed with RNG protocol output
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+commit 196dff2712ca5a2e651977bb2fe6b05474111a83 upstream.
+
+Instead of blindly creating the EFI random seed configuration table if
+the RNG protocol is implemented and works, check whether such a EFI
+configuration table was provided by an earlier boot stage and if so,
+concatenate the existing and the new seeds, leaving it up to the core
+code to mix it in and credit it the way it sees fit.
+
+This can be used for, e.g., systemd-boot, to pass an additional seed to
+Linux in a way that can be consumed by the kernel very early. In that
+case, the following definitions should be used to pass the seed to the
+EFI stub:
+
+struct linux_efi_random_seed {
+      u32     size; // of the 'seed' array in bytes
+      u8      seed[];
+};
+
+The memory for the struct must be allocated as EFI_ACPI_RECLAIM_MEMORY
+pool memory, and the address of the struct in memory should be installed
+as a EFI configuration table using the following GUID:
+
+LINUX_EFI_RANDOM_SEED_TABLE_GUID        1ce1e5bc-7ceb-42f2-81e5-8aadf180f57b
+
+Note that doing so is safe even on kernels that were built without this
+patch applied, but the seed will simply be overwritten with a seed
+derived from the EFI RNG protocol, if available. The recommended seed
+size is 32 bytes, and seeds larger than 512 bytes are considered
+corrupted and ignored entirely.
+
+In order to preserve forward secrecy, seeds from previous bootloaders
+are memzero'd out, and in order to preserve memory, those older seeds
+are also freed from memory. Freeing from memory without first memzeroing
+is not safe to do, as it's possible that nothing else will ever
+overwrite those pages used by EFI.
+
+Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
+[ardb: incorporate Jason's followup changes to extend the maximum seed
+       size on the consumer end, memzero() it and drop a needless printk]
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/firmware/efi/efi.c             |    4 +--
+ drivers/firmware/efi/libstub/efistub.h |    2 +
+ drivers/firmware/efi/libstub/random.c  |   42 ++++++++++++++++++++++++++++-----
+ include/linux/efi.h                    |    2 -
+ 4 files changed, 40 insertions(+), 10 deletions(-)
+
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -590,7 +590,7 @@ int __init efi_config_parse_tables(const
+               seed = early_memremap(efi_rng_seed, sizeof(*seed));
+               if (seed != NULL) {
+-                      size = min(seed->size, EFI_RANDOM_SEED_SIZE);
++                      size = min_t(u32, seed->size, SZ_1K); // sanity check
+                       early_memunmap(seed, sizeof(*seed));
+               } else {
+                       pr_err("Could not map UEFI random seed!\n");
+@@ -599,8 +599,8 @@ int __init efi_config_parse_tables(const
+                       seed = early_memremap(efi_rng_seed,
+                                             sizeof(*seed) + size);
+                       if (seed != NULL) {
+-                              pr_notice("seeding entropy pool\n");
+                               add_bootloader_randomness(seed->bits, size);
++                              memzero_explicit(seed->bits, size);
+                               early_memunmap(seed, sizeof(*seed) + size);
+                       } else {
+                               pr_err("Could not map UEFI random seed!\n");
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -767,6 +767,8 @@ efi_status_t efi_get_random_bytes(unsign
+ efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
+                             unsigned long *addr, unsigned long random_seed);
++efi_status_t efi_random_get_seed(void);
++
+ efi_status_t check_platform_features(void);
+ void *get_efi_config_table(efi_guid_t guid);
+--- a/drivers/firmware/efi/libstub/random.c
++++ b/drivers/firmware/efi/libstub/random.c
+@@ -67,8 +67,9 @@ efi_status_t efi_random_get_seed(void)
+       efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+       efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
+       efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
++      struct linux_efi_random_seed *prev_seed, *seed = NULL;
++      int prev_seed_size = 0, seed_size = EFI_RANDOM_SEED_SIZE;
+       efi_rng_protocol_t *rng = NULL;
+-      struct linux_efi_random_seed *seed = NULL;
+       efi_status_t status;
+       status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
+@@ -76,18 +77,33 @@ efi_status_t efi_random_get_seed(void)
+               return status;
+       /*
++       * Check whether a seed was provided by a prior boot stage. In that
++       * case, instead of overwriting it, let's create a new buffer that can
++       * hold both, and concatenate the existing and the new seeds.
++       * Note that we should read the seed size with caution, in case the
++       * table got corrupted in memory somehow.
++       */
++      prev_seed = get_efi_config_table(LINUX_EFI_RANDOM_SEED_TABLE_GUID);
++      if (prev_seed && prev_seed->size <= 512U) {
++              prev_seed_size = prev_seed->size;
++              seed_size += prev_seed_size;
++      }
++
++      /*
+        * Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the
+        * allocation will survive a kexec reboot (although we refresh the seed
+        * beforehand)
+        */
+       status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
+-                           sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
++                           struct_size(seed, bits, seed_size),
+                            (void **)&seed);
+-      if (status != EFI_SUCCESS)
+-              return status;
++      if (status != EFI_SUCCESS) {
++              efi_warn("Failed to allocate memory for RNG seed.\n");
++              goto err_warn;
++      }
+       status = efi_call_proto(rng, get_rng, &rng_algo_raw,
+-                               EFI_RANDOM_SEED_SIZE, seed->bits);
++                              EFI_RANDOM_SEED_SIZE, seed->bits);
+       if (status == EFI_UNSUPPORTED)
+               /*
+@@ -100,14 +116,28 @@ efi_status_t efi_random_get_seed(void)
+       if (status != EFI_SUCCESS)
+               goto err_freepool;
+-      seed->size = EFI_RANDOM_SEED_SIZE;
++      seed->size = seed_size;
++      if (prev_seed_size)
++              memcpy(seed->bits + EFI_RANDOM_SEED_SIZE, prev_seed->bits,
++                     prev_seed_size);
++
+       status = efi_bs_call(install_configuration_table, &rng_table_guid, seed);
+       if (status != EFI_SUCCESS)
+               goto err_freepool;
++      if (prev_seed_size) {
++              /* wipe and free the old seed if we managed to install the new one */
++              memzero_explicit(prev_seed->bits, prev_seed_size);
++              efi_bs_call(free_pool, prev_seed);
++      }
+       return EFI_SUCCESS;
+ err_freepool:
++      memzero_explicit(seed, struct_size(seed, bits, seed_size));
+       efi_bs_call(free_pool, seed);
++      efi_warn("Failed to obtain seed from EFI_RNG_PROTOCOL\n");
++err_warn:
++      if (prev_seed)
++              efi_warn("Retaining bootloader-supplied seed only");
+       return status;
+ }
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -1108,8 +1108,6 @@ void efi_check_for_embedded_firmwares(vo
+ static inline void efi_check_for_embedded_firmwares(void) { }
+ #endif
+-efi_status_t efi_random_get_seed(void);
+-
+ void efi_retrieve_tpm2_eventlog(void);
+ /*
diff --git a/queue-5.10/mbcache-avoid-nesting-of-cache-c_list_lock-under-bit-locks.patch b/queue-5.10/mbcache-avoid-nesting-of-cache-c_list_lock-under-bit-locks.patch
new file mode 100644 (file)
index 0000000..f69506f
--- /dev/null
@@ -0,0 +1,66 @@
+From 5fc4cbd9fde5d4630494fd6ffc884148fb618087 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 8 Sep 2022 11:10:32 +0200
+Subject: mbcache: Avoid nesting of cache->c_list_lock under bit locks
+
+From: Jan Kara <jack@suse.cz>
+
+commit 5fc4cbd9fde5d4630494fd6ffc884148fb618087 upstream.
+
+Commit 307af6c87937 ("mbcache: automatically delete entries from cache
+on freeing") started nesting cache->c_list_lock under the bit locks
+protecting hash buckets of the mbcache hash table in
+mb_cache_entry_create(). This causes problems for real-time kernels
+because there spinlocks are sleeping locks while bitlocks stay atomic.
+Luckily the nesting is easy to avoid by holding entry reference until
+the entry is added to the LRU list. This makes sure we cannot race with
+entry deletion.
+
+Cc: stable@kernel.org
+Fixes: 307af6c87937 ("mbcache: automatically delete entries from cache on freeing")
+Reported-by: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220908091032.10513-1-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/mbcache.c |   17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/fs/mbcache.c
++++ b/fs/mbcache.c
+@@ -90,8 +90,14 @@ int mb_cache_entry_create(struct mb_cach
+               return -ENOMEM;
+       INIT_LIST_HEAD(&entry->e_list);
+-      /* Initial hash reference */
+-      atomic_set(&entry->e_refcnt, 1);
++      /*
++       * We create entry with two references. One reference is kept by the
++       * hash table, the other reference is used to protect us from
++       * mb_cache_entry_delete_or_get() until the entry is fully setup. This
++       * avoids nesting of cache->c_list_lock into hash table bit locks which
++       * is problematic for RT.
++       */
++      atomic_set(&entry->e_refcnt, 2);
+       entry->e_key = key;
+       entry->e_value = value;
+       entry->e_flags = 0;
+@@ -107,15 +113,12 @@ int mb_cache_entry_create(struct mb_cach
+               }
+       }
+       hlist_bl_add_head(&entry->e_hash_list, head);
+-      /*
+-       * Add entry to LRU list before it can be found by
+-       * mb_cache_entry_delete() to avoid races
+-       */
++      hlist_bl_unlock(head);
+       spin_lock(&cache->c_list_lock);
+       list_add_tail(&entry->e_list, &cache->c_list);
+       cache->c_entry_count++;
+       spin_unlock(&cache->c_list_lock);
+-      hlist_bl_unlock(head);
++      mb_cache_entry_put(cache, entry);
+       return 0;
+ }
index 639f356c4735c4d70225b43c30b078047fc25397..41d596e642e14ed96b63eeb736b202b45efb6436 100644 (file)
@@ -767,3 +767,5 @@ ext4-don-t-allow-journal-inode-to-have-encrypt-flag.patch
 selftests-set-the-build-variable-to-absolute-path.patch
 hfs-hfsplus-use-warn_on-for-sanity-check.patch
 hfs-hfsplus-avoid-warn_on-for-sanity-check-use-proper-error-handling.patch
+mbcache-avoid-nesting-of-cache-c_list_lock-under-bit-locks.patch
+efi-random-combine-bootloader-provided-rng-seed-with-rng-protocol-output.patch