[PATCH v1 2/7] bootstd: rauc: Clear bootmeth_priv after freeing it on error

Aristo Chen via U-Boot <[email protected]>
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <20260813155617.184928-3-aristo.chen__33618.3685156115$1786643972$gmane$org@canonical.com>
distro_rauc_read_bootflow() stores priv in bflow->bootmeth_priv before
calling distro_rauc_scan_parts(). If the scan fails, the error path
frees priv via distro_rauc_priv_free() but leaves bflow->bootmeth_priv
pointing at the freed memory.

With 'bootflow scan -a', failed bootflows are stored in the bootstd
list, so the stale pointer is kept. The next scan (or any other
bootflow removal) calls bootflow_free(), which frees bootmeth_priv
again. On sandbox, dlmalloc catches the double free:

  common/dlmalloc.c:816: do_check_inuse_chunk: Assertion `inuse(p)' failed.

The scan can fail this way whenever no slot has a valid filesystem, or
when BOOT_ORDER names an unknown slot.

Clear bflow->bootmeth_priv after freeing, as bootmeth_android already
does. Extend the bootflow_rauc test to run a failing scan with -a and
then rescan.

Fixes: 284855320282 ("bootstd: rauc: Free memory during error handling")
Signed-off-by: Aristo Chen <[email protected]>
---
 boot/bootmeth_rauc.c |  1 +
 test/boot/bootflow.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c
index 32be641ab54..3e76eabe2fb 100644
--- a/boot/bootmeth_rauc.c
+++ b/boot/bootmeth_rauc.c
@@ -239,6 +239,7 @@ static int distro_rauc_read_bootflow(struct udevice *dev, struct bootflow *bflow
 
 rauc_read_bootflow_err:
 	distro_rauc_priv_free(priv);
+	bflow->bootmeth_priv = NULL;
 	free(boot_order_copy);
 	free(partitions);
 
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 837c5a7a4aa..8fa8835c20c 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -1458,6 +1458,19 @@ static int bootflow_rauc(struct unit_test_state *uts)
 	ut_assert_skip_to_line("(0 bootflows, 0 valid)");
 	ut_assert_console_end();
 
+	/*
+	 * A failed scan with -a stores the failed bootflows; the next scan
+	 * removes them, freeing bootmeth_priv. This used to double free the
+	 * RAUC private data.
+	 */
+	ut_assertok(run_command("bootflow scan -a", 0));
+	ut_assert_nextline("No bootflows found; try again with -l");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow scan", 0));
+	ut_assert_nextline("No bootflows found; try again with -l");
+	ut_assert_console_end();
+
 	ut_assertok(env_set("BOOT_ORDER", "A B"));
 
 	/* Restore the order used by the device tree */
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.