* [PATCH] efi_loader: fix use of uninitialized guid in variable enumeration loops
@ 2026-07-28 16:49 Scott Moser
2026-07-28 17:16 ` Heinrich Schuchardt
2026-07-28 19:33 ` [PATCH v2] " Scott Moser
0 siblings, 2 replies; 4+ messages in thread
From: Scott Moser @ 2026-07-28 16:49 UTC (permalink / raw)
To: u-boot; +Cc: Heinrich Schuchardt, Ilias Apalodimas, Scott Moser
efi_bootmgr_delete_invalid_boot_option(), eficonfig_show_boot_selection(),
and eficonfig_create_change_boot_order_entry() each enumerate all EFI
variables by repeatedly calling efi_next_variable_name() in a loop,
passing the same efi_guid_t as both input and output. GetNextVariableName()
needs the vendor GUID returned by the previous call, together with the
variable name it returned, to know where to resume.
In each of these loops the efi_guid_t was declared inside the loop body,
so a new instance comes into scope on every iteration. Relying on it to
still hold the previous iteration's value depends on the compiler reusing
the same stack slot across iterations, which is undefined behavior. With
a compiler that zero-initializes locals by default (e.g. clang, or gcc
configured with -ftrivial-auto-var-init=zero), the GUID is cleared on
every iteration, so the lookup of the variable name returned by the
previous call fails and efi_init_obj_list() aborts:
Cannot initialize UEFI sub-system
** Booting bootflow ... with efi
Boot failed (err=-22)
Move the efi_guid_t declarations out of the loops so the value written
by the previous efi_next_variable_name() call is preserved across
iterations.
Fixes: 140a8959d48f ("eficonfig: use efi_get_next_variable_name_int()")
Signed-off-by: Scott Moser <smoser@brickies.net>
---
cmd/eficonfig.c | 4 ++--
lib/efi_loader/efi_bootmgr.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 4d060e3007c..cd66f05fb7a 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -1844,6 +1844,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
struct efimenu *efi_menu;
struct list_head *pos, *n;
struct eficonfig_entry *entry;
+ efi_guid_t guid = {};
efi_menu = calloc(1, sizeof(struct efimenu));
if (!efi_menu)
@@ -1872,7 +1873,6 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
var_name16[0] = 0;
for (;;) {
int index;
- efi_guid_t guid;
ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
if (ret == EFI_NOT_FOUND)
@@ -2245,6 +2245,7 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
u16 *var_name16 = NULL;
efi_uintn_t size, buf_size;
struct eficonfig_save_boot_order_data *save_data;
+ efi_guid_t guid = {};
/* list the load option in the order of BootOrder variable */
for (i = 0; i < num; i++) {
@@ -2265,7 +2266,6 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
var_name16[0] = 0;
for (;;) {
int index;
- efi_guid_t guid;
if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
break;
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 8c9a9b5eb56..3ee47000d23 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -934,6 +934,7 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
efi_status_t ret = EFI_SUCCESS;
u16 *delete_index_list = NULL, *p;
efi_uintn_t buf_size;
+ efi_guid_t guid = {};
buf_size = 128;
var_name16 = malloc(buf_size);
@@ -943,7 +944,6 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
var_name16[0] = 0;
for (;;) {
int index;
- efi_guid_t guid;
efi_uintn_t tmp;
ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] efi_loader: fix use of uninitialized guid in variable enumeration loops
2026-07-28 16:49 [PATCH] efi_loader: fix use of uninitialized guid in variable enumeration loops Scott Moser
@ 2026-07-28 17:16 ` Heinrich Schuchardt
2026-07-28 19:33 ` [PATCH v2] " Scott Moser
1 sibling, 0 replies; 4+ messages in thread
From: Heinrich Schuchardt @ 2026-07-28 17:16 UTC (permalink / raw)
To: Scott Moser, u-boot; +Cc: Ilias Apalodimas
Am 28. Juli 2026 18:49:48 MESZ schrieb Scott Moser <smoser@brickies.net>:
>efi_bootmgr_delete_invalid_boot_option(), eficonfig_show_boot_selection(),
>and eficonfig_create_change_boot_order_entry() each enumerate all EFI
>variables by repeatedly calling efi_next_variable_name() in a loop,
>passing the same efi_guid_t as both input and output. GetNextVariableName()
>needs the vendor GUID returned by the previous call, together with the
>variable name it returned, to know where to resume.
>
>In each of these loops the efi_guid_t was declared inside the loop body,
>so a new instance comes into scope on every iteration. Relying on it to
>still hold the previous iteration's value depends on the compiler reusing
>the same stack slot across iterations, which is undefined behavior. With
>a compiler that zero-initializes locals by default (e.g. clang, or gcc
>configured with -ftrivial-auto-var-init=zero), the GUID is cleared on
>every iteration, so the lookup of the variable name returned by the
>previous call fails and efi_init_obj_list() aborts:
>
> Cannot initialize UEFI sub-system
> ** Booting bootflow ... with efi
> Boot failed (err=-22)
>
>Move the efi_guid_t declarations out of the loops so the value written
>by the previous efi_next_variable_name() call is preserved across
>iterations.
>
>Fixes: 140a8959d48f ("eficonfig: use efi_get_next_variable_name_int()")
>Signed-off-by: Scott Moser <smoser@brickies.net>
>---
> cmd/eficonfig.c | 4 ++--
> lib/efi_loader/efi_bootmgr.c | 2 +-
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
>diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
>index 4d060e3007c..cd66f05fb7a 100644
>--- a/cmd/eficonfig.c
>+++ b/cmd/eficonfig.c
>@@ -1844,6 +1844,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
> struct efimenu *efi_menu;
> struct list_head *pos, *n;
> struct eficonfig_entry *entry;
>+ efi_guid_t guid = {};
>
> efi_menu = calloc(1, sizeof(struct efimenu));
> if (!efi_menu)
>@@ -1872,7 +1873,6 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
> var_name16[0] = 0;
> for (;;) {
> int index;
>- efi_guid_t guid;
>
> ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
> if (ret == EFI_NOT_FOUND)
>@@ -2245,6 +2245,7 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
> u16 *var_name16 = NULL;
> efi_uintn_t size, buf_size;
> struct eficonfig_save_boot_order_data *save_data;
>+ efi_guid_t guid = {};
Thank you for addressing this issue.
According to the UEFI specification:
"When VariableName is a pointer to a Null character, VendorGuid is ignored."
Initialization of the GUID is not needed and should be avoided to reduce the code size.
>
> /* list the load option in the order of BootOrder variable */
> for (i = 0; i < num; i++) {
>@@ -2265,7 +2266,6 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
> var_name16[0] = 0;
> for (;;) {
> int index;
>- efi_guid_t guid;
>
> if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
> break;
>diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
>index 8c9a9b5eb56..3ee47000d23 100644
>--- a/lib/efi_loader/efi_bootmgr.c
>+++ b/lib/efi_loader/efi_bootmgr.c
>@@ -934,6 +934,7 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
> efi_status_t ret = EFI_SUCCESS;
> u16 *delete_index_list = NULL, *p;
> efi_uintn_t buf_size;
>+ efi_guid_t guid = {};
ditto
Best regards
Heinrich
>
> buf_size = 128;
> var_name16 = malloc(buf_size);
>@@ -943,7 +944,6 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
> var_name16[0] = 0;
> for (;;) {
> int index;
>- efi_guid_t guid;
> efi_uintn_t tmp;
>
> ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] efi_loader: fix use of uninitialized guid in variable enumeration loops
2026-07-28 16:49 [PATCH] efi_loader: fix use of uninitialized guid in variable enumeration loops Scott Moser
2026-07-28 17:16 ` Heinrich Schuchardt
@ 2026-07-28 19:33 ` Scott Moser
2026-07-31 9:24 ` Heinrich Schuchardt
1 sibling, 1 reply; 4+ messages in thread
From: Scott Moser @ 2026-07-28 19:33 UTC (permalink / raw)
To: u-boot; +Cc: Heinrich Schuchardt, Ilias Apalodimas, Masahisa Kojima,
Scott Moser
efi_bootmgr_delete_invalid_boot_option(), eficonfig_show_boot_selection(),
and eficonfig_create_change_boot_order_entry() each enumerate all EFI
variables by repeatedly calling efi_next_variable_name() in a loop,
passing the same efi_guid_t as both input and output. GetNextVariableName()
needs the vendor GUID returned by the previous call, together with the
variable name it returned, to know where to resume.
In each of these loops the efi_guid_t was declared inside the loop body,
so a new instance comes into scope on every iteration. Relying on it to
still hold the previous iteration's value depends on the compiler reusing
the same stack slot across iterations, which is undefined behavior. With
a compiler that zero-initializes locals by default (e.g. clang, or gcc
configured with -ftrivial-auto-var-init=zero), the GUID is cleared on
every iteration, so the lookup of the variable name returned by the
previous call fails and efi_init_obj_list() aborts:
Cannot initialize UEFI sub-system
** Booting bootflow ... with efi
Boot failed (err=-22)
Move the efi_guid_t declarations out of the loops so the value written
by the previous efi_next_variable_name() call is preserved across
iterations.
Fixes: 140a8959d48f ("eficonfig: use efi_get_next_variable_name_int()")
Signed-off-by: Scott Moser <smoser@brickies.net>
---
Changes for v2:
- Drop the "= {}" initializer on the hoisted guid: per the UEFI spec,
VendorGuid is ignored when VariableName is an empty string, which is
the state var_name16 is in on the first call, so the initial value is
never read and zero-initializing it only costs code size.
cmd/eficonfig.c | 4 ++--
lib/efi_loader/efi_bootmgr.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 4d060e3007c..d8e7ed6666a 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -1844,6 +1844,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
struct efimenu *efi_menu;
struct list_head *pos, *n;
struct eficonfig_entry *entry;
+ efi_guid_t guid;
efi_menu = calloc(1, sizeof(struct efimenu));
if (!efi_menu)
@@ -1872,7 +1873,6 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
var_name16[0] = 0;
for (;;) {
int index;
- efi_guid_t guid;
ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
if (ret == EFI_NOT_FOUND)
@@ -2245,6 +2245,7 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
u16 *var_name16 = NULL;
efi_uintn_t size, buf_size;
struct eficonfig_save_boot_order_data *save_data;
+ efi_guid_t guid;
/* list the load option in the order of BootOrder variable */
for (i = 0; i < num; i++) {
@@ -2265,7 +2266,6 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
var_name16[0] = 0;
for (;;) {
int index;
- efi_guid_t guid;
if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
break;
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 8c9a9b5eb56..8938b214ceb 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -934,6 +934,7 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
efi_status_t ret = EFI_SUCCESS;
u16 *delete_index_list = NULL, *p;
efi_uintn_t buf_size;
+ efi_guid_t guid;
buf_size = 128;
var_name16 = malloc(buf_size);
@@ -943,7 +944,6 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
var_name16[0] = 0;
for (;;) {
int index;
- efi_guid_t guid;
efi_uintn_t tmp;
ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2] efi_loader: fix use of uninitialized guid in variable enumeration loops
2026-07-28 19:33 ` [PATCH v2] " Scott Moser
@ 2026-07-31 9:24 ` Heinrich Schuchardt
0 siblings, 0 replies; 4+ messages in thread
From: Heinrich Schuchardt @ 2026-07-31 9:24 UTC (permalink / raw)
To: Scott Moser; +Cc: Ilias Apalodimas, Masahisa Kojima, u-boot
On 7/28/26 21:33, Scott Moser wrote:
> efi_bootmgr_delete_invalid_boot_option(), eficonfig_show_boot_selection(),
> and eficonfig_create_change_boot_order_entry() each enumerate all EFI
> variables by repeatedly calling efi_next_variable_name() in a loop,
> passing the same efi_guid_t as both input and output. GetNextVariableName()
> needs the vendor GUID returned by the previous call, together with the
> variable name it returned, to know where to resume.
>
> In each of these loops the efi_guid_t was declared inside the loop body,
> so a new instance comes into scope on every iteration. Relying on it to
> still hold the previous iteration's value depends on the compiler reusing
> the same stack slot across iterations, which is undefined behavior. With
> a compiler that zero-initializes locals by default (e.g. clang, or gcc
> configured with -ftrivial-auto-var-init=zero), the GUID is cleared on
> every iteration, so the lookup of the variable name returned by the
> previous call fails and efi_init_obj_list() aborts:
>
> Cannot initialize UEFI sub-system
> ** Booting bootflow ... with efi
> Boot failed (err=-22)
>
> Move the efi_guid_t declarations out of the loops so the value written
> by the previous efi_next_variable_name() call is preserved across
> iterations.
>
> Fixes: 140a8959d48f ("eficonfig: use efi_get_next_variable_name_int()")
> Signed-off-by: Scott Moser <smoser@brickies.net>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
None of the loops handles EFI_BUFFER_TOO_SMALL. Just create a variable
called fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210
to break the code.
We should move all calls of GetNextVariable() to a new function in
lib/efi_loader/efi_var_common.c with proper handling of the variable
name buffer.
But let's merge the current patch first.
Best regards
Heinrich
> ---
> Changes for v2:
> - Drop the "= {}" initializer on the hoisted guid: per the UEFI spec,
> VendorGuid is ignored when VariableName is an empty string, which is
> the state var_name16 is in on the first call, so the initial value is
> never read and zero-initializing it only costs code size.
>
> cmd/eficonfig.c | 4 ++--
> lib/efi_loader/efi_bootmgr.c | 2 +-
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> index 4d060e3007c..d8e7ed6666a 100644
> --- a/cmd/eficonfig.c
> +++ b/cmd/eficonfig.c
> @@ -1844,6 +1844,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
> struct efimenu *efi_menu;
> struct list_head *pos, *n;
> struct eficonfig_entry *entry;
> + efi_guid_t guid;
>
> efi_menu = calloc(1, sizeof(struct efimenu));
> if (!efi_menu)
> @@ -1872,7 +1873,6 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
> var_name16[0] = 0;
> for (;;) {
> int index;
> - efi_guid_t guid;
>
> ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
> if (ret == EFI_NOT_FOUND)
> @@ -2245,6 +2245,7 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
> u16 *var_name16 = NULL;
> efi_uintn_t size, buf_size;
> struct eficonfig_save_boot_order_data *save_data;
> + efi_guid_t guid;
>
> /* list the load option in the order of BootOrder variable */
> for (i = 0; i < num; i++) {
> @@ -2265,7 +2266,6 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
> var_name16[0] = 0;
> for (;;) {
> int index;
> - efi_guid_t guid;
>
> if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
> break;
> diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
> index 8c9a9b5eb56..8938b214ceb 100644
> --- a/lib/efi_loader/efi_bootmgr.c
> +++ b/lib/efi_loader/efi_bootmgr.c
> @@ -934,6 +934,7 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
> efi_status_t ret = EFI_SUCCESS;
> u16 *delete_index_list = NULL, *p;
> efi_uintn_t buf_size;
> + efi_guid_t guid;
>
> buf_size = 128;
> var_name16 = malloc(buf_size);
> @@ -943,7 +944,6 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi
> var_name16[0] = 0;
> for (;;) {
> int index;
> - efi_guid_t guid;
> efi_uintn_t tmp;
>
> ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-31 9:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-28 16:49 [PATCH] efi_loader: fix use of uninitialized guid in variable enumeration loops Scott Moser
2026-07-28 17:16 ` Heinrich Schuchardt
2026-07-28 19:33 ` [PATCH v2] " Scott Moser
2026-07-31 9:24 ` Heinrich Schuchardt
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.