Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys add support for non-executable mappings (where the hardw...
details: https://anonhg.NetBSD.org/src/rev/90561ba6fcf4
branches: trunk
changeset: 550888:90561ba6fcf4
user: chs <chs%NetBSD.org@localhost>
date: Sun Aug 24 17:52:28 2003 +0000
description:
add support for non-executable mappings (where the hardware allows this)
and make the stack and heap non-executable by default. the changes
fall into two basic catagories:
- pmap and trap-handler changes. these are all MD:
= alpha: we already track per-page execute permission with the (software)
PG_EXEC bit, so just have the trap handler pay attention to it.
= i386: use a new GDT segment for %cs for processes that have no
executable mappings above a certain threshold (currently the
bottom of the stack). track per-page execute permission with
the last unused PTE bit.
= powerpc/ibm4xx: just use the hardware exec bit.
= powerpc/oea: we already track per-page exec bits, but the hardware only
implements non-exec mappings at the segment level. so track the
number of executable mappings in each segment and turn on the no-exec
segment bit iff the count is 0. adjust the trap handler to deal.
= sparc (sun4m): fix our use of the hardware protection bits.
fix the trap handler to recognize text faults.
= sparc64: split the existing unified TSB into data and instruction TSBs,
and only load TTEs into the appropriate TSB(s) for the permissions.
fix the trap handler to check for execute permission.
= not yet implemented: amd64, hppa, sh5
- changes in all the emulations that put a signal trampoline on the stack.
instead, we now put the trampoline into a uvm_aobj and map that into
the process separately.
originally from openbsd, adapted for netbsd by me.
diffstat:
sys/arch/alpha/alpha/pmap.c | 94 ++++----
sys/arch/alpha/alpha/trap.c | 58 ++--
sys/arch/alpha/include/pmap.h | 7 +-
sys/arch/alpha/include/pte.h | 6 +-
sys/arch/i386/i386/freebsd_machdep.c | 6 +-
sys/arch/i386/i386/ibcs2_machdep.c | 7 +-
sys/arch/i386/i386/machdep.c | 21 +-
sys/arch/i386/i386/pmap.c | 78 ++++++-
sys/arch/i386/i386/svr4_machdep.c | 8 +-
sys/arch/i386/i386/trap.c | 10 +-
sys/arch/i386/include/pcb.h | 3 +-
sys/arch/i386/include/pmap.h | 7 +-
sys/arch/i386/include/pte.h | 4 +-
sys/arch/i386/include/segments.h | 6 +-
sys/arch/i386/include/vmparam.h | 12 +-
sys/arch/powerpc/ibm4xx/pmap.c | 56 ++--
sys/arch/powerpc/ibm4xx/trap.c | 10 +-
sys/arch/powerpc/include/oea/pmap.h | 12 +-
sys/arch/powerpc/include/oea/pte.h | 4 +-
sys/arch/powerpc/oea/pmap.c | 157 ++++++-------
sys/arch/powerpc/powerpc/trap.c | 20 +-
sys/arch/sparc/sparc/pmap.c | 157 +++++++++-----
sys/arch/sparc/sparc/trap.c | 16 +-
sys/arch/sparc64/include/pmap.h | 3 +-
sys/arch/sparc64/sparc64/clock.c | 42 +--
sys/arch/sparc64/sparc64/db_interface.c | 71 +++---
sys/arch/sparc64/sparc64/locore.s | 67 ++---
sys/arch/sparc64/sparc64/pmap.c | 313 ++++++++++++----------------
sys/compat/aout/aout_exec.c | 9 +-
sys/compat/aoutm68k/aoutm68k_exec.c | 9 +-
sys/compat/darwin/darwin_exec.c | 7 +-
sys/compat/freebsd/freebsd_exec.c | 7 +-
sys/compat/hpux/hpux_exec.c | 7 +-
sys/compat/ibcs2/ibcs2_exec.c | 7 +-
sys/compat/irix/irix_exec.c | 5 +-
sys/compat/irix/irix_exec.h | 3 +-
sys/compat/linux/arch/i386/linux_machdep.c | 8 +-
sys/compat/linux/common/linux_exec.c | 8 +-
sys/compat/mach/mach_exec.c | 7 +-
sys/compat/netbsd32/netbsd32_netbsd.c | 7 +-
sys/compat/osf1/osf1_exec.c | 7 +-
sys/compat/pecoff/pecoff_emul.c | 7 +-
sys/compat/sunos/sunos_exec.c | 9 +-
sys/compat/sunos32/sunos32_exec.c | 7 +-
sys/compat/svr4/svr4_exec.c | 7 +-
sys/compat/svr4_32/svr4_32_exec.c | 7 +-
sys/compat/ultrix/ultrix_misc.c | 7 +-
sys/kern/exec_subr.c | 11 +-
sys/kern/kern_exec.c | 91 ++++++-
sys/kern/kern_resource.c | 6 +-
sys/sys/proc.h | 3 +-
sys/uvm/uvm_unix.c | 12 +-
52 files changed, 846 insertions(+), 667 deletions(-)
diffs (truncated from 3850 to 300 lines):
diff -r a6796a15b8e2 -r 90561ba6fcf4 sys/arch/alpha/alpha/pmap.c
--- a/sys/arch/alpha/alpha/pmap.c Sun Aug 24 17:36:32 2003 +0000
+++ b/sys/arch/alpha/alpha/pmap.c Sun Aug 24 17:52:28 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.202 2003/08/07 16:26:32 agc Exp $ */
+/* $NetBSD: pmap.c,v 1.203 2003/08/24 17:52:28 chs Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -145,7 +145,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.202 2003/08/07 16:26:32 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.203 2003/08/24 17:52:28 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1554,9 +1554,6 @@
return;
}
- if (prot & VM_PROT_WRITE)
- return;
-
PMAP_LOCK(pmap);
bits = pte_prot(pmap, prot);
@@ -2518,39 +2515,23 @@
up = protection_codes[1];
for (prot = 0; prot < 8; prot++) {
- kp[prot] = 0; up[prot] = 0;
- switch (prot) {
- case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
- kp[prot] |= PG_ASM;
- up[prot] |= 0;
- break;
-
- case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
- case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
- kp[prot] |= PG_EXEC; /* software */
- up[prot] |= PG_EXEC; /* software */
- /* FALLTHROUGH */
-
- case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
- kp[prot] |= PG_ASM | PG_KRE;
- up[prot] |= PG_URE | PG_KRE;
- break;
-
- case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
- kp[prot] |= PG_ASM | PG_KWE;
- up[prot] |= PG_UWE | PG_KWE;
- break;
-
- case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
- case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
- kp[prot] |= PG_EXEC; /* software */
- up[prot] |= PG_EXEC; /* software */
- /* FALLTHROUGH */
-
- case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
- kp[prot] |= PG_ASM | PG_KWE | PG_KRE;
- up[prot] |= PG_UWE | PG_URE | PG_KWE | PG_KRE;
- break;
+ kp[prot] = PG_ASM;
+ up[prot] = 0;
+
+ if (prot & VM_PROT_READ) {
+ kp[prot] |= PG_KRE;
+ up[prot] |= PG_KRE | PG_URE;
+ }
+ if (prot & VM_PROT_WRITE) {
+ kp[prot] |= PG_KWE;
+ up[prot] |= PG_KWE | PG_UWE;
+ }
+ if (prot & VM_PROT_EXECUTE) {
+ kp[prot] |= PG_EXEC | PG_KRE;
+ up[prot] |= PG_EXEC | PG_KRE | PG_URE;
+ } else {
+ kp[prot] |= PG_FOE;
+ up[prot] |= PG_FOE;
}
}
}
@@ -2722,20 +2703,24 @@
* pmap_emulate_reference:
*
* Emulate reference and/or modified bit hits.
+ * Return 1 if this was an execute fault on a non-exec mapping,
+ * otherwise return 0.
*/
-void
-pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int write)
+int
+pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int type)
{
+ struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap;
pt_entry_t faultoff, *pte;
struct vm_page *pg;
paddr_t pa;
boolean_t didlock = FALSE;
+ boolean_t exec = FALSE;
long cpu_id = cpu_number();
#ifdef DEBUG
if (pmapdebug & PDB_FOLLOW)
printf("pmap_emulate_reference: %p, 0x%lx, %d, %d\n",
- l, v, user, write);
+ l, v, user, type);
#endif
/*
@@ -2755,13 +2740,19 @@
if (l->l_proc->p_vmspace == NULL)
panic("pmap_emulate_reference: bad p_vmspace");
#endif
- PMAP_LOCK(l->l_proc->p_vmspace->vm_map.pmap);
+ PMAP_LOCK(pmap);
didlock = TRUE;
- pte = pmap_l3pte(l->l_proc->p_vmspace->vm_map.pmap, v, NULL);
+ pte = pmap_l3pte(pmap, v, NULL);
/*
* We'll unlock below where we're done with the PTE.
*/
}
+ exec = pmap_pte_exec(pte);
+ if (!exec && type == ALPHA_MMCSR_FOE) {
+ if (didlock)
+ PMAP_UNLOCK(pmap);
+ return (1);
+ }
#ifdef DEBUG
if (pmapdebug & PDB_FOLLOW) {
printf("\tpte = %p, ", pte);
@@ -2777,7 +2768,7 @@
* pmap_emulate_reference(), and the bits aren't guaranteed,
* for them...
*/
- if (write) {
+ if (type == ALPHA_MMCSR_FOW) {
if (!(*pte & (user ? PG_UWE : PG_UWE | PG_KWE)))
panic("pmap_emulate_reference: write but unwritable");
if (!(*pte & PG_FOW))
@@ -2798,7 +2789,7 @@
* it now.
*/
if (didlock)
- PMAP_UNLOCK(l->l_proc->p_vmspace->vm_map.pmap);
+ PMAP_UNLOCK(pmap);
#ifdef DEBUG
if (pmapdebug & PDB_FOLLOW)
@@ -2806,7 +2797,8 @@
#endif
#ifdef DIAGNOSTIC
if (!PAGE_IS_MANAGED(pa))
- panic("pmap_emulate_reference(%p, 0x%lx, %d, %d): pa 0x%lx not managed", l, v, user, write, pa);
+ panic("pmap_emulate_reference(%p, 0x%lx, %d, %d): "
+ "pa 0x%lx not managed", l, v, user, type, pa);
#endif
/*
@@ -2822,17 +2814,21 @@
PMAP_HEAD_TO_MAP_LOCK();
simple_lock(&pg->mdpage.pvh_slock);
- if (write) {
+ if (type == ALPHA_MMCSR_FOW) {
pg->mdpage.pvh_attrs |= (PGA_REFERENCED|PGA_MODIFIED);
- faultoff = PG_FOR | PG_FOW | PG_FOE;
+ faultoff = PG_FOR | PG_FOW;
} else {
pg->mdpage.pvh_attrs |= PGA_REFERENCED;
- faultoff = PG_FOR | PG_FOE;
+ faultoff = PG_FOR;
+ if (exec) {
+ faultoff |= PG_FOE;
+ }
}
pmap_changebit(pg, 0, ~faultoff, cpu_id);
simple_unlock(&pg->mdpage.pvh_slock);
PMAP_HEAD_TO_MAP_UNLOCK();
+ return (0);
}
#ifdef DEBUG
diff -r a6796a15b8e2 -r 90561ba6fcf4 sys/arch/alpha/alpha/trap.c
--- a/sys/arch/alpha/alpha/trap.c Sun Aug 24 17:36:32 2003 +0000
+++ b/sys/arch/alpha/alpha/trap.c Sun Aug 24 17:52:28 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.80 2003/06/23 11:01:00 martin Exp $ */
+/* $NetBSD: trap.c,v 1.81 2003/08/24 17:52:29 chs Exp $ */
/*-
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.80 2003/06/23 11:01:00 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.81 2003/08/24 17:52:29 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -232,17 +232,16 @@
trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
struct trapframe *framep)
{
- register struct lwp *l;
- register int i;
+ struct lwp *l;
u_int64_t ucode;
- int user;
+ vm_prot_t ftype;
+ int i, user;
#if defined(DDB)
int call_debugger = 1;
#endif
l = curlwp;
- uvmexp.traps++; /* XXXSMP: NOT ATOMIC */
ucode = 0;
user = (framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0;
if (user)
@@ -360,8 +359,10 @@
else
KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
- pmap_emulate_reference(l, a0, user,
- a1 == ALPHA_MMCSR_FOW ? 1 : 0);
+ if (pmap_emulate_reference(l, a0, user, a1)) {
+ ftype = VM_PROT_EXECUTE;
+ goto do_fault;
+ }
if (user)
KERNEL_PROC_UNLOCK(l);
@@ -372,12 +373,23 @@
case ALPHA_MMCSR_INVALTRANS:
case ALPHA_MMCSR_ACCESS:
{
- register vaddr_t va;
- register struct vmspace *vm = NULL;
- register struct vm_map *map;
- vm_prot_t ftype;
+ vaddr_t va;
+ struct vmspace *vm = NULL;
+ struct vm_map *map;
int rv;
+ switch (a2) {
+ case -1: /* instruction fetch fault */
+ ftype = VM_PROT_EXECUTE;
+ break;
+ case 0: /* load instruction */
+ ftype = VM_PROT_READ;
+ break;
+ case 1: /* store instruction */
+ ftype = VM_PROT_WRITE;
+ break;
+ }
+
if (user)
KERNEL_PROC_LOCK(l);
else {
@@ -427,6 +439,7 @@
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
+do_fault:
if (user == 0 && (a0 >= VM_MIN_KERNEL_ADDRESS ||
l->l_addr->u_pcb.pcb_onfault == 0))
map = kernel_map;
@@ -435,28 +448,11 @@
map = &vm->vm_map;
}
- switch (a2) {
- case -1: /* instruction fetch fault */
- case 0: /* load instruction */
- ftype = VM_PROT_READ;
- break;
- case 1: /* store instruction */
- ftype = VM_PROT_WRITE;
- break;
-#ifdef DIAGNOSTIC
- default: /* XXX gcc -Wuninitialized */
- if (user)
- KERNEL_PROC_UNLOCK(l);
- else
- KERNEL_UNLOCK();
- goto dopanic;
-#endif
- }
-
va = trunc_page((vaddr_t)a0);
rv = uvm_fault(map, va,
Home |
Main Index |
Thread Index |
Old Index