summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Jones <pjones@redhat.com>2025-02-25 11:44:11 -0500
committerPeter Jones <pjones@redhat.com>2025-02-25 19:40:54 -0500
commit3bce11831343ba6e67740f23ab3a6c6f09bc0bca (patch)
tree53a2fd99cb66cb0cd51e6bcc80d3fa0223e61699
parent1baf1efb37e2728104765477b12b70aeef3090af (diff)
downloadefi-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.c2
-rw-r--r--include/pe.h3
-rw-r--r--pe-relocate.c12
-rw-r--r--pe.c4
-rw-r--r--shim.c4
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;
}
diff --git a/pe.c b/pe.c
index 40812bb7..d785c44e 100644
--- a/pe.c
+++ b/pe.c
@@ -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;
diff --git a/shim.c b/shim.c
index 6afb35c5..9efbde11 100644
--- a/shim.c
+++ b/shim.c
@@ -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;