[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1530582654-25662-7-git-send-email-sai.praneeth.prakhya@intel.com>
Date: Mon, 2 Jul 2018 18:50:54 -0700
From: Sai Praneeth Prakhya <sai.praneeth.prakhya@...el.com>
To: linux-efi@...r.kernel.org, linux-kernel@...r.kernel.org
Cc: Sai Praneeth <sai.praneeth.prakhya@...el.com>,
Lee Chun-Yi <jlee@...e.com>, Dave Young <dyoung@...hat.com>,
Borislav Petkov <bp@...en8.de>,
Laszlo Ersek <lersek@...hat.com>,
Jan Kiszka <jan.kiszka@...mens.com>,
Dave Hansen <dave.hansen@...el.com>,
Bhupesh Sharma <bhsharma@...hat.com>,
Nicolai Stange <nicstange@...il.com>,
Naresh Bhat <naresh.bhat@...aro.org>,
Ricardo Neri <ricardo.neri@...el.com>,
Peter Zijlstra <peterz@...radead.org>,
Taku Izumi <izumi.taku@...fujitsu.com>,
Ravi Shankar <ravi.v.shankar@...el.com>,
Matt Fleming <matt@...eblueprint.co.uk>,
Dan Williams <dan.j.williams@...el.com>,
Ard Biesheuvel <ard.biesheuvel@...aro.org>
Subject: [PATCH 6/6] efi: Fix unaligned fake memmap entries corrupting efi memory map
From: Sai Praneeth <sai.praneeth.prakhya@...el.com>
efi_fake_memmap() inserts user given fake memory map entries into the
original efi memory map using efi_memmmap_insert(). efi_memmmap_insert()
checks for EFI_PAGE_SIZE alignment and could fail if an unaligned efi
memory region is passed (Eg: efi_fake_memmap=1K@...3ae0000:
0x8000000000000000). Since EFI_PAGE_SIZE is 4K the above request fails,
but efi_fake_memmap() doesn't check for failures in efi_memmap_insert()
and installs an empty efi memory map from efi_memmap_alloc(). Since efi
memory map is corrupted all the later efi calls fail too. Hence, fix
this bug by changing the return type of efi_memmap_insert() from void to
int.
Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@...el.com>
Suggested-by: Ard Biesheuvel <ard.biesheuvel@...aro.org>
Cc: Lee Chun-Yi <jlee@...e.com>
Cc: Dave Young <dyoung@...hat.com>
Cc: Borislav Petkov <bp@...en8.de>
Cc: Laszlo Ersek <lersek@...hat.com>
Cc: Jan Kiszka <jan.kiszka@...mens.com>
Cc: Dave Hansen <dave.hansen@...el.com>
Cc: Bhupesh Sharma <bhsharma@...hat.com>
Cc: Nicolai Stange <nicstange@...il.com>
Cc: Naresh Bhat <naresh.bhat@...aro.org>
Cc: Ricardo Neri <ricardo.neri@...el.com>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Taku Izumi <izumi.taku@...fujitsu.com>
Cc: Ravi Shankar <ravi.v.shankar@...el.com>
Cc: Matt Fleming <matt@...eblueprint.co.uk>
Cc: Dan Williams <dan.j.williams@...el.com>
Cc: Ard Biesheuvel <ard.biesheuvel@...aro.org>
---
arch/x86/platform/efi/quirks.c | 8 +++++++-
drivers/firmware/efi/fake_mem.c | 11 +++++++++--
drivers/firmware/efi/memmap.c | 12 ++++++++----
include/linux/efi.h | 4 ++--
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 8fce327387e5..0e607ac24a3b 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -290,7 +290,13 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
return;
}
- efi_memmap_insert(&efi.memmap, new, &mr);
+ if (efi_memmap_insert(&efi.memmap, new, &mr)) {
+ pr_err("Failed to reserve EFI memory region\n");
+ early_memunmap(new, new_size);
+ efi_memmap_free(new_phys, num_entries, alloc_type);
+ return;
+ }
+
early_memunmap(new, new_size);
/* Free existing memory map before installing new memory map */
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 09b0fabf07fd..ae373af6931b 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -84,8 +84,15 @@ void __init efi_fake_memmap(void)
return;
}
- for (i = 0; i < nr_fake_mem; i++)
- efi_memmap_insert(&efi.memmap, new_memmap, &fake_mems[i]);
+ for (i = 0; i < nr_fake_mem; i++) {
+ if (efi_memmap_insert(&efi.memmap, new_memmap, &fake_mems[i])) {
+ pr_err("efi_fake_mem: Failed to create fake memmap\n");
+ early_memunmap(new_memmap,
+ efi.memmap.desc_size * new_nr_map);
+ efi_memmap_free(new_memmap_phy, new_nr_map, alloc_type);
+ return;
+ }
+ }
/* swap into new EFI memmap */
early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map);
diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c
index d4e3e114cf86..05a556e63ec2 100644
--- a/drivers/firmware/efi/memmap.c
+++ b/drivers/firmware/efi/memmap.c
@@ -290,9 +290,11 @@ int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range)
*
* It is suggested that you call efi_memmap_split_count() first
* to see how large @buf needs to be.
+ *
+ * Returns zero on success, a negative error code on failure.
*/
-void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
- struct efi_mem_range *mem)
+int __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
+ struct efi_mem_range *mem)
{
u64 m_start, m_end, m_attr;
efi_memory_desc_t *md;
@@ -311,8 +313,9 @@ void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
*/
if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) ||
!IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) {
- WARN_ON(1);
- return;
+ WARN(1, "Address 0x%llx - 0x%llx is not EFI_PAGE_SIZE aligned",
+ m_start, m_end);
+ return -EINVAL;
}
for (old = old_memmap->map, new = buf;
@@ -379,4 +382,5 @@ void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
md->attribute |= m_attr;
}
}
+ return 0;
}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index c9752c67d184..bca955205a3f 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1023,8 +1023,8 @@ extern int __init efi_memmap_install(phys_addr_t addr, unsigned int nr_map,
enum efi_memmap_type alloc_type);
extern int __init efi_memmap_split_count(efi_memory_desc_t *md,
struct range *range);
-extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap,
- void *buf, struct efi_mem_range *mem);
+extern int __init efi_memmap_insert(struct efi_memory_map *old_memmap,
+ void *buf, struct efi_mem_range *mem);
extern void __init efi_memmap_free(phys_addr_t mem, unsigned int num_entries,
enum efi_memmap_type alloc_type);
--
2.7.4
Powered by blists - more mailing lists