summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-03-22 10:47:30 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-03-22 10:47:30 +0000
commitdb17f14929936c41e6265bc755b6a476de76388d (patch)
tree407d255f72ab5f9d81ae1c23bfcee61e02a2af28 /sys/arch
parent8ee73ce0f99999cbe894966fe11127d4526ba77d (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.c65
-rw-r--r--sys/arch/arm64/conf/kern.ldscript16
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 = .;
}