From: dongshengyuan <545258830@qq.com> Date: Thu, 9 Jul 2026 00:39:03 +0000 (+0800) Subject: efi-api: validate boot option device path lengths X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d13b002aec366aeab72019dce86e956e8c7ba65c;p=thirdparty%2Fsystemd.git efi-api: validate boot option device path lengths efi_get_boot_option() validates the overall Boot#### variable size and the advertised device-path byte count, but then walks each device-path node without first checking that the node header and subtype payload fit in the remaining buffer. A malformed Boot#### variable could make the parser read past the end of the current node, or past the available device-path data. Limit parsing to the bytes that are actually present, and stop walking the device path when a malformed node is encountered. This keeps the previous best-effort behaviour for fields parsed before the anomaly while avoiding out-of-bounds reads. Signed-off-by: dongshengyuan --- diff --git a/src/shared/efi-api.c b/src/shared/efi-api.c index 56b055a0c8a..652c48e84ba 100644 --- a/src/shared/efi-api.c +++ b/src/shared/efi-api.c @@ -283,19 +283,23 @@ int efi_get_boot_option( if (header->path_len > 0) { uint8_t *dbuf; - size_t dnext, doff; + size_t dnext, doff, path_len; doff = offsetof(struct boot_option, title) + title_size; dbuf = buf + doff; - if (header->path_len > l - doff) - return -EINVAL; + path_len = MIN((size_t) header->path_len, l - doff); dnext = 0; - while (dnext < header->path_len) { + while (dnext < path_len) { struct device_path *dpath; + size_t remaining = path_len - dnext; + + if (remaining < offsetof(struct device_path, path)) + break; dpath = (struct device_path *)(dbuf + dnext); - if (dpath->length < 4) + if (dpath->length < offsetof(struct device_path, path) || + dpath->length > remaining) break; /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */ @@ -310,6 +314,9 @@ int efi_get_boot_option( /* Sub-Type 1 – Hard Drive */ if (dpath->sub_type == MEDIA_HARDDRIVE_DP) { + if (dpath->length < offsetof(struct device_path, drive) + sizeof(struct drive_path)) + break; + /* 0x02 – GUID Partition Table */ if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER) continue; @@ -325,9 +332,9 @@ int efi_get_boot_option( /* Sub-Type 4 – File Path */ if (dpath->sub_type == MEDIA_FILEPATH_DP && !p && ret_path) { - p = utf16_to_utf8(dpath->path, dpath->length-4); + p = utf16_to_utf8(dpath->path, dpath->length - offsetof(struct device_path, path)); if (!p) - return -ENOMEM; + return -ENOMEM; efi_tilt_backslashes(p); continue;