Commit cf1d2ffc authored by Ard Biesheuvel's avatar Ard Biesheuvel

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.
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
parent b0048092
...@@ -20,7 +20,7 @@ void efi_init(void); ...@@ -20,7 +20,7 @@ void efi_init(void);
void arm_efi_init(void); void arm_efi_init(void);
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); 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_setup() efi_virtmap_load()
#define arch_efi_call_virt_teardown() efi_virtmap_unload() #define arch_efi_call_virt_teardown() efi_virtmap_unload()
......
...@@ -23,7 +23,8 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) ...@@ -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, 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; unsigned long base, size;
...@@ -71,7 +72,7 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) ...@@ -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 stricter permissions were specified, apply them now.
*/ */
if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) 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; return 0;
} }
......
...@@ -27,7 +27,8 @@ bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg) ...@@ -27,7 +27,8 @@ bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
#endif #endif
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); 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() \ #define arch_efi_call_virt_setup() \
({ \ ({ \
......
...@@ -110,7 +110,8 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) ...@@ -110,7 +110,8 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data)
} }
int __init efi_set_mapping_permissions(struct mm_struct *mm, 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 && BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE &&
md->type != EFI_RUNTIME_SERVICES_DATA); md->type != EFI_RUNTIME_SERVICES_DATA);
......
...@@ -19,7 +19,7 @@ extern void efi_init(void); ...@@ -19,7 +19,7 @@ extern void efi_init(void);
#endif #endif
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); 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() ({ \ #define arch_efi_call_virt_setup() ({ \
sync_kernel_mappings(efi_mm.pgd); \ sync_kernel_mappings(efi_mm.pgd); \
......
...@@ -78,7 +78,8 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) ...@@ -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, 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 && BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE &&
md->type != EFI_RUNTIME_SERVICES_DATA); md->type != EFI_RUNTIME_SERVICES_DATA);
......
...@@ -389,7 +389,8 @@ static int __init efi_update_mappings(efi_memory_desc_t *md, unsigned long pf) ...@@ -389,7 +389,8 @@ static int __init efi_update_mappings(efi_memory_desc_t *md, unsigned long pf)
return err1 || err2; 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; unsigned long pf = 0;
......
...@@ -129,6 +129,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, ...@@ -129,6 +129,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm,
efi_memattr_perm_setter fn) efi_memattr_perm_setter fn)
{ {
efi_memory_attributes_table_t *tbl; efi_memory_attributes_table_t *tbl;
bool has_bti = false;
int i, ret; int i, ret;
if (tbl_size <= sizeof(*tbl)) if (tbl_size <= sizeof(*tbl))
...@@ -150,6 +151,10 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, ...@@ -150,6 +151,10 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm,
return -ENOMEM; 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)) if (efi_enabled(EFI_DBG))
pr_info("Processing EFI Memory Attributes table:\n"); pr_info("Processing EFI Memory Attributes table:\n");
...@@ -169,7 +174,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, ...@@ -169,7 +174,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm,
efi_md_typeattr_format(buf, sizeof(buf), &md)); efi_md_typeattr_format(buf, sizeof(buf), &md));
if (valid) { if (valid) {
ret = fn(mm, &md); ret = fn(mm, &md, has_bti);
if (ret) if (ret)
pr_err("Error updating mappings, skipping subsequent md's\n"); pr_err("Error updating mappings, skipping subsequent md's\n");
} }
......
...@@ -584,11 +584,15 @@ typedef struct { ...@@ -584,11 +584,15 @@ typedef struct {
#define EFI_INVALID_TABLE_ADDR (~0UL) #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 { typedef struct {
u32 version; u32 version;
u32 num_entries; u32 num_entries;
u32 desc_size; u32 desc_size;
u32 reserved; u32 flags;
efi_memory_desc_t entry[0]; efi_memory_desc_t entry[0];
} efi_memory_attributes_table_t; } efi_memory_attributes_table_t;
...@@ -751,7 +755,7 @@ extern unsigned long efi_mem_attr_table; ...@@ -751,7 +755,7 @@ extern unsigned long efi_mem_attr_table;
* argument in the page tables referred to by the * argument in the page tables referred to by the
* first argument. * 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_init(void);
extern int efi_memattr_apply_permissions(struct mm_struct *mm, extern int efi_memattr_apply_permissions(struct mm_struct *mm,
......
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