From: Hem Parekh Date: Mon, 27 Jul 2026 11:03:36 +0000 (+0200) Subject: efi_loader: check efi_deserialize_load_option() in get_dp_device() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d47f55832833744b870dc8b9c7564ceed48d2bd;p=thirdparty%2Fu-boot.git efi_loader: check efi_deserialize_load_option() in get_dp_device() 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. Suggested-by: Hem Parekh Cc: Hem Parekh Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 52887f7c274..a77810fa15c 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -860,7 +860,11 @@ 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 %ls\n", boot_var); + goto out; + } if (lo.attributes & LOAD_OPTION_ACTIVE) { efi_dp_split_file_path(lo.file_path, device_dp, &file_dp); @@ -871,6 +875,7 @@ static efi_status_t get_dp_device(u16 *boot_var, ret = EFI_NOT_FOUND; } +out: free(buf); return ret;