* [PATCH 0/4] boot: UAF and double free fixes
@ 2026-10-30 7:34 Sascha Hauer
2026-10-30 7:34 ` [PATCH 1/4] boot: fix use-after-free when restoring bootm variables Sascha Hauer
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Sascha Hauer @ 2026-10-30 7:34 UTC (permalink / raw)
To: BAREBOX
This fixes some Use after free and double free cases. Also bring back the
information that the kernel image can be overriden to the boot help text.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Sascha Hauer (4):
boot: fix use-after-free when restoring bootm variables
bootargs: fix double free in linux_bootargs_get()
commands: boot: fix use-after-free of overrides taken from globalvars
commands: boot: list bootm.image in the -o help text again
commands/boot.c | 40 +++++++++++++++++++++++++++++++---------
common/boot.c | 17 +++++++++++++++++
common/bootargs.c | 1 +
3 files changed, 49 insertions(+), 9 deletions(-)
---
base-commit: f2e574b9c63c6da07a06179a868cae8a471ec176
change-id: 20261030-boot-mem-fixes-e19012a6b82d
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4] boot: fix use-after-free when restoring bootm variables
2026-10-30 7:34 [PATCH 0/4] boot: UAF and double free fixes Sascha Hauer
@ 2026-10-30 7:34 ` Sascha Hauer
2026-10-30 7:34 ` [PATCH 2/4] bootargs: fix double free in linux_bootargs_get() Sascha Hauer
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2026-10-30 7:34 UTC (permalink / raw)
To: BAREBOX
bootscript_boot() takes a backup of the global.bootm. variables with
bootm_data_init_defaults() to restore them after the boot script
returns. The string members of struct bootm_data are not copies, though:
getenv_nonempty() returns a pointer to the globalvar's current value.
When the boot script assigns one of these variables, the parameter code
frees the old value, leaving the backup pointing to freed memory, which
bootm_data_restore_defaults() then copies back. This is easily observed
with a boot script that sets global.bootm.image to a nonexistent file:
after the failed boot, global.bootm.image holds the script's value
instead of the original one, because the new value was allocated into
the just freed chunk.
Fix this by duplicating the strings in the backup and freeing them after
restoring.
Fixes: 926985a74ee0 ("bootm: don't clobber global.bootm. variables after script boot fails")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/boot.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/common/boot.c b/common/boot.c
index 149bfeca00..1d8768b864 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -107,6 +107,16 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
bootm_data_init_defaults(&backup);
+ /*
+ * The strings point to the globalvars' current values, which the
+ * script frees when it assigns new ones. Keep our own copies.
+ */
+ backup.os_file = xstrdup(backup.os_file);
+ backup.initrd_file = xstrdup(backup.initrd_file);
+ backup.oftree_file = xstrdup(backup.oftree_file);
+ backup.root_dev = xstrdup(backup.root_dev);
+ backup.root_param = xstrdup(backup.root_param);
+
globalvar_add_simple("linux.bootargs.dyn.ip", NULL);
globalvar_add_simple("linux.bootargs.dyn.root", NULL);
@@ -136,6 +146,13 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
ret = bootm_entry(entry, &data);
out:
bootm_data_restore_defaults(&backup);
+
+ free_const(backup.os_file);
+ free_const(backup.initrd_file);
+ free_const(backup.oftree_file);
+ free_const(backup.root_dev);
+ free_const(backup.root_param);
+
return ret;
}
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/4] bootargs: fix double free in linux_bootargs_get()
2026-10-30 7:34 [PATCH 0/4] boot: UAF and double free fixes Sascha Hauer
2026-10-30 7:34 ` [PATCH 1/4] boot: fix use-after-free when restoring bootm variables Sascha Hauer
@ 2026-10-30 7:34 ` Sascha Hauer
2026-10-30 7:45 ` Ahmad Fatoum
2026-10-30 7:34 ` [PATCH 3/4] commands: boot: fix use-after-free of overrides taken from globalvars Sascha Hauer
2026-10-30 7:34 ` [PATCH 4/4] commands: boot: list bootm.image in the -o help text again Sascha Hauer
3 siblings, 1 reply; 6+ messages in thread
From: Sascha Hauer @ 2026-10-30 7:34 UTC (permalink / raw)
To: BAREBOX
linux_bootargs_get() frees the previously generated bootargs before
building them again. When no global.linux.bootargs.* variables exist,
it returns the legacy bootargs environment variable instead, without
resetting linux_bootargs. The next call then frees the same pointer a
second time.
This is easily triggered by fixing up the device tree a couple of
times, e.g. on sandbox:
global linux.bootargs.base=console=x; of_dump -F /chosen
global -r linux.bootargs.base; of_dump -F /chosen
of_dump -F /chosen
Fix this by setting linux_bootargs to NULL after freeing it.
Fixes: ee4cab9e5874 ("booting: more flexible Linux bootargs generation")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootargs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/common/bootargs.c b/common/bootargs.c
index 36528b8b58..6373d9ccb1 100644
--- a/common/bootargs.c
+++ b/common/bootargs.c
@@ -32,6 +32,7 @@ const char *linux_bootargs_get(void)
return linux_bootargs;
free(linux_bootargs);
+ linux_bootargs = NULL;
bootargs = globalvar_get_match("linux.bootargs.", " ");
if (!strlen(bootargs)) {
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/4] commands: boot: fix use-after-free of overrides taken from globalvars
2026-10-30 7:34 [PATCH 0/4] boot: UAF and double free fixes Sascha Hauer
2026-10-30 7:34 ` [PATCH 1/4] boot: fix use-after-free when restoring bootm variables Sascha Hauer
2026-10-30 7:34 ` [PATCH 2/4] bootargs: fix double free in linux_bootargs_get() Sascha Hauer
@ 2026-10-30 7:34 ` Sascha Hauer
2026-10-30 7:34 ` [PATCH 4/4] commands: boot: list bootm.image in the -o help text again Sascha Hauer
3 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2026-10-30 7:34 UTC (permalink / raw)
To: BAREBOX
When boot -o is given a variable without a value, e.g.
"boot -o bootm.image", boot_add_override() stores the pointer returned
by globalvar_get(). That string belongs to the globalvar. When the boot
entry then sets the globalvar, which is what boot scripts usually do
with global.bootm.image, the string is freed and the override points to
freed memory. In practice the override silently turns into the value
the script set, as the new value tends to land at the same address.
Store a copy of the override values and free them when do_boot()
returns. While at it, route the remaining early returns through the
cleanup path, which also fixes leaking the boot entries when the menu
default entry is invalid.
Fixes: a5e4c4340ef6 ("commands: boot: add support for overriding boot artifacts")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/boot.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/commands/boot.c b/commands/boot.c
index cc7a64bcca..b436afa91d 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -25,6 +25,23 @@ static char *next_word(void *context)
return strsep(context, " ");
}
+static void boot_set_override(const char **override, const char *val)
+{
+ free_const(*override);
+ /*
+ * Copy the value: if it was taken from a globalvar, the boot entry
+ * may change that globalvar, freeing the original string.
+ */
+ *override = val ? xstrdup(val) : NULL;
+}
+
+static void boot_free_overrides(struct bootm_overrides *overrides)
+{
+ free_const(overrides->os_file);
+ free_const(overrides->oftree_file);
+ free_const(overrides->initrd_file);
+}
+
static int boot_add_override(struct bootm_overrides *overrides, char *var)
{
const char *val;
@@ -44,11 +61,11 @@ static int boot_add_override(struct bootm_overrides *overrides, char *var)
if (!strcmp(var, "bootm.image")) {
if (isempty(val))
return -EINVAL;
- overrides->os_file = val;
+ boot_set_override(&overrides->os_file, val);
} else if (!strcmp(var, "bootm.oftree")) {
- overrides->oftree_file = val;
+ boot_set_override(&overrides->oftree_file, val);
} else if (!strcmp(var, "bootm.initrd")) {
- overrides->initrd_file = val;
+ boot_set_override(&overrides->initrd_file, val);
} else {
return -EINVAL;
}
@@ -124,10 +141,11 @@ static int do_boot(int argc, char *argv[])
case 'o':
ret = boot_add_override(&overrides, optarg);
if (ret)
- return ret;
+ goto out_overrides;
break;
default:
- return COMMAND_ERROR_USAGE;
+ ret = COMMAND_ERROR_USAGE;
+ goto out_overrides;
}
}
@@ -139,7 +157,7 @@ static int do_boot(int argc, char *argv[])
def = getenv("global.boot.default");
if (!def)
- return 0;
+ goto out_overrides;
handle = freep = xstrdup(def);
next = next_word;
@@ -181,8 +199,10 @@ static int do_boot(int argc, char *argv[])
int idx;
idx = bootentries_get_default_menu_entry(entries, default_menu_entry);
- if (idx < 0)
- return idx;
+ if (idx < 0) {
+ ret = idx;
+ goto out;
+ }
bootsources_menu(entries, idx, timeout);
}
@@ -191,6 +211,8 @@ static int do_boot(int argc, char *argv[])
out:
bootentries_free(entries);
free(freep);
+out_overrides:
+ boot_free_overrides(&overrides);
return ret;
}
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4/4] commands: boot: list bootm.image in the -o help text again
2026-10-30 7:34 [PATCH 0/4] boot: UAF and double free fixes Sascha Hauer
` (2 preceding siblings ...)
2026-10-30 7:34 ` [PATCH 3/4] commands: boot: fix use-after-free of overrides taken from globalvars Sascha Hauer
@ 2026-10-30 7:34 ` Sascha Hauer
3 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2026-10-30 7:34 UTC (permalink / raw)
To: BAREBOX
Commit 2d6aaf0100f0 ("bootm: remove ability for late override of
bootm.image") dropped bootm.image from the help text when the image
override was removed. Commit a9f6911e9eb1 ("bootm: implement plain and
FIT bootm.image override") brought the override back but left the help
text alone. Add bootm.image again.
Fixes: a9f6911e9eb1 ("bootm: implement plain and FIT bootm.image override")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/boot.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/commands/boot.c b/commands/boot.c
index b436afa91d..81f392075d 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -263,7 +263,7 @@ BAREBOX_CMD_HELP_OPT ("-m","Show a menu with boot options")
BAREBOX_CMD_HELP_OPT ("-M DEFAULT","Show a menu with boot options with entry DEFAULT preselected")
BAREBOX_CMD_HELP_OPT ("-w SECS","Start watchdog with timeout SECS before booting")
#ifdef CONFIG_BOOT_OVERRIDE
-BAREBOX_CMD_HELP_OPT ("-o VAR[=VAL]","override VAR (bootm.{oftree,initrd}) with VAL")
+BAREBOX_CMD_HELP_OPT ("-o VAR[=VAL]","override VAR (bootm.{image,oftree,initrd}) with VAL")
BAREBOX_CMD_HELP_OPT (" ","if VAL is not specified, the value of VAR is taken")
#endif
BAREBOX_CMD_HELP_OPT ("-t SECS","specify timeout in SECS")
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/4] bootargs: fix double free in linux_bootargs_get()
2026-10-30 7:34 ` [PATCH 2/4] bootargs: fix double free in linux_bootargs_get() Sascha Hauer
@ 2026-10-30 7:45 ` Ahmad Fatoum
0 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2026-10-30 7:45 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
On 10/30/26 8:34 AM, Sascha Hauer wrote:
> linux_bootargs_get() frees the previously generated bootargs before
> building them again. When no global.linux.bootargs.* variables exist,
> it returns the legacy bootargs environment variable instead, without
> resetting linux_bootargs. The next call then frees the same pointer a
> second time.
>
> This is easily triggered by fixing up the device tree a couple of
> times, e.g. on sandbox:
>
> global linux.bootargs.base=console=x; of_dump -F /chosen
> global -r linux.bootargs.base; of_dump -F /chosen
> of_dump -F /chosen
>
> Fix this by setting linux_bootargs to NULL after freeing it.
>
> Fixes: ee4cab9e5874 ("booting: more flexible Linux bootargs generation")
> Assisted-by: Claude:claude-opus-5-5
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
I have the same patch in my UKI series[1], but cherry-picking this
directly to master is a good idea.
[1]:
https://lore.kernel.org/barebox/20261026121150.455510-4-a.fatoum@pengutronix.de/
> ---
> common/bootargs.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/common/bootargs.c b/common/bootargs.c
> index 36528b8b58..6373d9ccb1 100644
> --- a/common/bootargs.c
> +++ b/common/bootargs.c
> @@ -32,6 +32,7 @@ const char *linux_bootargs_get(void)
> return linux_bootargs;
>
> free(linux_bootargs);
> + linux_bootargs = NULL;
>
> bootargs = globalvar_get_match("linux.bootargs.", " ");
> if (!strlen(bootargs)) {
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-30 7:46 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 7:34 [PATCH 0/4] boot: UAF and double free fixes Sascha Hauer
2026-10-30 7:34 ` [PATCH 1/4] boot: fix use-after-free when restoring bootm variables Sascha Hauer
2026-10-30 7:34 ` [PATCH 2/4] bootargs: fix double free in linux_bootargs_get() Sascha Hauer
2026-10-30 7:45 ` Ahmad Fatoum
2026-10-30 7:34 ` [PATCH 3/4] commands: boot: fix use-after-free of overrides taken from globalvars Sascha Hauer
2026-10-30 7:34 ` [PATCH 4/4] commands: boot: list bootm.image in the -o help text again Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox