diff options
| author | Peter Jones <pjones@redhat.com> | 2025-02-25 11:44:11 -0500 |
|---|---|---|
| committer | Peter Jones <pjones@redhat.com> | 2025-02-25 19:40:54 -0500 |
| commit | 3bce11831343ba6e67740f23ab3a6c6f09bc0bca (patch) | |
| tree | 53a2fd99cb66cb0cd51e6bcc80d3fa0223e61699 | |
| parent | 1baf1efb37e2728104765477b12b70aeef3090af (diff) | |
| download | efi-boot-shim-3bce11831343ba6e67740f23ab3a6c6f09bc0bca.tar.gz efi-boot-shim-3bce11831343ba6e67740f23ab3a6c6f09bc0bca.zip | |
pe: read_header(): allow skipping SecDir content validation
When we're parsing the PE header of shim itself from the Loaded Image
object, the signatures aren't present, but the Certificate Table entry
in the Data Directory has not been cleared, so it'll fail verification.
We know when we're doing that, so this patch makes that test optional.
Signed-off-by: Peter Jones <pjones@redhat.com>
| -rw-r--r-- | fuzz-pe-relocate.c | 2 | ||||
| -rw-r--r-- | include/pe.h | 3 | ||||
| -rw-r--r-- | pe-relocate.c | 12 | ||||
| -rw-r--r-- | pe.c | 4 | ||||
| -rw-r--r-- | shim.c | 4 |
5 files changed, 15 insertions, 10 deletions
diff --git a/fuzz-pe-relocate.c b/fuzz-pe-relocate.c index 1f62234d..09d38331 100644 --- a/fuzz-pe-relocate.c +++ b/fuzz-pe-relocate.c @@ -28,7 +28,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) memcpy(data_copy, data, size); data_copy[size] = 0; - status = read_header(data_copy, size, &context); + status = read_header(data_copy, size, &context, true); free(data_copy); diff --git a/include/pe.h b/include/pe.h index 9ea9eb44..a1eb8853 100644 --- a/include/pe.h +++ b/include/pe.h @@ -12,7 +12,8 @@ ImageAddress (void *image, uint64_t size, uint64_t address); EFI_STATUS read_header(void *data, unsigned int datasize, - PE_COFF_LOADER_IMAGE_CONTEXT *context); + PE_COFF_LOADER_IMAGE_CONTEXT *context, + bool check_secdir); EFI_STATUS verify_image(void *data, unsigned int datasize, EFI_LOADED_IMAGE *li, diff --git a/pe-relocate.c b/pe-relocate.c index bde71729..b436d3ec 100644 --- a/pe-relocate.c +++ b/pe-relocate.c @@ -368,7 +368,8 @@ image_is_loadable(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr) */ EFI_STATUS read_header(void *data, unsigned int datasize, - PE_COFF_LOADER_IMAGE_CONTEXT *context) + PE_COFF_LOADER_IMAGE_CONTEXT *context, + bool check_secdir) { EFI_IMAGE_DOS_HEADER *DosHdr = data; EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data; @@ -542,9 +543,12 @@ read_header(void *data, unsigned int datasize, return EFI_UNSUPPORTED; } - if (context->SecDir->VirtualAddress > datasize || - (context->SecDir->VirtualAddress == datasize && - context->SecDir->Size > 0)) { + if (check_secdir && + (context->SecDir->VirtualAddress > datasize || + (context->SecDir->VirtualAddress == datasize && + context->SecDir->Size > 0))) { + dprint(L"context->SecDir->VirtualAddress:0x%llx context->SecDir->Size:0x%llx datasize:0x%llx\n", + context->SecDir->VirtualAddress, context->SecDir->Size, datasize); perror(L"Malformed security header\n"); return EFI_INVALID_PARAMETER; } @@ -406,7 +406,7 @@ EFI_STATUS verify_image(void *data, unsigned int datasize, /* * The binary header contains relevant context and section pointers */ - efi_status = read_header(data, datasize, context); + efi_status = read_header(data, datasize, context, true); if (EFI_ERROR(efi_status)) { perror(L"Failed to read header: %r\n", efi_status); return efi_status; @@ -482,7 +482,7 @@ handle_image (void *data, unsigned int datasize, /* * The binary header contains relevant context and section pointers */ - efi_status = read_header(data, datasize, &context); + efi_status = read_header(data, datasize, &context, true); if (EFI_ERROR(efi_status)) { perror(L"Failed to read header: %r\n", efi_status); return efi_status; @@ -961,7 +961,7 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) in_protocol = 1; - efi_status = read_header(buffer, size, &context); + efi_status = read_header(buffer, size, &context, true); if (EFI_ERROR(efi_status)) goto done; @@ -1016,7 +1016,7 @@ static EFI_STATUS shim_read_header(void *data, unsigned int datasize, EFI_STATUS efi_status; in_protocol = 1; - efi_status = read_header(data, datasize, context); + efi_status = read_header(data, datasize, context, true); in_protocol = 0; return efi_status; |
