diff options
-rw-r--r-- | src/image/efi_image.c | 76 |
1 files changed, 71 insertions, 5 deletions
diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 0be485649..6a7bba014 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -356,9 +356,75 @@ static int efi_image_probe ( struct image *image ) { return rc; } -/** EFI image type */ -struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = { - .name = "EFI", - .probe = efi_image_probe, - .exec = efi_image_exec, +/** + * Probe EFI PE image + * + * @v image EFI file + * @ret rc Return status code + * + * The extremely broken UEFI Secure Boot model provides no way for us + * to unambiguously determine that a valid EFI executable image was + * rejected by LoadImage() because it failed signature verification. + * We must therefore use heuristics to guess whether not an image that + * was rejected by LoadImage() could still be loaded via a separate PE + * loader such as the UEFI shim. + */ +static int efi_pe_image_probe ( struct image *image ) { + const UINT16 magic = ( ( sizeof ( UINTN ) == sizeof ( uint32_t ) ) ? + EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC : + EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC ); + union { + EFI_IMAGE_DOS_HEADER dos; + EFI_IMAGE_OPTIONAL_HEADER_UNION pe; + } u; + + /* Check for existence of DOS header */ + if ( image->len < sizeof ( u.dos ) ) { + DBGC ( image, "EFIIMAGE %s too short for DOS header\n", + image->name ); + return -ENOEXEC; + } + copy_from_user ( &u.dos, image->data, 0, sizeof ( u.dos ) ); + if ( u.dos.e_magic != EFI_IMAGE_DOS_SIGNATURE ) { + DBGC ( image, "EFIIMAGE %s missing MZ signature\n", + image->name ); + return -ENOEXEC; + } + + /* Check for existence of PE header */ + if ( ( image->len < u.dos.e_lfanew ) || + ( ( image->len - u.dos.e_lfanew ) < sizeof ( u.pe ) ) ) { + DBGC ( image, "EFIIMAGE %s too short for PE header\n", + image->name ); + return -ENOEXEC; + } + copy_from_user ( &u.pe, image->data, u.dos.e_lfanew, sizeof ( u.pe ) ); + if ( u.pe.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE ) { + DBGC ( image, "EFIIMAGE %s missing PE signature\n", + image->name ); + return -ENOEXEC; + } + + /* Check PE header magic */ + if ( u.pe.Pe32.OptionalHeader.Magic != magic ) { + DBGC ( image, "EFIIMAGE %s incorrect magic %04x\n", + image->name, u.pe.Pe32.OptionalHeader.Magic ); + return -ENOEXEC; + } + + return 0; +} + +/** EFI image types */ +struct image_type efi_image_type[] __image_type ( PROBE_NORMAL ) = { + { + .name = "EFI", + .probe = efi_image_probe, + .exec = efi_image_exec, + }, + { + .name = "EFIPE", + .probe = efi_pe_image_probe, + .exec = efi_image_exec, + }, }; |