From: Ard Biesheuvel <ardb(a)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(a)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(a)kernel.org>
Signed-off-by: Jason A. Donenfeld <Jason(a)zx2c4.com>
---
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(-)
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a06decee51e0..a6e9968a2ddc 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -608,7 +608,7 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
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");
@@ -617,8 +617,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
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");
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index b0ae0a454404..0ce2bf4b8b58 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -873,6 +873,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
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);
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 33ab56769595..f85d2c066877 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -67,27 +67,43 @@ 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);
if (status != EFI_SUCCESS)
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;
}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index f87b2f5db9f8..4f51616f01b2 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1139,8 +1139,6 @@ void efi_check_for_embedded_firmwares(void);
static inline void efi_check_for_embedded_firmwares(void) { }
#endif
-efi_status_t efi_random_get_seed(void);
-
#define arch_efi_call_virt(p, f, args...) ((p)->f(args))
/*
--
2.39.0
The ACPI PRM address space handler calls efi_call_virt_pointer() to
execute PRM firmware code, but doing so is only permitted when the EFI
runtime environment is available. Otherwise, such calls are guaranteed
to result in a crash, and must therefore be avoided.
Cc: <stable(a)vger.kernel.org>
Cc: "Rafael J. Wysocki" <rafael(a)kernel.org>
Cc: Len Brown <lenb(a)kernel.org>
Cc: linux-acpi(a)vger.kernel.org
Signed-off-by: Ard Biesheuvel <ardb(a)kernel.org>
---
drivers/acpi/prmt.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c
index 998101cf16e47145..74f924077866ae69 100644
--- a/drivers/acpi/prmt.c
+++ b/drivers/acpi/prmt.c
@@ -236,6 +236,11 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
efi_status_t status;
struct prm_context_buffer context;
+ if (!efi_enabled(EFI_RUNTIME_SERVICES)) {
+ pr_err("PRM: EFI runtime services unavailable\n");
+ return AE_NOT_IMPLEMENTED;
+ }
+
/*
* The returned acpi_status will always be AE_OK. Error values will be
* saved in the first byte of the PRM message buffer to be used by ASL.
--
2.39.0
commit 27c0d217340e47ec995557f61423ef415afba987 upstream.
When a driver registers with a bus, it will attempt to match with every
device on the bus through the __driver_attach() function. Currently, if
the bus_type.match() function encounters an error that is not
-EPROBE_DEFER, __driver_attach() will return a negative error code, which
causes the driver registration logic to stop trying to match with the
remaining devices on the bus.
This behavior is not correct; a failure while matching a driver to a
device does not mean that the driver won't be able to match and bind
with other devices on the bus. Update the logic in __driver_attach()
to reflect this.
Fixes: 656b8035b0ee ("ARM: 8524/1: driver cohandle -EPROBE_DEFER from bus_type.match()")
Cc: stable(a)vger.kernel.org
Cc: Saravana Kannan <saravanak(a)google.com>
Signed-off-by: Isaac J. Manjarres <isaacmanjarres(a)google.com>
---
drivers/base/dd.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a7bcbb99e820..0f006cad2be7 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -785,8 +785,12 @@ static int __driver_attach(struct device *dev, void *data)
*/
return 0;
} else if (ret < 0) {
- dev_dbg(dev, "Bus failed to match device: %d", ret);
- return ret;
+ dev_dbg(dev, "Bus failed to match device: %d\n", ret);
+ /*
+ * Driver could not match with device, but may match with
+ * another device on the bus.
+ */
+ return 0;
} /* ret > 0 means positive match */
if (dev->parent) /* Needed for USB */
--
2.39.0.314.g84b9a713c41-goog
Greg -
Here are backports of the MPTCP patches, and one prerequisite, that
recently failed to apply to the 5.10 stable tree. They prevent IPv6
memory leaks with MPTCP.
Thanks!
Florian Westphal (1):
mptcp: mark ops structures as ro_after_init
Matthieu Baerts (3):
mptcp: remove MPTCP 'ifdef' in TCP SYN cookies
mptcp: dedicated request sock for subflow in v6
mptcp: use proper req destructor for IPv6
include/net/mptcp.h | 12 +++++--
net/ipv4/syncookies.c | 7 ++--
net/mptcp/subflow.c | 76 +++++++++++++++++++++++++++++++++----------
3 files changed, 71 insertions(+), 24 deletions(-)
--
2.39.0
From: "Tyler Hicks" <code(a)tyhicks.com>
When attempting to build kselftests with a separate output directory, a
number of the tests fail to build.
For example,
$ rm -rf build && \
make INSTALL_HDR_PATH=build/usr headers_install > /dev/null && \
make O=build FORCE_TARGETS=1 TARGETS=breakpoints -C tools/testing/selftests > /dev/null
/usr/bin/ld: cannot open output file
build/kselftest/breakpoints/step_after_suspend_test: No such file or directory
collect2: error: ld returned 1 exit status
make[1]: *** [../lib.mk:146: build/kselftest/breakpoints/step_after_suspend_test] Error 1
make: *** [Makefile:163: all] Error 2
This has already been addressed upstream with v5.18 commit 5ad51ab618de
("selftests: set the BUILD variable to absolute path"). It does not
cleanly cherry pick to the linux-5.4.y branch without v5.7 commit
29e911ef7b70 ("selftests: Fix kselftest O=objdir build from cluttering
top level objdir"). Commit 5ad51ab618de was written in a way that
assumes that the kselftests aren't build in the top level objdir so it
makes sense to bring the pre-req commit back but it does represent a
slight change in behavior since the kselftests will now be built in a
subdir of the specified objdir (O=).
Tyler
Muhammad Usama Anjum (1):
selftests: set the BUILD variable to absolute path
Shuah Khan (1):
selftests: Fix kselftest O=objdir build from cluttering top level
objdir
tools/testing/selftests/Makefile | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
--
2.34.1
From: Indan Zupancic <Indan.Zupancic(a)mep-info.com>
[ Upstream commit 401fb66a355eb0f22096cf26864324f8e63c7d78 ]
If an irq is pending when devm_request_irq() is called, the irq
handler will cause a NULL pointer access because initialisation
is not done yet.
Fixes: 9d7ee0e28da59 ("tty: serial: lpuart: avoid report NULL interrupt")
Cc: stable <stable(a)vger.kernel.org>
Signed-off-by: Indan Zupancic <Indan.Zupancic(a)mep-info.com>
Link: https://lore.kernel.org/r/20220505114750.45423-1-Indan.Zupancic@mep-info.com
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
[5.10 did not have lpuart_global_reset or anything after
uart_add_one_port(), so add the remove call in cleanup manually]
Signed-off-by: Dominique Martinet <dominique.martinet(a)atmark-techno.com>
---
This was originally intended as a prerequirement to backport the patch
submitted in [1] for 5.10, but even with that part of the patch gone it
makes sense as a fix on its own.
[1] https://lkml.kernel.org/r/20221222114414.1886632-1-linux@rasmusvillemoes.dk
drivers/tty/serial/fsl_lpuart.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 43aca5a2ef0f..223695947b65 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2586,6 +2586,7 @@ static int lpuart_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct lpuart_port *sport;
struct resource *res;
+ irq_handler_t handler;
int ret;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
@@ -2658,17 +2659,12 @@ static int lpuart_probe(struct platform_device *pdev)
if (lpuart_is_32(sport)) {
lpuart_reg.cons = LPUART32_CONSOLE;
- ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0,
- DRIVER_NAME, sport);
+ handler = lpuart32_int;
} else {
lpuart_reg.cons = LPUART_CONSOLE;
- ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0,
- DRIVER_NAME, sport);
+ handler = lpuart_int;
}
- if (ret)
- goto failed_irq_request;
-
ret = uart_get_rs485_mode(&sport->port);
if (ret)
goto failed_get_rs485;
@@ -2684,11 +2680,17 @@ static int lpuart_probe(struct platform_device *pdev)
if (ret)
goto failed_attach_port;
+ ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0,
+ DRIVER_NAME, sport);
+ if (ret)
+ goto failed_irq_request;
+
return 0;
+failed_irq_request:
+ uart_remove_one_port(&lpuart_reg, &sport->port);
failed_get_rs485:
failed_attach_port:
-failed_irq_request:
lpuart_disable_clks(sport);
return ret;
}
--
2.35.1
When 7c7f9bc986e6 ("serial: Deassert Transmit Enable on probe in
driver-specific way") got backported to 5.15.y, there known as
b079d3775237, this hunk was accidentally left out. So if the "goto
failed_get_rs485;" is hit, the cleanup will do uart_remove_one_port()
despite uart_add_one_port() not having been called.
Add the missing hunk.
Fixes: b079d3775237 ("serial: Deassert Transmit Enable on probe in driver-specific way")
Signed-off-by: Rasmus Villemoes <linux(a)rasmusvillemoes.dk>
---
Not quite sure how to submit patches for a specific -stable series
only, or if the Fixes tag is appropriate and correct. Please let me
know if you'd have preferred anything different.
drivers/tty/serial/fsl_lpuart.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 595430aedc0d..fc311df9f1c9 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2784,9 +2784,9 @@ static int lpuart_probe(struct platform_device *pdev)
return 0;
failed_irq_request:
-failed_get_rs485:
uart_remove_one_port(&lpuart_reg, &sport->port);
failed_attach_port:
+failed_get_rs485:
failed_reset:
lpuart_disable_clks(sport);
return ret;
base-commit: fd6d66840b4269da4e90e1ea807ae3197433bc66
--
2.37.2
The recent ext4 fast-commit fixes with 'Cc stable' didn't apply to 5.10
due to conflicts. Since the fast-commit support in 5.10 is rudimentary
and hard to backport fixes too, this series backports the two most
important fixes only. Please apply to 5.10-stable.
Eric Biggers (2):
ext4: disable fast-commit of encrypted dir operations
ext4: don't set up encryption key during jbd2 transaction
fs/ext4/ext4.h | 4 ++--
fs/ext4/fast_commit.c | 42 +++++++++++++++++++++--------------
fs/ext4/fast_commit.h | 1 +
fs/ext4/namei.c | 44 ++++++++++++++++++++-----------------
include/trace/events/ext4.h | 7 ++++--
5 files changed, 57 insertions(+), 41 deletions(-)
--
2.39.0