From: Sai Praneeth <sai.praneeth.prakhya@xxxxxxxxx> 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@0x73ae0000: 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@xxxxxxxxx> Suggested-by: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> Cc: Lee Chun-Yi <jlee@xxxxxxxx> Cc: Dave Young <dyoung@xxxxxxxxxx> Cc: Borislav Petkov <bp@xxxxxxxxx> Cc: Laszlo Ersek <lersek@xxxxxxxxxx> Cc: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> Cc: Dave Hansen <dave.hansen@xxxxxxxxx> Cc: Bhupesh Sharma <bhsharma@xxxxxxxxxx> Cc: Nicolai Stange <nicstange@xxxxxxxxx> Cc: Naresh Bhat <naresh.bhat@xxxxxxxxxx> Cc: Ricardo Neri <ricardo.neri@xxxxxxxxx> Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> Cc: Taku Izumi <izumi.taku@xxxxxxxxxxxxxx> Cc: Ravi Shankar <ravi.v.shankar@xxxxxxxxx> Cc: Matt Fleming <matt@xxxxxxxxxxxxxxxxxxx> Cc: Dan Williams <dan.j.williams@xxxxxxxxx> Cc: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html