Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+25 -11
+1 -1
arch/arm/include/asm/efi.h
··· 20 20 void arm_efi_init(void); 21 21 22 22 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); 23 - int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); 23 + int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md, bool); 24 24 25 25 #define arch_efi_call_virt_setup() efi_virtmap_load() 26 26 #define arch_efi_call_virt_teardown() efi_virtmap_unload()
+3 -2
arch/arm/kernel/efi.c
··· 23 23 } 24 24 25 25 int __init efi_set_mapping_permissions(struct mm_struct *mm, 26 - efi_memory_desc_t *md) 26 + efi_memory_desc_t *md, 27 + bool ignored) 27 28 { 28 29 unsigned long base, size; 29 30 ··· 72 71 * If stricter permissions were specified, apply them now. 73 72 */ 74 73 if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) 75 - return efi_set_mapping_permissions(mm, md); 74 + return efi_set_mapping_permissions(mm, md, false); 76 75 return 0; 77 76 } 78 77
+2 -1
arch/arm64/include/asm/efi.h
··· 27 27 #endif 28 28 29 29 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); 30 - int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); 30 + int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md, 31 + bool has_bti); 31 32 32 33 #define arch_efi_call_virt_setup() \ 33 34 ({ \
+2 -1
arch/arm64/kernel/efi.c
··· 110 110 } 111 111 112 112 int __init efi_set_mapping_permissions(struct mm_struct *mm, 113 - efi_memory_desc_t *md) 113 + efi_memory_desc_t *md, 114 + bool has_bti) 114 115 { 115 116 BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && 116 117 md->type != EFI_RUNTIME_SERVICES_DATA);
+1 -1
arch/riscv/include/asm/efi.h
··· 19 19 #endif 20 20 21 21 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); 22 - int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); 22 + int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md, bool); 23 23 24 24 #define arch_efi_call_virt_setup() ({ \ 25 25 sync_kernel_mappings(efi_mm.pgd); \
+2 -1
arch/riscv/kernel/efi.c
··· 78 78 } 79 79 80 80 int __init efi_set_mapping_permissions(struct mm_struct *mm, 81 - efi_memory_desc_t *md) 81 + efi_memory_desc_t *md, 82 + bool ignored) 82 83 { 83 84 BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && 84 85 md->type != EFI_RUNTIME_SERVICES_DATA);
+2 -1
arch/x86/platform/efi/efi_64.c
··· 389 389 return err1 || err2; 390 390 } 391 391 392 - static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *md) 392 + static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *md, 393 + bool has_ibt) 393 394 { 394 395 unsigned long pf = 0; 395 396
+6 -1
drivers/firmware/efi/memattr.c
··· 129 129 efi_memattr_perm_setter fn) 130 130 { 131 131 efi_memory_attributes_table_t *tbl; 132 + bool has_bti = false; 132 133 int i, ret; 133 134 134 135 if (tbl_size <= sizeof(*tbl)) ··· 151 150 return -ENOMEM; 152 151 } 153 152 153 + if (tbl->version > 1 && 154 + (tbl->flags & EFI_MEMORY_ATTRIBUTES_FLAGS_RT_FORWARD_CONTROL_FLOW_GUARD)) 155 + has_bti = true; 156 + 154 157 if (efi_enabled(EFI_DBG)) 155 158 pr_info("Processing EFI Memory Attributes table:\n"); 156 159 ··· 174 169 efi_md_typeattr_format(buf, sizeof(buf), &md)); 175 170 176 171 if (valid) { 177 - ret = fn(mm, &md); 172 + ret = fn(mm, &md, has_bti); 178 173 if (ret) 179 174 pr_err("Error updating mappings, skipping subsequent md's\n"); 180 175 }
+6 -2
include/linux/efi.h
··· 584 584 585 585 #define EFI_INVALID_TABLE_ADDR (~0UL) 586 586 587 + // BIT0 implies that Runtime code includes the forward control flow guard 588 + // instruction, such as X86 CET-IBT or ARM BTI. 589 + #define EFI_MEMORY_ATTRIBUTES_FLAGS_RT_FORWARD_CONTROL_FLOW_GUARD 0x1 590 + 587 591 typedef struct { 588 592 u32 version; 589 593 u32 num_entries; 590 594 u32 desc_size; 591 - u32 reserved; 595 + u32 flags; 592 596 efi_memory_desc_t entry[0]; 593 597 } efi_memory_attributes_table_t; 594 598 ··· 755 751 * argument in the page tables referred to by the 756 752 * first argument. 757 753 */ 758 - typedef int (*efi_memattr_perm_setter)(struct mm_struct *, efi_memory_desc_t *); 754 + typedef int (*efi_memattr_perm_setter)(struct mm_struct *, efi_memory_desc_t *, bool); 759 755 760 756 extern int efi_memattr_init(void); 761 757 extern int efi_memattr_apply_permissions(struct mm_struct *mm,