From: Frieder Schrempf <[email protected]>
find_active_slot() returns a strdup() copy of the slot name, which
distro_rauc_boot() never frees, so every boot attempt leaks it. The
strdup() result is not checked either and if it fails, get_slot() passes
NULL to strcmp().
The copy is only used to look up the slot. Pass the private data to
find_active_slot() and look up the slot there, while the boot order list
is still valid, and return the slot instead of its name. This drops the
copy altogether. It also catches a BOOT_ORDER entry without a matching
slot before its BOOT_x_LEFT counter is decremented.
Fixes: 7e5c2c782fb9 ("bootstd: Add implementation for bootmeth rauc")
Assisted-by: LLM
Signed-off-by: Frieder Schrempf <[email protected]>
---
Changes in v2:
- Look up the slot in find_active_slot() and return it instead of a
strdup() copy of its name (Simon)
- Update the commit message accordingly
---
boot/bootmeth_rauc.c | 47 +++++++++++++++++++++++------------------------
1 file changed, 23 insertions(+), 24 deletions(-)
diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c
index 4a3f05103eb..7273156c4dd 100644
--- a/boot/bootmeth_rauc.c
+++ b/boot/bootmeth_rauc.c
@@ -19,6 +19,7 @@
#include <mapmem.h>
#include <part.h>
#include <string.h>
+#include <linux/err.h>
#include <linux/stringify.h>
#include <asm/cache.h>
@@ -318,42 +319,46 @@ static int distro_rauc_load_boot_script(struct bootflow
*bflow,
return 0;
}
-static int find_active_slot(char **slot_name, ulong *slot_tries)
+static const struct distro_rauc_slot *find_active_slot(struct distro_rauc_priv
*priv,
+ ulong *slot_tries)
{
ulong tries;
char boot_left[BOOT_LEFT_LEN];
char *boot_order;
+ const struct distro_rauc_slot *slot = NULL;
const char **boot_order_list;
- bool slot_found = false;
int ret;
int i;
boot_order = env_get("BOOT_ORDER");
if (!boot_order)
- return log_msg_ret("env", -ENOENT);
+ return ERR_PTR(log_msg_ret("env", -ENOENT));
boot_order_list = str_to_list(boot_order);
- for (i = 0; boot_order_list[i] && !slot_found; i++) {
+ for (i = 0; boot_order_list[i] && !slot; i++) {
sprintf(boot_left, "BOOT_%s_LEFT", boot_order_list[i]);
tries = env_get_ulong(boot_left, 10, ULONG_MAX);
if (tries == ULONG_MAX) {
str_free_list(boot_order_list);
- return log_msg_ret("env", -ENOENT);
+ return ERR_PTR(log_msg_ret("env", -ENOENT));
}
if (tries) {
+ slot = get_slot(priv, boot_order_list[i]);
+ if (!slot) {
+ str_free_list(boot_order_list);
+ return ERR_PTR(log_msg_ret("slot", -ENOENT));
+ }
ret = env_set_ulong(boot_left, tries - 1);
if (ret) {
str_free_list(boot_order_list);
- return log_msg_ret("env", ret);
+ return ERR_PTR(log_msg_ret("env", ret));
}
- *slot_name = strdup(boot_order_list[i]);
*slot_tries = tries;
- slot_found = true;
}
}
str_free_list(boot_order_list);
- if (!slot_found) {
+ if (!slot) {
if (IS_ENABLED(CONFIG_BOOTMETH_RAUC_RESET_ALL_ZERO_TRIES)) {
log_warning("WARNING: No valid slot found\n");
log_info("INFO: Resetting all slot tries to "
__stringify(CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES) "\n");
@@ -363,20 +368,20 @@ static int find_active_slot(char **slot_name, ulong
*slot_tries)
ret = env_set_ulong(boot_left,
CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES);
if (ret) {
str_free_list(boot_order_list);
- return log_msg_ret("env", ret);
+ return ERR_PTR(log_msg_ret("env", ret));
}
}
str_free_list(boot_order_list);
ret = env_save();
if (ret)
- return log_msg_ret("env", ret);
+ return ERR_PTR(log_msg_ret("env", ret));
do_reset(NULL, 0, 0, NULL);
}
log_err("ERROR: No valid slot found\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
- return 0;
+ return slot;
}
static int distro_rauc_boot(struct udevice *dev, struct bootflow *bflow)
@@ -386,7 +391,6 @@ static int distro_rauc_boot(struct udevice *dev, struct
bootflow *bflow)
const struct distro_rauc_slot *slot;
char *boot_order;
const char **boot_order_list;
- char *active_slot;
ulong active_slot_tries;
char raucargs[64];
char boot_left[BOOT_LEFT_LEN];
@@ -411,20 +415,15 @@ static int distro_rauc_boot(struct udevice *dev, struct
bootflow *bflow)
return log_msg_ret("env", ret);
/* Find active, valid slot */
- ret = find_active_slot(&active_slot, &active_slot_tries);
- if (ret)
- return log_msg_ret("env", ret);
+ slot = find_active_slot(priv, &active_slot_tries);
+ if (IS_ERR(slot))
+ return log_msg_ret("env", PTR_ERR(slot));
/* Kernel command line arguments */
- sprintf(raucargs, "rauc.slot=%s", active_slot);
+ sprintf(raucargs, "rauc.slot=%s", slot->name);
ret = env_set("raucargs", raucargs);
if (ret)
return log_msg_ret("env", ret);
-
- /* Active slot info */
- slot = get_slot(priv, active_slot);
- if (!slot)
- return log_msg_ret("env", -ENOENT);
ret = env_set_hex("distro_bootpart", slot->boot_part);
if (ret)
return log_msg_ret("env", ret);
@@ -441,7 +440,7 @@ static int distro_rauc_boot(struct udevice *dev, struct
bootflow *bflow)
return log_msg_ret("load", ret);
log_info("INFO: Booting slot %s, %lu of %d tries left\n",
- active_slot, active_slot_tries,
CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES);
+ slot->name, active_slot_tries,
CONFIG_BOOTMETH_RAUC_DEFAULT_TRIES);
log_debug("devtype: %s\n", env_get("devtype"));
log_debug("devnum: %s\n", env_get("devnum"));
--
2.56.0