efi_loader: Check machine type in the image header
authorIvan Gorinov <ivan.gorinov@intel.com>
Fri, 6 Apr 2018 01:32:06 +0000 (18:32 -0700)
committerAlexander Graf <agraf@suse.de>
Fri, 6 Apr 2018 07:28:01 +0000 (09:28 +0200)
Check FileHeader.Machine to make sure the EFI executable image is built
for the same architecture. For example, 32-bit U-Boot on x86 will print
an error message instead of loading an x86_64 image and crashing.

Signed-off-by: Ivan Gorinov <ivan.gorinov@intel.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
include/pe.h
lib/efi_loader/efi_image_loader.c

index c3a19cef765ed17ee0764b5f1edbd1664b6c489f..e7845bb7d2cfa5ff00144b768d12492e7af849e3 100644 (file)
@@ -38,11 +38,15 @@ typedef struct _IMAGE_DOS_HEADER {
 #define IMAGE_DOS_SIGNATURE            0x5A4D     /* MZ   */
 #define IMAGE_NT_SIGNATURE             0x00004550 /* PE00 */
 
+#define IMAGE_FILE_MACHINE_I386                0x014c
 #define IMAGE_FILE_MACHINE_ARM         0x01c0
 #define IMAGE_FILE_MACHINE_THUMB       0x01c2
 #define IMAGE_FILE_MACHINE_ARMNT       0x01c4
 #define IMAGE_FILE_MACHINE_AMD64       0x8664
 #define IMAGE_FILE_MACHINE_ARM64       0xaa64
+#define IMAGE_FILE_MACHINE_RISCV32     0x5032
+#define IMAGE_FILE_MACHINE_RISCV64     0x5064
+
 #define IMAGE_NT_OPTIONAL_HDR32_MAGIC  0x10b
 #define IMAGE_NT_OPTIONAL_HDR64_MAGIC  0x20b
 #define IMAGE_SUBSYSTEM_EFI_APPLICATION        10
index f5885760d416338e58bab63736c97319cf8c3da5..d5fbba3138358e9827c5a3a58bcf650e268c21c5 100644 (file)
@@ -22,6 +22,30 @@ const efi_guid_t efi_simple_file_system_protocol_guid =
                EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
 const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
 
+static int machines[] = {
+#if defined(CONFIG_ARM64)
+       IMAGE_FILE_MACHINE_ARM64,
+#elif defined(CONFIG_ARM)
+       IMAGE_FILE_MACHINE_ARM,
+       IMAGE_FILE_MACHINE_THUMB,
+       IMAGE_FILE_MACHINE_ARMNT,
+#endif
+
+#if defined(CONFIG_X86_64)
+       IMAGE_FILE_MACHINE_AMD64,
+#elif defined(CONFIG_X86)
+       IMAGE_FILE_MACHINE_I386,
+#endif
+
+#if defined(CONFIG_CPU_RISCV_32)
+       IMAGE_FILE_MACHINE_RISCV32,
+#endif
+
+#if defined(CONFIG_CPU_RISCV_64)
+       IMAGE_FILE_MACHINE_RISCV64,
+#endif
+       0 };
+
 /*
  * Print information about a loaded image.
  *
@@ -172,14 +196,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
        void *entry;
        uint64_t image_size;
        unsigned long virt_size = 0;
-       bool can_run_nt64 = true;
-       bool can_run_nt32 = true;
-
-#if defined(CONFIG_ARM64)
-       can_run_nt32 = false;
-#elif defined(CONFIG_ARM)
-       can_run_nt64 = false;
-#endif
+       int supported = 0;
 
        dos = efi;
        if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
@@ -193,6 +210,18 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
                return NULL;
        }
 
+       for (i = 0; machines[i]; i++)
+               if (machines[i] == nt->FileHeader.Machine) {
+                       supported = 1;
+                       break;
+               }
+
+       if (!supported) {
+               printf("%s: Machine type 0x%04x is not supported\n",
+                      __func__, nt->FileHeader.Machine);
+               return NULL;
+       }
+
        /* Calculate upper virtual address boundary */
        num_sections = nt->FileHeader.NumberOfSections;
        sections = (void *)&nt->OptionalHeader +
@@ -205,8 +234,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
        }
 
        /* Read 32/64bit specific header bits */
-       if (can_run_nt64 &&
-           (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)) {
+       if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
                IMAGE_NT_HEADERS64 *nt64 = (void *)nt;
                IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
                image_size = opt->SizeOfImage;
@@ -222,8 +250,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
                rel_size = opt->DataDirectory[rel_idx].Size;
                rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
                virt_size = ALIGN(virt_size, opt->SectionAlignment);
-       } else if (can_run_nt32 &&
-                  (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
+       } else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
                IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
                image_size = opt->SizeOfImage;
                efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);