summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/image/efi_image.c76
1 files changed, 71 insertions, 5 deletions
diff --git a/src/image/efi_image.c b/src/image/efi_image.c
index 0be48564..6a7bba01 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,
+ },
};