All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/2] x86/efi: don't allocate memmap through memblock after mm_init()
@ 2017-01-05 12:51 ` Nicolai Stange
  0 siblings, 0 replies; 21+ messages in thread
From: Nicolai Stange @ 2017-01-05 12:51 UTC (permalink / raw)
  To: Ingo Molnar, Matt Fleming
  Cc: Thomas Gleixner, H. Peter Anvin,
	x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Mika Penttilä,
	Dan Williams, Ard Biesheuvel, Dave Young,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Nicolai Stange

With commit 4bc9f92e64c8 ("x86/efi-bgrt: Use efi_mem_reserve() to avoid
copying image data"), efi_bgrt_init() calls into the memblock allocator
through efi_mem_reserve() => efi_arch_mem_reserve() *after* mm_init()
has been called.

Indeed, KASAN reports a bad read access later on in
efi_free_boot_services():

  BUG: KASAN: use-after-free in efi_free_boot_services+0xae/0x24c
            at addr ffff88022de12740
  Read of size 4 by task swapper/0/0
  page:ffffea0008b78480 count:0 mapcount:-127
  mapping:          (null) index:0x1 flags: 0x5fff8000000000()
  [...]
  Call Trace:
   dump_stack+0x68/0x9f
   kasan_report_error+0x4c8/0x500
   kasan_report+0x58/0x60
   __asan_load4+0x61/0x80
   efi_free_boot_services+0xae/0x24c
   start_kernel+0x527/0x562
   x86_64_start_reservations+0x24/0x26
   x86_64_start_kernel+0x157/0x17a
   start_cpu+0x5/0x14

The instruction at the given address is the first read from the memmap's
memory, i.e. the read of md->type in efi_free_boot_services().

Note that the writes earlier in efi_arch_mem_reserve() don't splat because
they're done through early_memremap()ed addresses.

So, after memblock is gone, allocations should be done through the "normal"
page allocator. Introduce a helper, efi_memmap_alloc() for this. Use
it from efi_arch_mem_reserve(), efi_free_boot_services() and, for the sake
of consistency, from efi_fake_memmap() as well.

Note that for the latter, the memmap allocations cease to be page aligned.
This isn't needed though.

Fixes: 4bc9f92e64c8 ("x86/efi-bgrt: Use efi_mem_reserve() to avoid copying image data")
Signed-off-by: Nicolai Stange <nicstange-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
Applicable to next-20170105.
Boot-tested with an efi_fake_mem= parameter on x86_64.

v2 of this patch got a

  Tested-by: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>


Changes to v2:
 - Use the new efi_memmap_alloc() from efi_fake_memmap(), too.
 - Update commit message accordingly.

 arch/x86/platform/efi/quirks.c  |  4 ++--
 drivers/firmware/efi/fake_mem.c |  3 +--
 drivers/firmware/efi/memmap.c   | 38 ++++++++++++++++++++++++++++++++++++++
 include/linux/efi.h             |  1 +
 4 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 10aca63a50d7..30031d5293c4 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -214,7 +214,7 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
 
 	new_size = efi.memmap.desc_size * num_entries;
 
-	new_phys = memblock_alloc(new_size, 0);
+	new_phys = efi_memmap_alloc(num_entries);
 	if (!new_phys) {
 		pr_err("Could not allocate boot services memmap\n");
 		return;
@@ -355,7 +355,7 @@ void __init efi_free_boot_services(void)
 	}
 
 	new_size = efi.memmap.desc_size * num_entries;
-	new_phys = memblock_alloc(new_size, 0);
+	new_phys = efi_memmap_alloc(num_entries);
 	if (!new_phys) {
 		pr_err("Failed to allocate new EFI memmap\n");
 		return;
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 520a40e5e0e4..6c7d60c239b5 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -71,8 +71,7 @@ void __init efi_fake_memmap(void)
 	}
 
 	/* allocate memory for new EFI memmap */
-	new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map,
-					PAGE_SIZE);
+	new_memmap_phy = efi_memmap_alloc(new_nr_map);
 	if (!new_memmap_phy)
 		return;
 
diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c
index f03ddecd232b..78686443cb37 100644
--- a/drivers/firmware/efi/memmap.c
+++ b/drivers/firmware/efi/memmap.c
@@ -9,6 +9,44 @@
 #include <linux/efi.h>
 #include <linux/io.h>
 #include <asm/early_ioremap.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+
+static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
+{
+	return memblock_alloc(size, 0);
+}
+
+static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
+{
+	unsigned int order = get_order(size);
+	struct page *p = alloc_pages(GFP_KERNEL, order);
+
+	if (!p)
+		return 0;
+
+	return PFN_PHYS(page_to_pfn(p));
+}
+
+/**
+ * efi_memmap_alloc - Allocate memory for the EFI memory map
+ * @num_entries: Number of entries in the allocated map.
+ *
+ * Depending on whether mm_init() has already been invoked or not,
+ * either memblock or "normal" page allocation is used.
+ *
+ * Returns the physical address of the allocated memory map on
+ * success, zero on failure.
+ */
+phys_addr_t __init efi_memmap_alloc(unsigned int num_entries)
+{
+	unsigned long size = num_entries * efi.memmap.desc_size;
+
+	if (slab_is_available())
+		return __efi_memmap_alloc_late(size);
+
+	return __efi_memmap_alloc_early(size);
+}
 
 /**
  * __efi_memmap_init - Common code for mapping the EFI memory map
diff --git a/include/linux/efi.h b/include/linux/efi.h
index a07a476178cd..0c5420208c40 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -950,6 +950,7 @@ static inline efi_status_t efi_query_variable_store(u32 attributes,
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
 
+extern phys_addr_t __init efi_memmap_alloc(unsigned int num_entries);
 extern int __init efi_memmap_init_early(struct efi_memory_map_data *data);
 extern int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size);
 extern void __init efi_memmap_unmap(void);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2017-01-09 13:07 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-05 12:51 [PATCH v3 1/2] x86/efi: don't allocate memmap through memblock after mm_init() Nicolai Stange
2017-01-05 12:51 ` Nicolai Stange
     [not found] ` <20170105125130.2815-1-nicstange-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-05 12:51   ` [PATCH v3 2/2] efi: efi_mem_reserve(): don't reserve " Nicolai Stange
