Thanks you for the patch, it passed review and validation, we got it merged.

-Ning


-----Original Message-----
From: Sahil Rihan [mailto:sri...@fb.com] 
Sent: Friday, February 10, 2017 5:01 PM
To: tboot-devel@lists.sourceforge.net
Subject: [tboot-devel] Fix EFI memory map handling

Pass through the EFI memory map that's provided by grub2. Also remove the 
get_efi_memmap code which was buggy to start with (it was using the struct size 
instead of the descriptor size while creating the efi memmap). 

If no memmap is provided the kernel will panic early since it tries to compute 
the number of entries in the memmap by dividing memmap size by mempap descr 
size. Fixing the div by 0 lets the kernel make further progress, so it panics 
at a point where the panic is visible without needing earlyprintk.

Note that booting *without* noefi is a security risk since the EFI runtime is 
not part of the trust base after a dynamic launch. This can be addressed by 
extending the chain of trust from the bootloader to tboot.

Testing: Remove noefi kernel param, verify efibootmgr works. Boot with noefi 
kernel param, verify tboot works, but efibootmgr fails. Halt from inside 
kernel, verify tboot shutdown is called.

Signed-off-by: Sahil Rihan <sri...@fb.com>

 tboot/common/e820.c       |  70 
----------------------------------------------------------------------
 tboot/common/linux.c      |  39 ++++++++++++++++++++++-----------------
 tboot/common/loader.c     |  20 ++++++++++++++++++++
 tboot/include/e820.h      |   3 ---
 tboot/include/loader.h    |   2 ++
 tboot/include/multiboot.h |  11 +++++++++++
 6 files changed, 55 insertions(+), 90 deletions(-)

diff --git a/tboot/common/e820.c b/tboot/common/e820.c
--- a/tboot/common/e820.c
+++ b/tboot/common/e820.c
@@ -60,9 +60,6 @@
 static unsigned int g_nr_map;
 static memory_map_t *g_copy_e820_map = (memory_map_t *)TBOOT_E820_COPY_ADDR;
 
-static efi_memory_desc_t *efi_memmap_addr = NULL; -static uint32_t 
efi_memmap_size = 0;
-
 static inline void split64b(uint64_t val, uint32_t *val_lo, uint32_t *val_hi)  
{
     *val_lo = (uint32_t)(val & 0xffffffff); @@ -691,73 +688,6 @@
     *ram_size = last_fit_size;
 }
 
-#define PAGE_4K (1 << 12)
-
-efi_memory_desc_t
-*get_efi_memmap(uint32_t *memmap_size)
-{
-    unsigned int i;
-    memory_map_t *mp;
-    efi_memory_desc_t *ep;
-    uint32_t space_required;
-    
-    if (efi_memmap_addr == NULL){
-        /* we haven't done the conversion yet--is there room? */
-        space_required = sizeof(memory_map_t) * g_nr_map +
-            sizeof(efi_memory_desc_t) * g_nr_map + 0xf;
-        if (space_required >= TBOOT_E820_COPY_SIZE){
-            printk(TBOOT_ERR
-                   "Insufficient space to make EFI copy of E820 [%d => %d]\n",
-                   space_required, TBOOT_E820_COPY_SIZE);
-            return NULL;
-        }
-        /* for fun, we'll align the entries to 0x10 */
-        ep = efi_memmap_addr = (efi_memory_desc_t *)
-            ((TBOOT_E820_COPY_ADDR + sizeof(memory_map_t) * g_nr_map + 0xf)
-             & ~0xf);
-        /* printk(TBOOT_INFO"efi memmap base now at %p\n", ep); */
-        mp = g_copy_e820_map;
-        for (i = 0; i < g_nr_map; i++){
-            uint64_t length;
-            ep[i].phys_addr = ep[i].virt_addr = e820_base_64(mp + i);
-            ep[i].pad = 0;
-            length = e820_length_64(mp + i);
-            length += PAGE_4K - 1;
-            length &= ~(PAGE_4K - 1);
-            ep[i].num_pages = length / PAGE_4K;
-            switch (mp[i].type){
-            case E820_RAM:
-                ep[i].type = EFI_CONVENTIONAL_MEMORY;
-                ep[i].attribute |= EFI_MEMORY_WB;
-                break;
-            case E820_ACPI:
-                ep[i].type = EFI_ACPI_RECLAIM_MEMORY;
-                break;
-            case E820_NVS:
-                ep[i].type = EFI_ACPI_MEMORY_NVS;
-                break;
-            case E820_UNUSABLE:
-                ep[i].type = EFI_UNUSABLE_MEMORY;
-                break;
-            case E820_GAP:
-            case E820_MIXED:
-            case E820_RESERVED:
-            default:
-                ep[i].type = EFI_RESERVED_TYPE;
-                break;
-            }
-            /*
-              printk(TBOOT_INFO
-              "EFI entry %d at %016Lx type %d with %Lx pages\n",
-              i, ep[i].phys_addr, ep[i].type, ep[i].num_pages);
-            */
-            efi_memmap_size += sizeof(efi_memory_desc_t);
-        }
-    }
-    *memmap_size = efi_memmap_size;
-    return efi_memmap_addr;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tboot/common/linux.c b/tboot/common/linux.c
--- a/tboot/common/linux.c
+++ b/tboot/common/linux.c
@@ -327,6 +327,7 @@
             (struct screen_info_t *)(boot_params->screen_info);
         uint32_t address = 0;
         uint64_t long_address = 0UL;
+        uint32_t descr_size = 0, descr_vers = 0, mmap_size = 0, 
+ efi_mmap_addr = 0;
 
         /* loader signature */
         memcpy(&efi->efi_ldr_sig, "EL64", sizeof(uint32_t)); @@ -346,26 
+347,30 @@
             }
         }
 
