Commit 1d959312 authored by Ard Biesheuvel's avatar Ard Biesheuvel

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: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Acked-by: default avatarMark Rutland <mark.rutland@arm.com>
Reviewed-by: default avatarWill Deacon <will@kernel.org>
parent cf1d2ffc
...@@ -96,15 +96,24 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) ...@@ -96,15 +96,24 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
return 0; 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) 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); pte_t pte = READ_ONCE(*ptep);
if (md->attribute & EFI_MEMORY_RO) if (md->attribute & EFI_MEMORY_RO)
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
if (md->attribute & EFI_MEMORY_XP) if (md->attribute & EFI_MEMORY_XP)
pte = set_pte_bit(pte, __pgprot(PTE_PXN)); 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); set_pte(ptep, pte);
return 0; return 0;
} }
...@@ -113,6 +122,8 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm, ...@@ -113,6 +122,8 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm,
efi_memory_desc_t *md, efi_memory_desc_t *md,
bool has_bti) bool has_bti)
{ {
struct set_perm_data data = { md, has_bti };
BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE &&
md->type != EFI_RUNTIME_SERVICES_DATA); md->type != EFI_RUNTIME_SERVICES_DATA);
...@@ -128,7 +139,7 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm, ...@@ -128,7 +139,7 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm,
*/ */
return apply_to_page_range(mm, md->virt_addr, return apply_to_page_range(mm, md->virt_addr,
md->num_pages << EFI_PAGE_SHIFT, md->num_pages << EFI_PAGE_SHIFT,
set_permissions, md); set_permissions, &data);
} }
/* /*
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/efi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/sched/debug.h> #include <linux/sched/debug.h>
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include <asm/daifflags.h> #include <asm/daifflags.h>
#include <asm/debug-monitors.h> #include <asm/debug-monitors.h>
#include <asm/efi.h>
#include <asm/esr.h> #include <asm/esr.h>
#include <asm/exception.h> #include <asm/exception.h>
#include <asm/extable.h> #include <asm/extable.h>
...@@ -492,6 +494,10 @@ void do_el0_bti(struct pt_regs *regs) ...@@ -492,6 +494,10 @@ void do_el0_bti(struct pt_regs *regs)
void do_el1_bti(struct pt_regs *regs, unsigned long esr) 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); die("Oops - BTI", regs, esr);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment