diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 4d2c6f3f0c41..a7503805c5bf 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -139,7 +139,12 @@ tsk .req x28 // current thread_info * Interrupt handling. */ .macro irq_handler +#ifdef CONFIG_STRICT_MEMORY_RWX + ldr x1, =handle_arch_irq + ldr x1, [x1] +#else ldr x1, handle_arch_irq +#endif mov x0, sp blr x1 .endm @@ -676,5 +681,9 @@ ENTRY(sys_rt_sigreturn_wrapper) b sys_rt_sigreturn ENDPROC(sys_rt_sigreturn_wrapper) +#ifdef CONFIG_STRICT_MEMORY_RWX +.data +#endif + ENTRY(handle_arch_irq) .quad 0 diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 123be98332e4..4287035aba9f 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -207,7 +207,11 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems msr vttbr_el2, xzr /* Hypervisor stub */ +#ifndef CONFIG_STRICT_MEMORY_RWX adr x0, __hyp_stub_vectors +#else + ldr x0, =__hyp_stub_vectors +#endif msr vbar_el2, x0 /* spsr */ diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 5161ad992091..dca88814f84f 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -8,6 +8,9 @@ #include #include #include +#ifdef CONFIG_STRICT_MEMORY_RWX +#include +#endif #define ARM_EXIT_KEEP(x) #define ARM_EXIT_DISCARD(x) x @@ -52,6 +55,9 @@ SECTIONS _text = .; HEAD_TEXT } +#ifdef CONFIG_STRICT_MEMORY_RWX + . = ALIGN(1<= (unsigned long)__init_data_begin) + return prot_sect_kernel | PMD_SECT_PXN; + if (addr >= (unsigned long)__init_begin) + return prot_sect_kernel | PMD_SECT_RDONLY; + if (addr >= (unsigned long)__start_rodata) + return prot_sect_kernel | PMD_SECT_RDONLY | PMD_SECT_PXN; + if (addr >= (unsigned long)_stext) + return prot_sect_kernel | PMD_SECT_RDONLY; + return prot_sect_kernel | PMD_SECT_PXN; +} +#else +pmdval_t get_pmd_prot_sect_kernel(unsigned long addr) +{ + return prot_sect_kernel; +} +#endif + static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, phys_addr_t phys) { @@ -204,7 +224,8 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, next = pmd_addr_end(addr, end); /* try section mapping first */ if (((addr | next | phys) & ~SECTION_MASK) == 0) - set_pmd(pmd, __pmd(phys | prot_sect_kernel)); + set_pmd(pmd, + __pmd(phys | get_pmd_prot_sect_kernel(addr))); else alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys)); phys += next - addr; diff --git a/include/linux/mm.h b/include/linux/mm.h index 43502d97d995..342f2234889a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -18,6 +18,10 @@ #include #include +#ifdef CONFIG_STRICT_MEMORY_RWX +extern char __init_data_begin[]; +#endif + struct mempolicy; struct anon_vma; struct anon_vma_chain;