str_to_list() allocates a copy of the input string plus a pointer
array, which must be released with str_free_list(). Several error
paths return early without doing so and leak both allocations:

- distro_rauc_scan_parts() when BOOT_ORDER names an unknown slot
- distro_rauc_read_bootflow() and find_active_slot() when reading or
  writing a BOOT_*_LEFT variable fails

The scan_parts leak is the most visible one: a stray BOOT_ORDER entry
leaks the list on every scan attempt, and scans can be retried
indefinitely from the U-Boot prompt.

Free the list before each early return.

Fixes: 7e5c2c782fb9 ("bootstd: Add implementation for bootmeth rauc")
Fixes: f271b0627001 ("bootstd: rauc: Only scan all partitions instead of boot 
files")
Signed-off-by: Aristo Chen <[email protected]>
---
 boot/bootmeth_rauc.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c
index 3e76eabe2fb..12ab9fc5bbd 100644
--- a/boot/bootmeth_rauc.c
+++ b/boot/bootmeth_rauc.c
@@ -117,8 +117,10 @@ static int distro_rauc_scan_parts(struct bootflow *bflow)
                const struct distro_rauc_slot *slot;
 
                slot = get_slot(priv, boot_order_list[i]);
-               if (!slot)
+               if (!slot) {
+                       str_free_list(boot_order_list);
                        return log_msg_ret("slot", -EINVAL);
+               }
                if (desc) {
                        ret = fs_set_blk_dev_with_part(desc, slot->boot_part);
                        if (ret)
@@ -167,8 +169,10 @@ static int distro_rauc_read_bootflow(struct udevice *dev, 
struct bootflow *bflow
                if (!env_get(boot_left)) {
                        log_debug("%s did not exist yet, setting default 
value\n",
                                  boot_left);
-                       if (env_set_ulong(boot_left, 
CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES))
+                       if (env_set_ulong(boot_left, 
CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES)) {
+                               str_free_list(default_boot_order_list);
                                return log_msg_ret("env", -EPERM);
+                       }
                }
        }
        str_free_list(default_boot_order_list);
@@ -324,13 +328,17 @@ static int find_active_slot(char **slot_name, ulong 
*slot_tries)
        for (i = 0; boot_order_list[i] && !slot_found; i++) {
                sprintf(boot_left, "BOOT_%s_LEFT", boot_order_list[i]);
                tries = env_get_ulong(boot_left, 10, ULONG_MAX);
-               if (tries == ULONG_MAX)
+               if (tries == ULONG_MAX) {
+                       str_free_list(boot_order_list);
                        return log_msg_ret("env", -ENOENT);
+               }
 
                if (tries) {
                        ret = env_set_ulong(boot_left, tries - 1);
-                       if (ret)
+                       if (ret) {
+                               str_free_list(boot_order_list);
                                return log_msg_ret("env", ret);
+                       }
                        *slot_name = strdup(boot_order_list[i]);
                        *slot_tries = tries;
                        slot_found = true;
@@ -346,8 +354,10 @@ static int find_active_slot(char **slot_name, ulong 
*slot_tries)
                        for (i = 0; boot_order_list[i]; i++) {
                                sprintf(boot_left, "BOOT_%s_LEFT", 
boot_order_list[i]);
                                ret = env_set_ulong(boot_left, 
CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES);
-                               if (ret)
+                               if (ret) {
+                                       str_free_list(boot_order_list);
                                        return log_msg_ret("env", ret);
+                               }
                        }
                        str_free_list(boot_order_list);
                        ret = env_save();
-- 
2.43.0

Reply via email to