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