* [PATCH 1/2] efi: Discover BTI support in runtime services regions
2023-02-01 13:25 [PATCH 0/2] efi: Enable BTI for EFI runtimes services Ard Biesheuvel
@ 2023-02-01 13:25 ` Ard Biesheuvel
2023-02-01 13:25 ` [PATCH 2/2] efi: arm64: Wire up BTI annotation in memory attributes table Ard Biesheuvel
2023-02-02 17:37 ` [PATCH 0/2] efi: Enable BTI for EFI runtimes services Kees Cook
2 siblings, 0 replies; 5+ messages in thread
From: Ard Biesheuvel @ 2023-02-01 13:25 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, Ard Biesheuvel, Catalin Marinas, Will Deacon,
Kees Cook, Mark Rutland
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.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
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(-)
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index b95241b1ca656f3c..78282ced50387dd3 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -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()
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
index 882104f43b3b0928..e2b9d2618c6727c6 100644
--- a/arch/arm/kernel/efi.c
+++ b/arch/arm/kernel/efi.c
@@ -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;
}
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index acaa39f6381a084b..8adca3b83c62a52b 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -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() \
({ \
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index b273900f45668587..908499486b00274e 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -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);
diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h
index 47d3ab0fcc36a186..29e9a0d84b16682f 100644
--- a/arch/riscv/include/asm/efi.h
+++ b/arch/riscv/include/asm/efi.h
@@ -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); \
diff --git a/arch/riscv/kernel/efi.c b/arch/riscv/kernel/efi.c
index 1aa540350abd31b0..aa6209a74c83ffc2 100644
--- a/arch/riscv/kernel/efi.c
+++ b/arch/riscv/kernel/efi.c
@@ -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);
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index b36596bf0fc38f4f..2e6fe430cb07bbbc 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -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;
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 0a9aba5f9ceff0bf..ab85bf8e165a3575 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -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");
}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 507390dda8b9c2f2..3ba27f34fe445aa3 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -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,
--
2.39.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/2] efi: arm64: Wire up BTI annotation in memory attributes table
2023-02-01 13:25 [PATCH 0/2] efi: Enable BTI for EFI runtimes services Ard Biesheuvel
2023-02-01 13:25 ` [PATCH 1/2] efi: Discover BTI support in runtime services regions Ard Biesheuvel
@ 2023-02-01 13:25 ` Ard Biesheuvel
2023-02-02 17:37 ` [PATCH 0/2] efi: Enable BTI for EFI runtimes services Kees Cook
2 siblings, 0 replies; 5+ messages in thread
From: Ard Biesheuvel @ 2023-02-01 13:25 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, Ard Biesheuvel, Catalin Marinas, Will Deacon,
Kees Cook, Mark Rutland
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 <ardb@kernel.org>
---
arch/arm64/kernel/efi.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 908499486b00274e..6a61553b64c51dcd 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -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);
}
/*
--
2.39.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 5+ messages in thread