-        /* EFI memmap descriptor size */
-        efi->efi_memdescr_size = 0x30;
-
-        /* EFI memmap descriptor version */
-        efi->efi_memdescr_ver = 1;
+        efi_mmap_addr = find_efi_memmap(g_ldr_ctx, &descr_size,
+                                        &descr_vers, &mmap_size);
+        if (!efi_mmap_addr) {
+            printk(TBOOT_INFO"failed to get EFI memory map\n");
+            efi->efi_memdescr_size = 0x1; // Avoid div by 0 in kernel.
+            efi->efi_memmap_size = 0;
+            efi->efi_memmap = 0;
+        } else {
+            efi->efi_memdescr_size = descr_size;
+            efi->efi_memdescr_ver = descr_vers;
+            efi->efi_memmap_size = mmap_size;
+            efi->efi_memmap = efi_mmap_addr;
+            /* From Multiboot2 spec:
+             * The bootloader must not load any part of the kernel, the 
modules,
+             * the Multiboot2 information structure, etc. higher than 4 GiB - 
1.
+             */
+            efi->efi_memmap_hi = 0;
 
-#if 1   /* EFI memmap addr */
-        {
-            uint32_t length;
-            efi->efi_memmap = (uint32_t) get_efi_memmap(&length);
-            /* EFI memmap size */
-            efi->efi_memmap_size = length;
+            printk(TBOOT_INFO "EFI memmap: memmap base: 0x%x, memmap size: 
0x%x\n",
+                  efi->efi_memmap, efi->efi_memmap_size);
+            printk(TBOOT_INFO "EFI memmap: descr size: 0x%x, descr version: 
0x%x\n",
+                  efi->efi_memdescr_size, efi->efi_memdescr_ver);
         }
-#else
-        efi->efi_memmap = 0;
-        efi->efi_memmap_size = 0x70;
-#endif
 
-        /* EFI memmap high--since we're consing our own, we know this == 0 */
-        efi->efi_memmap_hi = 0;
         /* if we're here, GRUB2 probably threw a framebuffer tag at us */
         load_framebuffer_info(g_ldr_ctx, (void *)scr);
     }
diff --git a/tboot/common/loader.c b/tboot/common/loader.c
--- a/tboot/common/loader.c
+++ b/tboot/common/loader.c
@@ -1899,6 +1899,26 @@
     return false;
 }
 
+uint32_t
+find_efi_memmap(loader_ctx *lctx, uint32_t *descr_size,
+                uint32_t *descr_vers, uint32_t *mmap_size) {
+    struct mb2_tag *start = NULL, *hit = NULL;
+    struct mb2_tag_efi_mmap *efi_mmap = NULL;
+
+    start = (struct mb2_tag *)(lctx->addr + 8);
+    hit = find_mb2_tag_type(start, MB2_TAG_TYPE_EFI_MMAP);
+    if (hit == NULL) {
+       return 0;
+    }
+
+    efi_mmap = (struct mb2_tag_efi_mmap *)hit;
+    *descr_size = efi_mmap->descr_size;
+    *descr_vers = efi_mmap->descr_vers;
+    *mmap_size = efi_mmap->size;
+    return (uint32_t)(&efi_mmap->efi_mmap); }
+
 bool
 is_loader_launch_efi(loader_ctx *lctx)
 {
diff --git a/tboot/include/e820.h b/tboot/include/e820.h
--- a/tboot/include/e820.h
+++ b/tboot/include/e820.h
@@ -89,9 +89,6 @@
 extern void get_highest_sized_ram(uint64_t size, uint64_t limit,
                                   uint64_t *ram_base, uint64_t *ram_size);
 
-/* EFI memory map support */
-extern efi_memory_desc_t *get_efi_memmap(uint32_t *memmap_size);
-
 /*
  * Memory map descriptor:
  */
diff --git a/tboot/include/loader.h b/tboot/include/loader.h
--- a/tboot/include/loader.h
+++ b/tboot/include/loader.h
@@ -76,6 +76,8 @@
 
 
 extern bool is_kernel_linux(void);
+extern uint32_t find_efi_memmap(loader_ctx *lctx, uint32_t *descr_size,
+                                uint32_t *descr_vers, uint32_t 
+*mmap_size);
 extern bool launch_kernel(bool is_measured_launch);  extern bool 
verify_loader_context(loader_ctx *lctx);  extern bool verify_modules(loader_ctx 
*lctx); diff --git a/tboot/include/multiboot.h b/tboot/include/multiboot.h
--- a/tboot/include/multiboot.h
+++ b/tboot/include/multiboot.h
@@ -98,6 +98,8 @@
 #define MB2_TAG_TYPE_ACPI_OLD         14
 #define MB2_TAG_TYPE_ACPI_NEW         15
 #define MB2_TAG_TYPE_NETWORK          16
+#define MB2_TAG_TYPE_EFI_MMAP         17
+#define MB2_TAG_TYPE_EFI_BS           18
 
 #ifndef __ASSEMBLY__
 
@@ -314,6 +316,15 @@
   struct mb2_vbe_mode_info_block vbe_mode_info;  };
 
+struct mb2_tag_efi_mmap
+{
+    uint32_t type;
+    uint32_t size;
+    uint32_t descr_size;
+    uint32_t descr_vers;
+    uint8_t efi_mmap[0];
+};
+
 struct mb2_fb_common
 {
   uint32_t type;



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech 
sites, SlashDot.org! http://sdm.link/slashdot 
_______________________________________________
tboot-devel mailing list
tboot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tboot-devel

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
tboot-devel mailing list
tboot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tboot-devel

Reply via email to