2017-01-05 12:51     ` Nicolai Stange
     [not found]     ` <20170105125130.2815-2-nicstange-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-06  8:35       ` Ard Biesheuvel
2017-01-06  8:35         ` Ard Biesheuvel
2017-01-06 13:02         ` Nicolai Stange
     [not found]           ` <87wpe8mjdk.fsf-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-06 16:41             ` Ard Biesheuvel
2017-01-06 16:41               ` Ard Biesheuvel
     [not found]               ` <CAKv+Gu_BnSf_LMsWHTeFaTak8iV1Cwex7WBEsufwYRrBzY8KzQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-01-06 17:46                 ` Nicolai Stange
2017-01-06 17:46                   ` Nicolai Stange
     [not found]                   ` <87showm682.fsf-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-06 19:28                     ` Ard Biesheuvel
2017-01-06 19:28                       ` Ard Biesheuvel
     [not found]                       ` <CAKv+Gu9B_amUwKuQCfMj6d96EpcLdeBDm732E0iqKSkRp11Z4w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-01-08  0:24                         ` Nicolai Stange
2017-01-08  0:24                           ` Nicolai Stange
2017-01-09 13:07                           ` Matt Fleming
2017-01-09 13:00                         ` Matt Fleming
2017-01-09 13:00                           ` Matt Fleming
2017-01-05 21:30   ` [PATCH v3 1/2] x86/efi: don't allocate memmap " Dan Williams
2017-01-05 21:30     ` Dan Williams
2017-01-09  6:43 ` [tip:efi/urgent] x86/efi: Don't " tip-bot for Nicolai Stange

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.