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: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
Родитель
b0048092f7
Коммит
cf1d2ffcc6
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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() \
|
||||
({ \
|
||||
|
|
|
@ -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,
|
||||
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);
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -751,7 +755,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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче