From 1d959312e2f23c8ee6ed9432a6fa4416b267477b Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 1 Feb 2023 09:50:07 +0100 Subject: [PATCH] efi: arm64: Wire up BTI annotation in memory attributes table UEFI 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. Signed-off-by: Ard Biesheuvel Reviewed-by: Kees Cook Acked-by: Mark Rutland Reviewed-by: Will Deacon --- arch/arm64/kernel/efi.c | 15 +++++++++++++-- arch/arm64/kernel/traps.c | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 78ffd5a..db9007c 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -96,15 +96,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; } @@ -113,6 +122,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); @@ -128,7 +139,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); } /* diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 4c0caa5..1f366b9 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -492,6 +494,10 @@ void do_el0_bti(struct pt_regs *regs) void do_el1_bti(struct pt_regs *regs, unsigned long esr) { + if (efi_runtime_fixup_exception(regs, "BTI violation")) { + regs->pstate &= ~PSR_BTYPE_MASK; + return; + } die("Oops - BTI", regs, esr); } -- 2.7.4