diff options
author | 2015-08-25 04:57:31 +0000 | |
---|---|---|
committer | 2015-08-25 04:57:31 +0000 | |
commit | bea8db73856639fbd5b7db5348e0addb7007f714 (patch) | |
tree | 85b336ed1a570429f928192aeb27d7dc22a947bf | |
parent | Switch from utimes() to utimensat() to $estore full nanosecond granularity (diff) | |
download | wireguard-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.s | 10 | ||||
-rw-r--r-- | sys/arch/i386/i386/pmap.c | 3 | ||||
-rw-r--r-- | sys/arch/i386/i386/pmapae.c | 48 |
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 |