efi: Enable BTI for EFI runtimes services
Subsystems (5)
Ard Biesheuvel
maintainercover efi: Enable BTI for EFI runtimes services
The EFI spec v2.10 introduces a global flag in the memory attributes table that indicates whether the EFI runtime code regions were emitted with BTI landing pads, and can therefore tolerate being mapped with BTI enforcement enabled.
Add the generic plumbing for this, and wire it up for arm64.
Ard Biesheuvel (2):
efi: Discover BTI support in runtime services regions
efi: arm64: Wire up BTI annotation in memory attributes table
arch/arm/include/asm/efi.h | 2 +- arch/arm/kernel/efi.c | 5 +++-- arch/arm64/include/asm/efi.h | 3 ++- arch/arm64/kernel/efi.c | 18 +++++++++++++++--- arch/riscv/include/asm/efi.h | 2 +- arch/riscv/kernel/efi.c | 3 ++- arch/x86/platform/efi/efi_64.c | 3 ++- drivers/firmware/efi/memattr.c | 9 +++++++-- include/linux/efi.h | 8 ++++++-- 9 files changed, 39 insertions(+), 14 deletions(-)
Signature · 1 line
2.39.0
Ard Biesheuvel
maintainerPATCH 1/2 efi: Discover BTI support in runtime services regions
Add the generic plumbing to detect whether or not the runtime code regions were constructed with BTI/IBT landing pads by the firmware, permitting the OS to enable enforcement when mapping these regions into the OS's address space.
--- arch/arm/include/asm/efi.h | 2 +- arch/arm/kernel/efi.c | 5 +++-- arch/arm64/include/asm/efi.h | 3 ++- arch/arm64/kernel/efi.c | 3 ++- arch/riscv/include/asm/efi.h | 2 +- arch/riscv/kernel/efi.c | 3 ++- arch/x86/platform/efi/efi_64.c | 3 ++- drivers/firmware/efi/memattr.c | 9 +++++++-- include/linux/efi.h | 8 ++++++-- 9 files changed, 26 insertions(+), 12 deletions(-)
arch/arm/include/asm/efi.h +1 -1
@@ -20,7 +20,7 @@ void efi_init(void);void arm_efi_init (void );int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md); -int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md); +int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md,bool );#define arch_efi_call_virt_setup () efi_virtmap_load()#define arch_efi_call_virt_teardown () efi_virtmap_unload()
arch/arm/kernel/efi.c +3 -2
@@ -23,7 +23,8 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) }int __init efi_set_mapping_permissions (struct mm_struct *mm, -efi_memory_desc_t *md) +efi_memory_desc_t *md, +bool ignored) {unsigned long base, size;
@@ -71,7 +72,7 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)* If stricter permissions were specified, apply them now. */ if (md->attribute & (EFI_MEMORY_RO |EFI_MEMORY_XP )) -return efi_set_mapping_permissions (mm, md); +return efi_set_mapping_permissions (mm, md, false);return 0 ; }
arch/arm64/include/asm/efi.h +2 -1
@@ -27,7 +27,8 @@ bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)#endif int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md); -int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md); +int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md, +bool has_bti);#define arch_efi_call_virt_setup () \ ({ \
arch/arm64/kernel/efi.c +2 -1
@@ -111,7 +111,8 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) }int __init efi_set_mapping_permissions (struct mm_struct *mm, -efi_memory_desc_t *md) +efi_memory_desc_t *md, +bool has_bti) {BUG_ON (md->type !=EFI_RUNTIME_SERVICES_CODE && md->type !=EFI_RUNTIME_SERVICES_DATA );
arch/riscv/include/asm/efi.h +1 -1
@@ -19,7 +19,7 @@ extern void efi_init(void);#endif int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md); -int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md); +int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md,bool );#define arch_efi_call_virt_setup () ({ \ sync_kernel_mappings(efi_mm.pgd); \
arch/riscv/kernel/efi.c +2 -1
@@ -78,7 +78,8 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) }int __init efi_set_mapping_permissions (struct mm_struct *mm, -efi_memory_desc_t *md) +efi_memory_desc_t *md, +bool ignored) {BUG_ON (md->type !=EFI_RUNTIME_SERVICES_CODE && md->type !=EFI_RUNTIME_SERVICES_DATA );
arch/x86/platform/efi/efi_64.c +2 -1
@@ -389,7 +389,8 @@ static int __init efi_update_mappings(efi_memory_desc_t *md, unsigned long pf)return err1 || err2; } -static int __init efi_update_mem_attr (struct mm_struct *mm,efi_memory_desc_t *md) +static int __init efi_update_mem_attr (struct mm_struct *mm,efi_memory_desc_t *md, +bool has_ibt) {unsigned long pf =0 ;
drivers/firmware/efi/memattr.c +7 -2
@@ -33,7 +33,7 @@ int __init efi_memattr_init(void)return -ENOMEM ; } -if (tbl->version >1 ) { +if (tbl->version >2 ) {pr_warn ("Unexpected EFI Memory Attributes table version %d\n" , tbl->version); goto unmap;
@@ -129,6 +129,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, efi_memattr_perm_setter fn) {efi_memory_attributes_table_t *tbl; +bool has_bti = false;int i, ret;if (tbl_size <=sizeof (*tbl))
@@ -150,6 +151,10 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm,return -ENOMEM ; } +if (tbl->version >1 && + (tbl->flags &EFI_MEMORY_ATTRIBUTES_FLAGS_RT_FORWARD_CONTROL_FLOW_GUARD )) + has_bti = true; +if (efi_enabled (EFI_DBG ))pr_info ("Processing EFI Memory Attributes table:\n" );
@@ -169,7 +174,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, efi_md_typeattr_format(buf, sizeof(buf), &md));if (valid) { - ret =fn (mm, &md); + ret =fn (mm, &md, has_bti);if (ret)pr_err ("Error updating mappings, skipping subsequent md's\n" ); }
include/linux/efi.h +6 -2
@@ -584,11 +584,15 @@ typedef struct {#define EFI_INVALID_TABLE_ADDR (~0UL) +// BIT0 implies that Runtime code includes the forward control flow guard +// instruction, such as X86 CET-IBT or ARM BTI. +#define EFI_MEMORY_ATTRIBUTES_FLAGS_RT_FORWARD_CONTROL_FLOW_GUARD 0x1 +typedef struct {u32 version;u32 num_entries;u32 desc_size; -u32 reserved; +u32 flags;efi_memory_desc_t entry[0 ]; }efi_memory_attributes_table_t ;
@@ -752,7 +756,7 @@ extern unsigned long efi_mem_attr_table;* argument in the page tables referred to by the * first argument. */ -typedef int (*efi_memattr_perm_setter )(struct mm_struct *,efi_memory_desc_t *); +typedef int (*efi_memattr_perm_setter )(struct mm_struct *,efi_memory_desc_t *,bool );extern int efi_memattr_init (void ); extern int efi_memattr_apply_permissions(struct mm_struct *mm,
Signature · 1 line
2.39.0
Ard Biesheuvel
maintainerPATCH 2/2 efi: arm64: Wire up BTI annotation in memory attributes table
In reply to Ard BiesheuvelUEFI v2.10 extends the EFI memory attributes table with a flag that indicates whether or not all RuntimeServicesCode regions were constructed with BTI landing pads, permitting the OS to map these regions with BTI restrictions enabled.
So let's take this into account on arm64.
--- arch/arm64/kernel/efi.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
arch/arm64/kernel/efi.c +13 -2
@@ -97,15 +97,24 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)return 0 ; } +struct set_perm_data { +const efi_memory_desc_t *md; +bool has_bti; +}; +static int __init set_permissions (pte_t *ptep,unsigned long addr,void *data) { -efi_memory_desc_t *md = data; +struct set_perm_data *spd = data; +const efi_memory_desc_t *md = spd->md;pte_t pte =READ_ONCE (*ptep);if (md->attribute &EFI_MEMORY_RO ) pte =set_pte_bit (pte,__pgprot (PTE_RDONLY ));if (md->attribute &EFI_MEMORY_XP ) pte =set_pte_bit (pte,__pgprot (PTE_PXN )); +else if (IS_ENABLED (CONFIG_ARM64_BTI_KERNEL ) && +system_supports_bti () && spd->has_bti) + pte =set_pte_bit (pte,__pgprot (PTE_GP ));set_pte (ptep, pte);return 0 ; }
@@ -114,6 +123,8 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md, bool has_bti) { +struct set_perm_data data = { md, has_bti }; +BUG_ON (md->type !=EFI_RUNTIME_SERVICES_CODE && md->type !=EFI_RUNTIME_SERVICES_DATA );
@@ -129,7 +140,7 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm,*/ return apply_to_page_range (mm, md->virt_addr, md->num_pages <<EFI_PAGE_SHIFT , - set_permissions, md); + set_permissions, &data); }/*
Signature · 1 line
2.39.0
Quoted 6 lines · Ard Biesheuvel
The EFI spec v2.10 introduces a global flag in the memory attributes table that indicates whether the EFI runtime code regions were emitted with BTI landing pads, and can therefore tolerate being mapped with BTI enforcement enabled.
Add the generic plumbing for this, and wire it up for arm64.
Looks nice! :)
Quoted 24 lines
Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Kees Cook <[email protected]>Cc Mark Rutland <[email protected]>Ard Biesheuvel (2):
efi: Discover BTI support in runtime services regions
efi: arm64: Wire up BTI annotation in memory attributes tablearch/arm/include/asm/efi.h | 2 +- arch/arm/kernel/efi.c | 5 +++-- arch/arm64/include/asm/efi.h | 3 ++- arch/arm64/kernel/efi.c | 18 +++++++++++++++--- arch/riscv/include/asm/efi.h | 2 +- arch/riscv/kernel/efi.c | 3 ++- arch/x86/platform/efi/efi_64.c | 3 ++- drivers/firmware/efi/memattr.c | 9 +++++++-- include/linux/efi.h | 8 ++++++-- 9 files changed, 39 insertions(+), 14 deletions(-)Signature · 1 line
2.39.0
Signature · 1 line
Kees Cook
Ard Biesheuvel
maintainerQuoted 7 lines · Kees Cook
Quoted 5 lines · Ard Biesheuvel
The EFI spec v2.10 introduces a global flag in the memory attributes table that indicates whether the EFI runtime code regions were emitted with BTI landing pads, and can therefore tolerate being mapped with BTI enforcement enabled.
Quoted 6 lines
Quoted 1 line
Add the generic plumbing for this, and wire it up for arm64.
Looks nice! :)
Reviewed-by Kees Cook <[email protected]>
Thanks
I've queued these up now in efi/next
Quoted 27 lines
Quoted 21 lines
Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Kees Cook <[email protected]>Cc Mark Rutland <[email protected]>Ard Biesheuvel (2):
efi: Discover BTI support in runtime services regions
efi: arm64: Wire up BTI annotation in memory attributes tablearch/arm/include/asm/efi.h | 2 +- arch/arm/kernel/efi.c | 5 +++-- arch/arm64/include/asm/efi.h | 3 ++- arch/arm64/kernel/efi.c | 18 +++++++++++++++--- arch/riscv/include/asm/efi.h | 2 +- arch/riscv/kernel/efi.c | 3 ++- arch/x86/platform/efi/efi_64.c | 3 ++- drivers/firmware/efi/memattr.c | 9 +++++++-- include/linux/efi.h | 8 ++++++-- 9 files changed, 39 insertions(+), 14 deletions(-)Quoted 3 lines
--
2.39.0--
Kees Cook