Better page protections for arm64
v8 cover Better page protections for arm64
Hi,
This should be the final version of the series to add stricter page protections for arm64. The goal is to have text be RO/X and everything else be RW/NX.
v8: Minor tweaks, adding acks
Laura Abbott (2):
arm64: use fixmap for text patching
arm64: add better page protections to arm64
arch/arm64/Kconfig.debug | 23 ++++ arch/arm64/include/asm/cacheflush.h | 5 + arch/arm64/include/asm/fixmap.h | 1 + arch/arm64/kernel/insn.c | 47 +++++++- arch/arm64/kernel/vmlinux.lds.S | 17 ++- arch/arm64/mm/init.c | 1 + arch/arm64/mm/mm.h | 2 + arch/arm64/mm/mmu.c | 211 ++++++++++++++++++++++++++++++++---- 8 files changed, 280 insertions(+), 27 deletions(-)
Signature · 2 lines
Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v8 1/2 arm64: use fixmap for text patching
When kernel text is marked as read only, it cannot be modified directly. Use a fixmap to modify the text instead in a similar manner to x86 and arm.
---
v8: Included some headers and added BUG_ON for !page case
--- arch/arm64/include/asm/fixmap.h | 1 + arch/arm64/kernel/insn.c | 47 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-)
arch/arm64/include/asm/fixmap.h +1 -0
@@ -49,6 +49,7 @@ enum fixed_addresses {FIX_BTMAP_END = __end_of_permanent_fixed_addresses,FIX_BTMAP_BEGIN =FIX_BTMAP_END +TOTAL_FIX_BTMAPS -1 , +FIX_TEXT_POKE0 , __end_of_fixed_addresses };
arch/arm64/kernel/insn.c +46 -1
76 lines not on this page · raw message
Signature · 2 lines
Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v8 2/2 arm64: add better page protections to arm64
In reply to Laura AbbottAdd page protections for arm64 similar to those in arm. This is for security reasons to prevent certain classes of exploits. The current method:
- Map all memory as either RWX or RW. We round to the nearest section to avoid creating page tables before everything is mapped
- Once everything is mapped, if either end of the RWX section should not be X, we split the PMD and remap as necessary
- When initmem is to be freed, we change the permissions back to RW (using stop machine if necessary to flush the TLB)
- If CONFIG_DEBUG_RODATA is set, the read only sections are set read only.
--- arch/arm64/Kconfig.debug | 23 ++++ arch/arm64/include/asm/cacheflush.h | 5 + arch/arm64/kernel/vmlinux.lds.S | 17 ++- arch/arm64/mm/init.c | 1 + arch/arm64/mm/mm.h | 2 + arch/arm64/mm/mmu.c | 211 ++++++++++++++++++++++++++++++++---- 6 files changed, 233 insertions(+), 26 deletions(-)
arch/arm64/Kconfig.debug +23 -0
@@ -66,4 +66,27 @@ config DEBUG_SET_MODULE_RONX against certain classes of kernel exploits. If in doubt, say "N". +config DEBUG_RODATA + bool "Make kernel text and rodata read-only" + help + If this is set, kernel text and rodata will be made read-only. This + is to help catch accidental or malicious attempts to change the + kernel's executable code. Additionally splits rodata from kernel + text so it can be made explicitly non-executable. + + If in doubt, say Y + +config DEBUG_ALIGN_RODATA + depends on DEBUG_RODATA && !ARM64_64K_PAGES + bool "Align linker sections up to SECTION_SIZE" + help + If this option is enabled, sections that may potentially be marked as + read only or non-executable will be aligned up to the section size of + the kernel. This prevents sections from being split into pages and + avoids a potential TLB penalty. The downside is an increase in + alignment and potentially wasted space. Turn on this option if + performance is more important than memory pressure. + + If in doubt, say N + endmenu
arch/arm64/include/asm/cacheflush.h +5 -0
@@ -152,4 +152,9 @@ int set_memory_ro(unsigned long addr, int numpages);int set_memory_rw (unsigned long addr,int numpages);int set_memory_x (unsigned long addr,int numpages);int set_memory_nx (unsigned long addr,int numpages); + +#ifdef CONFIG_DEBUG_RODATA +void mark_rodata_ro (void ); +#endif +#endif
arch/arm64/kernel/vmlinux.lds.S +15 -2
@@ -8,6 +8,7 @@ #include <asm/thread_info.h> #include <asm/memory.h> #include <asm/page.h> +#include <asm/pgtable.h> #include "image.h"
@@ -49,6 +50,14 @@ PECOFF_FILE_ALIGNMENT = 0x200; #define PECOFF_EDATA_PADDING #endif +#ifdef CONFIG_DEBUG_ALIGN_RODATA +#define ALIGN_DEBUG_RO . = ALIGN(1<<SECTION_SHIFT); +#define ALIGN_DEBUG_RO_MIN(min) ALIGN_DEBUG_RO +#else +#define ALIGN_DEBUG_RO +#define ALIGN_DEBUG_RO_MIN(min) . = ALIGN(min); +#endif + SECTIONS { /*
@@ -71,6 +80,7 @@ SECTIONS _text = .; HEAD_TEXT } + ALIGN_DEBUG_RO .text : { /* Real text segment */ _stext = .; /* Text and read-only data */ __exception_text_start = .;
@@ -87,19 +97,22 @@ SECTIONS *(.got) /* Global offset table */ } + ALIGN_DEBUG_RO RO_DATA(PAGE_SIZE) EXCEPTION_TABLE(8) NOTES + ALIGN_DEBUG_RO _etext = .; /* End of text and rodata section */ - . = ALIGN(PAGE_SIZE); + ALIGN_DEBUG_RO_MIN(PAGE_SIZE) __init_begin = .; INIT_TEXT_SECTION(8) .exit.text : { ARM_EXIT_KEEP(EXIT_TEXT) } - . = ALIGN(16); + + ALIGN_DEBUG_RO_MIN(16) .init.data : { INIT_DATA INIT_SETUP(16)
arch/arm64/mm/init.c +1 -0
@@ -325,6 +325,7 @@ void __init mem_init(void)void free_initmem (void ) { +fixup_init ();free_initmem_default (0 );free_alternatives_memory (); }
arch/arm64/mm/mm.h +2 -0
@@ -1 +1,3 @@extern void __init bootmem_init (void ); + +void fixup_init (void );
arch/arm64/mm/mmu.c +187 -24
324 lines not on this page · raw message
Signature · 2 lines
Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
v8 cover Better page protections for arm64
In reply to Laura AbbottQuoted 3 lines · Laura Abbott
This should be the final version of the series to add stricter page protections for arm64. The goal is to have text be RO/X and everything else be RW/NX.
Applied. Thanks.
Signature · 1 line
Catalin