distro_rauc_boot() deep-frees the private data once the boot script
has been loaded and run, but leaves bflow->bootmeth_priv pointing at
the freed memory. The bootflow being booted is the one stored in the
bootstd list, so if the boot script returns (bootflow_boot() treats
this as an error), the stale pointer is kept and bootflow_free()
frees it a second time when the bootflow is removed, for example by
the next 'bootflow scan'.

Clear bflow->bootmeth_priv after freeing, as the scan error path
does. Also check priv before using it, like the other users of
bootmeth_priv in this file: after a failed boot attempt, a retry now
finds bootmeth_priv NULL and must not hand it to get_slot(), which
would dereference it.

Fixes: 498e423457a0 ("bootstd: rauc: Free private data when booting")
Signed-off-by: Aristo Chen <[email protected]>
---
 boot/bootmeth_rauc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c
index 2df141f7424..844df7576bb 100644
--- a/boot/bootmeth_rauc.c
+++ b/boot/bootmeth_rauc.c
@@ -398,6 +398,8 @@ static int distro_rauc_boot(struct udevice *dev, struct 
bootflow *bflow)
        if (desc->uclass_id != UCLASS_MMC)
                return log_msg_ret("blk", -EINVAL);
        priv = bflow->bootmeth_priv;
+       if (!priv || !priv->slots)
+               return log_msg_ret("priv", -EINVAL);
 
        /* Device info variables */
        ret = env_set("devtype", blk_get_devtype(bflow->blk));
@@ -464,6 +466,7 @@ static int distro_rauc_boot(struct udevice *dev, struct 
bootflow *bflow)
                return log_msg_ret("boot", ret);
 
        distro_rauc_priv_free(priv);
+       bflow->bootmeth_priv = NULL;
 
        return 0;
 }
-- 
2.43.0

Reply via email to