summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormlarkin <mlarkin@openbsd.org>2015-08-25 04:57:31 +0000
committermlarkin <mlarkin@openbsd.org>2015-08-25 04:57:31 +0000
commitbea8db73856639fbd5b7db5348e0addb7007f714 (patch)
tree85b336ed1a570429f928192aeb27d7dc22a947bf
parentSwitch from utimes() to utimensat() to $estore full nanosecond granularity (diff)
downloadwireguard-openbsd-bea8db73856639fbd5b7db5348e0addb7007f714.tar.xz
wireguard-openbsd-bea8db73856639fbd5b7db5348e0addb7007f714.zip
Enforce kernel w^x policy by properly setting NX (as needed) for
kernel text, PTEs, .rodata, data, bss and the symbol regions. This has been in snaps for a while with no reported fallout. The APTE space and MP/ACPI trampolines will be fixed next. ok deraadt@
-rw-r--r--sys/arch/i386/i386/locore.s10
-rw-r--r--sys/arch/i386/i386/pmap.c3
-rw-r--r--sys/arch/i386/i386/pmapae.c48
3 files changed, 48 insertions, 13 deletions
diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s
index 8d367a84a39..979e929a2a3 100644
--- a/sys/arch/i386/i386/locore.s
+++ b/sys/arch/i386/i386/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.160 2015/08/12 06:19:25 mlarkin Exp $ */
+/* $OpenBSD: locore.s,v 1.161 2015/08/25 04:57:31 mlarkin Exp $ */
/* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */
/*-
@@ -1668,15 +1668,15 @@ ENTRY(cpu_paenable)
rep
movsl
- movl %cr4, %eax
- orl $CR4_PAE, %eax
- movl %eax, %cr4 /* BANG!!! */
-
movl $MSR_EFER, %ecx
rdmsr
orl $EFER_NXE, %eax
wrmsr
+ movl %cr4, %eax
+ orl $CR4_PAE, %eax
+ movl %eax, %cr4 /* BANG!!! */
+
movl 12(%esp), %eax
subl $KERNBASE, %eax
movl %eax, %cr3 /* reload real PDPT */
diff --git a/sys/arch/i386/i386/pmap.c b/sys/arch/i386/i386/pmap.c
index d1f7c4daa56..4e89d37244b 100644
--- a/sys/arch/i386/i386/pmap.c
+++ b/sys/arch/i386/i386/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.182 2015/08/22 07:16:10 mlarkin Exp $ */
+/* $OpenBSD: pmap.c,v 1.183 2015/08/25 04:57:31 mlarkin Exp $ */
/* $NetBSD: pmap.c,v 1.91 2000/06/02 17:46:37 thorpej Exp $ */
/*
@@ -812,6 +812,7 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
bits = pmap_pte_set(va, pa, ((prot & PROT_WRITE) ? PG_RW : PG_RO) |
PG_V | global | PG_U | PG_M |
+ ((prot & PROT_EXEC) ? PG_X : 0) |
((pa & PMAP_NOCACHE) ? PG_N : 0) |
((pa & PMAP_WC) ? pmap_pg_wc : 0));
if (pmap_valid_entry(bits)) {
diff --git a/sys/arch/i386/i386/pmapae.c b/sys/arch/i386/i386/pmapae.c
index e3aa0f93132..e33391dce8a 100644
--- a/sys/arch/i386/i386/pmapae.c
+++ b/sys/arch/i386/i386/pmapae.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmapae.c,v 1.42 2015/08/22 07:16:10 mlarkin Exp $ */
+/* $OpenBSD: pmapae.c,v 1.43 2015/08/25 04:57:31 mlarkin Exp $ */
/*
* Copyright (c) 2006-2008 Michael Shalayeff
@@ -425,6 +425,10 @@ typedef u_int64_t pt_entry_t; /* PTE */
extern u_int32_t protection_codes[]; /* maps MI prot to i386 prot code */
extern boolean_t pmap_initialized; /* pmap_init done yet? */
+/* Segment boundaries */
+extern vaddr_t kernel_text, etext, __rodata_start, erodata, __data_start;
+extern vaddr_t edata, __bss_start, end, ssym, esym, PTmap;
+
/*
* MULTIPROCESSOR: special VA's/ PTE's are actually allocated inside a
* MAXCPUS*NPTECL array of PTE's, to avoid cache line thrashing
@@ -550,10 +554,16 @@ u_int32_t
pmap_pte_set_pae(vaddr_t va, paddr_t pa, u_int32_t bits)
{
pt_entry_t pte, *ptep = vtopte(va);
+ uint64_t nx;
pa &= PMAP_PA_MASK;
- pte = i386_atomic_testset_uq(ptep, pa | bits); /* zap! */
+ if (bits & PG_X)
+ nx = 0;
+ else
+ nx = PG_NX;
+
+ pte = i386_atomic_testset_uq(ptep, pa | bits | nx); /* zap! */
return (pte & ~PG_FRAME);
}
@@ -595,6 +605,7 @@ pmap_bootstrap_pae(void)
paddr_t ptaddr;
u_int32_t bits;
vaddr_t va, eva;
+ pt_entry_t pte;
if ((cpu_feature & CPUID_PAE) == 0 ||
(ecpu_feature & CPUID_NXE) == 0)
@@ -629,6 +640,13 @@ pmap_bootstrap_pae(void)
kpm->pm_stats.resident_count++;
}
bits = pmap_pte_bits_86(va) | pmap_pg_g;
+
+ /* At this point, only kernel text should be executable */
+ if (va >= (vaddr_t)&kernel_text && va <= (vaddr_t)&etext)
+ bits |= PG_X;
+ else
+ bits &= ~PG_X;
+
if (pmap_valid_entry(bits))
pmap_pte_set_pae(va, pmap_pte_paddr_86(va), bits);
}
@@ -670,7 +688,23 @@ pmap_bootstrap_pae(void)
bzero((void *)kpm->pm_pdir + 8, (PDSLOT_PTE-1) * 8);
/* TODO also reclaim old PDPs */
}
-}
+
+ /* Set region permissions */
+ for (va = (vaddr_t)&PTmap; va < KERNBASE; va += NBPD) {
+ pte = PDE(kpm, pdei(va));
+ PDE(kpm, pdei(va)) = pte | PG_NX;
+ }
+
+ pmap_write_protect(kpm, (vaddr_t)&kernel_text, (vaddr_t)&etext,
+ PROT_READ | PROT_EXEC);
+ pmap_write_protect(kpm, (vaddr_t)&__rodata_start,
+ (vaddr_t)&erodata, PROT_READ);
+ pmap_write_protect(kpm, (vaddr_t)&__data_start, (vaddr_t)&edata,
+ PROT_READ | PROT_WRITE);
+ pmap_write_protect(kpm, (vaddr_t)&__bss_start, (vaddr_t)&end,
+ PROT_READ | PROT_WRITE);
+ pmap_write_protect(kpm, ssym, esym, PROT_READ);
+ }
/*
* p t p f u n c t i o n s
@@ -800,13 +834,13 @@ pmap_pinit_pd_pae(struct pmap *pmap)
bzero((void *)pmap->pm_pdir, PDSLOT_PTE * sizeof(pd_entry_t));
/* put in recursive PDE to map the PTEs */
PDE(pmap, PDSLOT_PTE+0) = pmap->pm_pdidx[0] | PG_KW | PG_U |
- PG_M | PG_V;
+ PG_M | PG_V | PG_NX;
PDE(pmap, PDSLOT_PTE+1) = pmap->pm_pdidx[1] | PG_KW | PG_U |
- PG_M | PG_V;
+ PG_M | PG_V | PG_NX;
PDE(pmap, PDSLOT_PTE+2) = pmap->pm_pdidx[2] | PG_KW | PG_U |
- PG_M | PG_V;
+ PG_M | PG_V | PG_NX;
PDE(pmap, PDSLOT_PTE+3) = pmap->pm_pdidx[3] | PG_KW | PG_U |
- PG_M | PG_V;
+ PG_M | PG_V | PG_NX;
/*
* we need to lock pmaps_lock to prevent nkpde from changing on