forked from Minki/linux
A set of EFI fixes:
- Enforce NX on RO data in mixed EFI mode - Destroy workqueue in an error handling path to prevent UAF - Stop argument parser at '--' which is the delimiter for init - Treat a NULL command line pointer as empty instead of dereferncing it unconditionally. - Handle an unterminated command line correctly - Cleanup the 32bit code leftovers and remove obsolete documentation -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAl9CJMATHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYoXDXD/4ypNf6J1B7VX/eSO8IRW5LepYaatUb nOYESLCFF9RcWV4ff1ujs1Wow8rmTV0U+uCb6auSAMvmFu53VA5uJ9U8lHLjx/cZ 2qFpz6PScXr+cv4oPZ/8T4i7zuT887He1jtwsc+ABRHDUu9yd+qt0IZxqhLAqGQW dBal0WdZIfMftR1IBZvdbp8hNqHU/sEnVYJOovf2PpKNe8Z+IR2eeQVUoryM7V1b VNL+KtfpsYAbG5Gr4QVB18tHLnfEEJZHh8Dt7TlTOMF8hFJ6lAE7MutydWqHDMVv DlXtbs07C1aFIlpJuRdiwKHvNh4/9cUG0XgPqXW44NAXKK2yynV33oidlu9xjLNA uuFZ7Ni3XyHYgI4PyNX81tC4tG/krIRi5282KRh1OEUc7zgJvHRXo8cCy4HLgpEM VU4R7bI3LLBJgAdEHh/4EXNnryXOdk2ATUMcLgWGH54ZvnKRCFo1soNggzmiZb+2 WXVRHbSS3nsc0udmXmoUSqqWkud29o9r3KnuC/2qomCXMwtVSTEamTiok+86ICfc BiNZRu3DeoZqovyssBuSEeNGazrLsg8cGR0lhlpkAf0nu12y+quawdOj13SB8QcH XGrsCEmXD4jE9cpHt/+qIipyRzFt8RcamJCMH9m5ZNhx1GS6ddunxZAZFD2Fbg/9 +CSclYiPCfH0cw== =+nbs -----END PGP SIGNATURE----- Merge tag 'efi-urgent-2020-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull EFI fixes from Thomas Gleixner: - Enforce NX on RO data in mixed EFI mode - Destroy workqueue in an error handling path to prevent UAF - Stop argument parser at '--' which is the delimiter for init - Treat a NULL command line pointer as empty instead of dereferncing it unconditionally. - Handle an unterminated command line correctly - Cleanup the 32bit code leftovers and remove obsolete documentation * tag 'efi-urgent-2020-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: Documentation: efi: remove description of efi=old_map efi/x86: Move 32-bit code into efi_32.c efi/libstub: Handle unterminated cmdline efi/libstub: Handle NULL cmdline efi/libstub: Stop parsing arguments at "--" efi: add missed destroy_workqueue when efisubsys_init fails efi/x86: Mark kernel rodata non-executable for mixed mode
This commit is contained in:
commit
10c091b62e
@ -1233,8 +1233,7 @@
|
||||
efi= [EFI]
|
||||
Format: { "debug", "disable_early_pci_dma",
|
||||
"nochunk", "noruntime", "nosoftreserve",
|
||||
"novamap", "no_disable_early_pci_dma",
|
||||
"old_map" }
|
||||
"novamap", "no_disable_early_pci_dma" }
|
||||
debug: enable misc debug output.
|
||||
disable_early_pci_dma: disable the busmaster bit on all
|
||||
PCI bridges while in the EFI boot stub.
|
||||
@ -1251,8 +1250,6 @@
|
||||
novamap: do not call SetVirtualAddressMap().
|
||||
no_disable_early_pci_dma: Leave the busmaster bit set
|
||||
on all PCI bridges while in the EFI boot stub
|
||||
old_map [X86-64]: switch to the old ioremap-based EFI
|
||||
runtime services mapping. [Needs CONFIG_X86_UV=y]
|
||||
|
||||
efi_no_storage_paranoia [EFI; X86]
|
||||
Using this parameter you can use more than 50% of
|
||||
|
@ -81,11 +81,8 @@ extern unsigned long efi_fw_vendor, efi_config_table;
|
||||
kernel_fpu_end(); \
|
||||
})
|
||||
|
||||
|
||||
#define arch_efi_call_virt(p, f, args...) p->f(args)
|
||||
|
||||
#define efi_ioremap(addr, size, type, attr) ioremap_cache(addr, size)
|
||||
|
||||
#else /* !CONFIG_X86_32 */
|
||||
|
||||
#define EFI_LOADER_SIGNATURE "EL64"
|
||||
@ -125,9 +122,6 @@ struct efi_scratch {
|
||||
kernel_fpu_end(); \
|
||||
})
|
||||
|
||||
extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
|
||||
u32 type, u64 attribute);
|
||||
|
||||
#ifdef CONFIG_KASAN
|
||||
/*
|
||||
* CONFIG_KASAN may redefine memset to __memset. __memset function is present
|
||||
@ -143,17 +137,13 @@ extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
|
||||
#endif /* CONFIG_X86_32 */
|
||||
|
||||
extern struct efi_scratch efi_scratch;
|
||||
extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
|
||||
extern int __init efi_memblock_x86_reserve_range(void);
|
||||
extern void __init efi_print_memmap(void);
|
||||
extern void __init efi_memory_uc(u64 addr, unsigned long size);
|
||||
extern void __init efi_map_region(efi_memory_desc_t *md);
|
||||
extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
|
||||
extern void efi_sync_low_kernel_mappings(void);
|
||||
extern int __init efi_alloc_page_tables(void);
|
||||
extern int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
|
||||
extern void __init old_map_region(efi_memory_desc_t *md);
|
||||
extern void __init runtime_code_page_mkexec(void);
|
||||
extern void __init efi_runtime_update_mappings(void);
|
||||
extern void __init efi_dump_pagetable(void);
|
||||
extern void __init efi_apply_memmap_quirks(void);
|
||||
|
@ -49,7 +49,6 @@
|
||||
#include <asm/efi.h>
|
||||
#include <asm/e820/api.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/set_memory.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/x86_init.h>
|
||||
#include <asm/uv/uv.h>
|
||||
@ -496,74 +495,6 @@ void __init efi_init(void)
|
||||
efi_print_memmap();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_X86_32)
|
||||
|
||||
void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
|
||||
{
|
||||
u64 addr, npages;
|
||||
|
||||
addr = md->virt_addr;
|
||||
npages = md->num_pages;
|
||||
|
||||
memrange_efi_to_native(&addr, &npages);
|
||||
|
||||
if (executable)
|
||||
set_memory_x(addr, npages);
|
||||
else
|
||||
set_memory_nx(addr, npages);
|
||||
}
|
||||
|
||||
void __init runtime_code_page_mkexec(void)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
|
||||
/* Make EFI runtime service code area executable */
|
||||
for_each_efi_memory_desc(md) {
|
||||
if (md->type != EFI_RUNTIME_SERVICES_CODE)
|
||||
continue;
|
||||
|
||||
efi_set_executable(md, true);
|
||||
}
|
||||
}
|
||||
|
||||
void __init efi_memory_uc(u64 addr, unsigned long size)
|
||||
{
|
||||
unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
|
||||
u64 npages;
|
||||
|
||||
npages = round_up(size, page_shift) / page_shift;
|
||||
memrange_efi_to_native(&addr, &npages);
|
||||
set_memory_uc(addr, npages);
|
||||
}
|
||||
|
||||
void __init old_map_region(efi_memory_desc_t *md)
|
||||
{
|
||||
u64 start_pfn, end_pfn, end;
|
||||
unsigned long size;
|
||||
void *va;
|
||||
|
||||
start_pfn = PFN_DOWN(md->phys_addr);
|
||||
size = md->num_pages << PAGE_SHIFT;
|
||||
end = md->phys_addr + size;
|
||||
end_pfn = PFN_UP(end);
|
||||
|
||||
if (pfn_range_is_mapped(start_pfn, end_pfn)) {
|
||||
va = __va(md->phys_addr);
|
||||
|
||||
if (!(md->attribute & EFI_MEMORY_WB))
|
||||
efi_memory_uc((u64)(unsigned long)va, size);
|
||||
} else
|
||||
va = efi_ioremap(md->phys_addr, size,
|
||||
md->type, md->attribute);
|
||||
|
||||
md->virt_addr = (u64) (unsigned long) va;
|
||||
if (!va)
|
||||
pr_err("ioremap of 0x%llX failed!\n",
|
||||
(unsigned long long)md->phys_addr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Merge contiguous regions of the same type and attribute */
|
||||
static void __init efi_merge_regions(void)
|
||||
{
|
||||
|
@ -29,9 +29,35 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/set_memory.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
void __init efi_map_region(efi_memory_desc_t *md)
|
||||
{
|
||||
u64 start_pfn, end_pfn, end;
|
||||
unsigned long size;
|
||||
void *va;
|
||||
|
||||
start_pfn = PFN_DOWN(md->phys_addr);
|
||||
size = md->num_pages << PAGE_SHIFT;
|
||||
end = md->phys_addr + size;
|
||||
end_pfn = PFN_UP(end);
|
||||
|
||||
if (pfn_range_is_mapped(start_pfn, end_pfn)) {
|
||||
va = __va(md->phys_addr);
|
||||
|
||||
if (!(md->attribute & EFI_MEMORY_WB))
|
||||
set_memory_uc((unsigned long)va, md->num_pages);
|
||||
} else {
|
||||
va = ioremap_cache(md->phys_addr, size);
|
||||
}
|
||||
|
||||
md->virt_addr = (unsigned long)va;
|
||||
if (!va)
|
||||
pr_err("ioremap of 0x%llX failed!\n", md->phys_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* To make EFI call EFI runtime service in physical addressing mode we need
|
||||
* prolog/epilog before/after the invocation to claim the EFI runtime service
|
||||
@ -58,11 +84,6 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init efi_map_region(efi_memory_desc_t *md)
|
||||
{
|
||||
old_map_region(md);
|
||||
}
|
||||
|
||||
void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
|
||||
void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
|
||||
|
||||
@ -107,6 +128,15 @@ efi_status_t __init efi_set_virtual_address_map(unsigned long memory_map_size,
|
||||
|
||||
void __init efi_runtime_update_mappings(void)
|
||||
{
|
||||
if (__supported_pte_mask & _PAGE_NX)
|
||||
runtime_code_page_mkexec();
|
||||
if (__supported_pte_mask & _PAGE_NX) {
|
||||
efi_memory_desc_t *md;
|
||||
|
||||
/* Make EFI runtime service code area executable */
|
||||
for_each_efi_memory_desc(md) {
|
||||
if (md->type != EFI_RUNTIME_SERVICES_CODE)
|
||||
continue;
|
||||
|
||||
set_memory_x(md->virt_addr, md->num_pages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,6 +259,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
|
||||
npages = (__end_rodata - __start_rodata) >> PAGE_SHIFT;
|
||||
rodata = __pa(__start_rodata);
|
||||
pfn = rodata >> PAGE_SHIFT;
|
||||
|
||||
pf = _PAGE_NX | _PAGE_ENC;
|
||||
if (kernel_map_pages_in_pgd(pgd, pfn, rodata, npages, pf)) {
|
||||
pr_err("Failed to map kernel rodata 1:1\n");
|
||||
return 1;
|
||||
|
@ -381,6 +381,7 @@ static int __init efisubsys_init(void)
|
||||
efi_kobj = kobject_create_and_add("efi", firmware_kobj);
|
||||
if (!efi_kobj) {
|
||||
pr_err("efi: Firmware registration failed.\n");
|
||||
destroy_workqueue(efi_rts_wq);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -424,6 +425,7 @@ err_unregister:
|
||||
generic_ops_unregister();
|
||||
err_put:
|
||||
kobject_put(efi_kobj);
|
||||
destroy_workqueue(efi_rts_wq);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -187,20 +187,28 @@ int efi_printk(const char *fmt, ...)
|
||||
*/
|
||||
efi_status_t efi_parse_options(char const *cmdline)
|
||||
{
|
||||
size_t len = strlen(cmdline) + 1;
|
||||
size_t len;
|
||||
efi_status_t status;
|
||||
char *str, *buf;
|
||||
|
||||
if (!cmdline)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
len = strnlen(cmdline, COMMAND_LINE_SIZE - 1) + 1;
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, len, (void **)&buf);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
str = skip_spaces(memcpy(buf, cmdline, len));
|
||||
memcpy(buf, cmdline, len - 1);
|
||||
buf[len - 1] = '\0';
|
||||
str = skip_spaces(buf);
|
||||
|
||||
while (*str) {
|
||||
char *param, *val;
|
||||
|
||||
str = next_arg(str, ¶m, &val);
|
||||
if (!val && !strcmp(param, "--"))
|
||||
break;
|
||||
|
||||
if (!strcmp(param, "nokaslr")) {
|
||||
efi_nokaslr = true;
|
||||
|
Loading…
Reference in New Issue
Block a user