On 6/17/26 07:31, Hem Parekh wrote:
From: Hem Parekh <[email protected]>
get_dp_device() reads a Boot#### variable and passes its contents to
efi_deserialize_load_option() but ignores the return value. On failure
efi_deserialize_load_option() may return without having initialised the
caller's struct efi_load_option, and even on a malformed device path it
sets lo.file_path before validating it with efi_dp_check_length().
As a result get_dp_device() can proceed to walk lo.file_path with
efi_dp_split_file_path() (via efi_dp_dup()/efi_dp_size()) on a device
path that was never validated, or on an uninitialised pointer when the
variable is too short to be parsed. A device-path node with a length of
zero makes the walk loop forever, and a length below the 4-byte node
header leads to an out-of-bounds read. The Boot#### variable is
attacker-controlled in threat models where writing EFI variables does
not imply the ability to execute firmware code, so this is reachable
during capsule-on-disk processing at boot.
Check the return value and bail out, as every other caller of
efi_deserialize_load_option() already does.
Signed-off-by: Hem Parekh <[email protected]>
Thank you for addressing the missing error handling.
Unfortunately we cannot merge this with an invalid email address in the
Signed-off-by line. Please, use your true email address when resending
the patch.
---
lib/efi_loader/efi_capsule.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 52887f7c..01c86bc4 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -860,7 +860,12 @@ static efi_status_t get_dp_device(u16 *boot_var,
if (!buf)
return EFI_NOT_FOUND;
- efi_deserialize_load_option(&lo, buf, &size);
+ ret = efi_deserialize_load_option(&lo, buf, &size);
+ if (ret != EFI_SUCCESS) {
+ log_err("Invalid load option for %ls\n", boot_var);
I would drop the word 'for' here.
This looks correct. Yet, typically we just use a `goto out;` and have a
label out: where the cleanup starts.
Best regards
Heinrich
+ free(buf);
+ return ret;
+ }
if (lo.attributes & LOAD_OPTION_ACTIVE) {
efi_dp_split_file_path(lo.file_path, device_dp, &file_dp);