diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-03-22 10:47:30 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-03-22 10:47:30 +0000 |
commit | db17f14929936c41e6265bc755b6a476de76388d (patch) | |
tree | 407d255f72ab5f9d81ae1c23bfcee61e02a2af28 /sys/arch | |
parent | 8ee73ce0f99999cbe894966fe11127d4526ba77d (diff) |
Implement kernel W^X for arm64. For this purpose align the different segments
containing .text, .rodata and .data/.bss at 2MB boundaries and set the
appropriate access permissions on the block translations.
ok patrick@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/arm64/arm64/pmap.c | 65 | ||||
-rw-r--r-- | sys/arch/arm64/conf/kern.ldscript | 16 |
2 files changed, 46 insertions, 35 deletions
diff --git a/sys/arch/arm64/arm64/pmap.c b/sys/arch/arm64/arm64/pmap.c index 4d0c58c3663..e86840f5dc3 100644 --- a/sys/arch/arm64/arm64/pmap.c +++ b/sys/arch/arm64/arm64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.26 2017/03/16 20:15:07 kettenis Exp $ */ +/* $OpenBSD: pmap.c,v 1.27 2017/03/22 10:47:29 kettenis Exp $ */ /* * Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com> * @@ -255,6 +255,27 @@ const struct kmem_pa_mode kp_lN = { .kp_zero = 1, }; +const uint64_t ap_bits_user[8] = { + [PROT_NONE] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AP(2), + [PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(3), + [PROT_WRITE] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1), + [PROT_WRITE|PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1), + [PROT_EXEC] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(2), + [PROT_EXEC|PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(3), + [PROT_EXEC|PROT_WRITE] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1), + [PROT_EXEC|PROT_WRITE|PROT_READ]= ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1), +}; + +const uint64_t ap_bits_kern[8] = { + [PROT_NONE] = ATTR_PXN|ATTR_UXN|ATTR_AP(2), + [PROT_READ] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(2), + [PROT_WRITE] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(0), + [PROT_WRITE|PROT_READ] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(0), + [PROT_EXEC] = ATTR_UXN|ATTR_AF|ATTR_AP(2), + [PROT_EXEC|PROT_READ] = ATTR_UXN|ATTR_AF|ATTR_AP(2), + [PROT_EXEC|PROT_WRITE] = ATTR_UXN|ATTR_AF|ATTR_AP(0), + [PROT_EXEC|PROT_WRITE|PROT_READ] = ATTR_UXN|ATTR_AF|ATTR_AP(0), +}; /* * This is used for pmap_kernel() mappings, they are not to be removed @@ -1222,7 +1243,9 @@ pmap_bootstrap(long kvo, paddr_t lpt1, long kernelstart, long kernelend, // enable mappings for existing 'allocated' mapping in the bootstrap // page tables extern uint64_t *pagetable; - extern int *_end; + extern char __text_start[], _etext[]; + extern char __rodata_start[], _erodata[]; + extern char _end[]; vp2 = (void *)((long)&pagetable + kvo); struct mem_region *mp; ssize_t size; @@ -1234,11 +1257,21 @@ pmap_bootstrap(long kvo, paddr_t lpt1, long kernelstart, long kernelend, { paddr_t mappa = pa & ~(L2_SIZE-1); vaddr_t mapva = mappa - kvo; - if (mapva < (vaddr_t)&_end) + int prot = PROT_READ | PROT_WRITE; + + if (mapva < (vaddr_t)_end) continue; + + if (mapva >= (vaddr_t)__text_start && + mapva < (vaddr_t)_etext) + prot = PROT_READ | PROT_EXEC; + else if (mapva >= (vaddr_t)__rodata_start && + mapva < (vaddr_t)_erodata) + prot = PROT_READ; + vp2->l2[VP_IDX2(mapva)] = mappa | L2_BLOCK | - ATTR_AF | ATTR_IDX(PTE_ATTR_WB) | - ATTR_SH(SH_INNER); + ATTR_IDX(PTE_ATTR_WB) | ATTR_SH(SH_INNER) | + ap_bits_kern[prot]; } } @@ -1573,28 +1606,6 @@ pmap_proc_iflush(struct process *pr, vaddr_t va, vsize_t len) cpu_icache_sync_range(va, len); } -STATIC uint64_t ap_bits_user[8] = { - [PROT_NONE] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AP(2), - [PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(3), - [PROT_WRITE] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1), - [PROT_WRITE|PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1), - [PROT_EXEC] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(2), - [PROT_EXEC|PROT_READ] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(3), - [PROT_EXEC|PROT_WRITE] = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1), - [PROT_EXEC|PROT_WRITE|PROT_READ]= ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1), -}; - -STATIC uint64_t ap_bits_kern[8] = { - [PROT_NONE] = ATTR_PXN|ATTR_UXN|ATTR_AP(2), - [PROT_READ] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(2), - [PROT_WRITE] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(0), - [PROT_WRITE|PROT_READ] = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(0), - [PROT_EXEC] = ATTR_UXN|ATTR_AF|ATTR_AP(2), - [PROT_EXEC|PROT_READ] = ATTR_UXN|ATTR_AF|ATTR_AP(2), - [PROT_EXEC|PROT_WRITE] = ATTR_UXN|ATTR_AF|ATTR_AP(0), - [PROT_EXEC|PROT_WRITE|PROT_READ] = ATTR_UXN|ATTR_AF|ATTR_AP(0), -}; - void pmap_pte_insert(struct pte_desc *pted) { diff --git a/sys/arch/arm64/conf/kern.ldscript b/sys/arch/arm64/conf/kern.ldscript index d422242bc43..9a4dd31ba86 100644 --- a/sys/arch/arm64/conf/kern.ldscript +++ b/sys/arch/arm64/conf/kern.ldscript @@ -1,4 +1,4 @@ -/* $OpenBSD: kern.ldscript,v 1.4 2017/01/23 14:11:21 kettenis Exp $ */ +/* $OpenBSD: kern.ldscript,v 1.5 2017/03/22 10:47:29 kettenis Exp $ */ /* $NetBSD: ldscript.evbarm,v 1.2 2003/03/05 23:54:22 thorpej Exp $ */ OUTPUT_ARCH(aarch64) @@ -12,34 +12,35 @@ PHDRS openbsd_randomize PT_OPENBSD_RANDOMIZE; } -__ALIGN_SIZE = 0x1000; +__ALIGN_SIZE = 0x200000; __kernel_base = @KERNEL_BASE_VIRT@; ENTRY(_start) SECTIONS { . = __kernel_base; + PROVIDE (__text_start = .); .text : { *(.text .text.*) *(.stub) *(.glue_7t) *(.glue_7) } :text =0 - PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); /* Move rodata to the next page, so we can nuke X and W bit on it */ . = ALIGN(__ALIGN_SIZE); + PROVIDE (__rodata_start = .); .rodata : { *(.rodata .rodata.*) } :rodata - PROVIDE (erodata = .); - _erodata = .; + PROVIDE (_erodata = .); /* Move .random to the next page, so we can add W bit on it and .data */ . = ALIGN(__ALIGN_SIZE); + PROVIDE (__data_start = .); .openbsd.randomdata : { *(.openbsd.randomdata) @@ -52,8 +53,7 @@ SECTIONS { *(.sdata .sdata.*) } :data - PROVIDE (edata = .); - _edata = .; + PROVIDE (_edata = .); PROVIDE (__bss_start = .); .sbss : @@ -74,6 +74,6 @@ SECTIONS .bss section disappears because there are no input sections. */ . = ALIGN(64 / 8); } :data + PROVIDE (_end = .); PROVIDE (end = .); - _end = .; } |