priv->slots is a NULL-terminated array of pointers, but get_slot()
tests priv->slots[i]->name in its loop condition, dereferencing each
entry before checking it against NULL. When slot_name does not match
any configured slot, the loop reaches the terminator and dereferences
a NULL pointer.
This is reachable from the BOOT_ORDER environment variable: an entry
naming a slot that is not listed in CONFIG_BOOTMETH_RAUC_PARTITIONS
crashes U-Boot in distro_rauc_scan_parts() or distro_rauc_boot().
Since BOOT_ORDER is typically stored in a disk-resident environment
written by the OS, a stray or corrupted value must not crash the
bootloader.
Test the array entry itself before using its name, as
distro_rauc_priv_free() already does. Both callers already handle a
NULL return.
Extend the bootflow_rauc test to scan with a BOOT_ORDER naming an
unconfigured slot. Without this fix the test crashes with SIGSEGV.
Fixes: 7e5c2c782fb9 ("bootstd: Add implementation for bootmeth rauc")
Signed-off-by: Aristo Chen <[email protected]>
---
boot/bootmeth_rauc.c | 2 +-
test/boot/bootflow.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c
index d7b0c686ffe..32be641ab54 100644
--- a/boot/bootmeth_rauc.c
+++ b/boot/bootmeth_rauc.c
@@ -71,7 +71,7 @@ static struct distro_rauc_slot *get_slot(struct
distro_rauc_priv *priv,
{
int i;
- for (i = 0; priv->slots[i]->name; i++) {
+ for (i = 0; priv->slots[i]; i++) {
if (!strcmp(priv->slots[i]->name, slot_name))
return priv->slots[i];
}
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 1cc137c9700..837c5a7a4aa 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -1444,6 +1444,22 @@ static int bootflow_rauc(struct unit_test_state *uts)
ut_assert_console_end();
+ /*
+ * Scan with a BOOT_ORDER naming a slot that has no configured
+ * partitions. get_slot() must not crash on the NULL array terminator;
+ * the bootflow just becomes invalid.
+ */
+ ut_assertok(env_set("BOOT_ORDER", "A B rescue"));
+ ut_assertok(run_command("bootflow scan", 0));
+ ut_assert_nextline("No bootflows found; try again with -l");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("bootflow list", 0));
+ ut_assert_skip_to_line("(0 bootflows, 0 valid)");
+ ut_assert_console_end();
+
+ ut_assertok(env_set("BOOT_ORDER", "A B"));
+
/* Restore the order used by the device tree */
std->bootdev_order = old_order;
--
2.43.0