Many fixes to the vm system by Yuval Yarom and Bruce Evans
authorBruce Evans <bde@runx.oz.au>
Tue, 10 Aug 1993 00:00:00 +0000 (00:00 +0000)
committerBruce Evans <bde@runx.oz.au>
Tue, 10 Aug 1993 00:00:00 +0000 (00:00 +0000)
Mark VTEXT executables so that install does not cream them

   The following patches were provided by Yuval Yarom and fix the following
problems:

David Greenman:
(Descriptions are in his words. The patches were originally for BSDI, but are
applicable to 386BSD, modified by me when necessary. Patches appear here for
incorporation into 386BSD with his permission. -David Greenman)

1) The page daemon calls vm_map_entry_create to create entries in pager_map.
This call might block waiting for memory.

2) On rare combinations of memory and kernel sizes the system may fault when
allocating the page map structures.  The cause of this is that the estimation
of the number of pages is too low, and the map entry for the additional page
does not fit in the allocated page maps space.  For example if start is
0x10a000 and end is 0x7fe000, the initial estimation is 1755 pages, while
after allocating the required page map space the system finds out there are
1756 pages free.  When attempting to initialize the 1756'th page map entry
the system faults.

3)   Munmap(2) fails to ensure the user does not deallocates parts of
the kernel context of the process, allowing programs like
main(){munmap(0xfdbfe000,8192);} to crash the system with a double
fault.  A similar problem occurs with /dev/vga ioctl VGAIOCUNMAP.

4)   Mmap(2) fails to ensure the user does not maps on parts of the kernel
context of the process, allowing programs like
  #include <sys/types.h>
  #include <sys/mman.h>
  main(){mmap(0xfdbfe000,8192,PROT_READ,MAP_ANON|MAP_FIXED|MAP_PRIVATE,0,0);}
to crash the system with a double fault, and providing a great opportunity
for attaining super user privileges.

Yuval:
The cause of this problem is that, due to a bug in vm_mmap, unnamed
anonymous memory objects are marked as persistant, and remain in the
object cache.  The following patch fixes the problem.

Bruce Evans:
Here are patches to stop ptrace from accessing various inaccessible areas,
to stop direct access to various inaccessible areas from crashing the system,
and a test program.  The patch to sys_process.c requires patch00011 from
the patchkit.

Interesting inaccessible areas include:

1. Unmapped pages below the user area: trap.c faults in a page table just to
   check these.  Up to about 4M of page tables per process may be wasted.
   Not fixed.

2. User area.  Can be read and written using ptrace.  Overwriting the user
   stack and some other items can crash the system.  There may be security
   problems.  Not fixed.

3. User page tables.  Could be read and written using ptrace.  Fixed.

4. Kernel memory.  Could be read and written using ptrace.  Fixed.

5. Last 8M of memory (2 page tables worth).  The top 2 page tables are
   special and must not be used for mapping.  But ptracing to high addresses
   used them and caused panic("pmap_enter: already in pv_tab") on the
   second access.  Fixed.

Bruce

AUTHOR: Yoval Yarom (???), fwd by David Greenman (davidg@implode.rain.com)
AUTHOR: Bruce Evans (???), fwd by David Greenman (davidg@implode.rain.com)
AUTHOR: Paul Kranenburg (pk@cs.few.eur.nl) (trap.c add counter for vmstat)
386BSD-Patchkit: patch00137

usr/src/sys.386bsd/i386/i386/trap.c
usr/src/sys.386bsd/kern/kern_execve.c
usr/src/sys.386bsd/kern/sys_process.c
usr/src/sys.386bsd/vm/vm_glue.c
usr/src/sys.386bsd/vm/vm_map.c
usr/src/sys.386bsd/vm/vm_mmap.c
usr/src/sys.386bsd/vm/vm_page.c
usr/src/sys.386bsd/vm/vm_pageout.c

index 69623cb..57195f3 100644 (file)
  * SUCH DAMAGE.
  *
  *     @(#)trap.c      7.4 (Berkeley) 5/13/91
  * SUCH DAMAGE.
  *
  *     @(#)trap.c      7.4 (Berkeley) 5/13/91
+ *
+ * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
+ * --------------------         -----   ----------------------
+ * CURRENT PATCH LEVEL:         1       00137
+ * --------------------         -----   ----------------------
+ *
+ * 08 Apr 93   Bruce Evans             Several VM system fixes
+ *             Paul Kranenburg         Add counter for vmstat
  */
 static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/trap.c,v 1.2 92/01/21 14:22:13 william Exp $";
 
  */
 static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/trap.c,v 1.2 92/01/21 14:22:13 william Exp $";
 
@@ -159,6 +167,7 @@ copyfault:
 
        case T_ASTFLT|T_USER:           /* Allow process switch */
                astoff();
 
        case T_ASTFLT|T_USER:           /* Allow process switch */
                astoff();
+               cnt.v_soft++;
                if ((p->p_flag & SOWEUPC) && p->p_stats->p_prof.pr_scale) {
                        addupc(frame.tf_eip, &p->p_stats->p_prof, 1);
                        p->p_flag &= ~SOWEUPC;
                if ((p->p_flag & SOWEUPC) && p->p_stats->p_prof.pr_scale) {
                        addupc(frame.tf_eip, &p->p_stats->p_prof, 1);
                        p->p_flag &= ~SOWEUPC;
@@ -196,7 +205,10 @@ copyfault:
                break;
 
        case T_PAGEFLT:                 /* allow page faults in kernel mode */
                break;
 
        case T_PAGEFLT:                 /* allow page faults in kernel mode */
+#if 0
+               /* XXX - check only applies to 386's and 486's with WP off */
                if (code & PGEX_P) goto we_re_toast;
                if (code & PGEX_P) goto we_re_toast;
+#endif
 
                /* fall into */
        case T_PAGEFLT|T_USER:          /* page fault */
 
                /* fall into */
        case T_PAGEFLT|T_USER:          /* page fault */
@@ -210,6 +222,27 @@ copyfault:
                unsigned nss,v;
 
                va = trunc_page((vm_offset_t)eva);
                unsigned nss,v;
 
                va = trunc_page((vm_offset_t)eva);
+               /*
+                * Avoid even looking at pde_v(va) for high va's.   va's
+                * above VM_MAX_KERNEL_ADDRESS don't correspond to normal
+                * PDE's (half of them correspond to APDEpde and half to
+                * an unmapped kernel PDE).  va's betweeen 0xFEC00000 and
+                * VM_MAX_KERNEL_ADDRESS correspond to unmapped kernel PDE's
+                * (XXX - why are only 3 initialized when 6 are required to
+                * reach VM_MAX_KERNEL_ADDRESS?).  Faulting in an unmapped
+                * kernel page table would give inconsistent PTD's.
+                *
+                * XXX - faulting in unmapped page tables wastes a page if
+                * va turns out to be invalid.
+                *
+                * XXX - should "kernel address space" cover the kernel page
+                * tables?  Might have same problem with PDEpde as with
+                * APDEpde (or there may be no problem with APDEpde).
+                */
+               if (va > 0xFEBFF000) {
+                       rv = KERN_FAILURE;      /* becomes SIGBUS */
+                       goto nogo;
+               }
                /*
                 * It is only a kernel address space fault iff:
                 *      1. (type & T_USER) == 0  and
                /*
                 * It is only a kernel address space fault iff:
                 *      1. (type & T_USER) == 0  and
@@ -218,7 +251,7 @@ copyfault:
                 * The last can occur during an exec() copyin where the
                 * argument space is lazy-allocated.
                 */
                 * The last can occur during an exec() copyin where the
                 * argument space is lazy-allocated.
                 */
-               if (type == T_PAGEFLT && va >= 0xfe000000)
+               if (type == T_PAGEFLT && va >= KERNBASE)
                        map = kernel_map;
                else
                        map = &vm->vm_map;
                        map = kernel_map;
                else
                        map = &vm->vm_map;
index abbc419..95c76d1 100644 (file)
@@ -52,7 +52,7 @@
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
- * CURRENT PATCH LEVEL:         3       00069
+ * CURRENT PATCH LEVEL:         4       00137
  * --------------------         -----   ----------------------
  *
  * 05 Aug 92   Paul Kranenburg         Fixed #! as a magic number
  * --------------------         -----   ----------------------
  *
  * 05 Aug 92   Paul Kranenburg         Fixed #! as a magic number
@@ -60,6 +60,7 @@
  * 15 Aug 92    Terry Lambert           Fixed CMOS RAM size bug
  * 12 Dec 92   Julians Elischer        Place argc into user address space
  *                                     correctly
  * 15 Aug 92    Terry Lambert           Fixed CMOS RAM size bug
  * 12 Dec 92   Julians Elischer        Place argc into user address space
  *                                     correctly
+ * 10 Aug 93   Yoval Yarom             Fix for busy text on executables
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -474,6 +475,8 @@ dont_bother:
        p->p_regs[SP] = (unsigned) (argbuf - 1);
        setregs(p, exdata.ex_hdr.a_entry);
 
        p->p_regs[SP] = (unsigned) (argbuf - 1);
        setregs(p, exdata.ex_hdr.a_entry);
 
+       ndp->ni_vp->v_flag |= VTEXT;            /* mark vnode pure text */
+
        vput(ndp->ni_vp);
        FREE(ndp->ni_pnbuf, M_NAMEI);
 
        vput(ndp->ni_vp);
        FREE(ndp->ni_pnbuf, M_NAMEI);
 
index 1dd6901..f4c9c06 100644 (file)
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
- * CURRENT PATCH LEVEL:         1       00011
+ * CURRENT PATCH LEVEL:         1       00137
  * --------------------         -----   ----------------------
  *
  * 04 Sep 92   Paul Kranenburg         Fixed copy-on-write checking for pages
  *                                     other than anonymous (text pages, etc.)
  * --------------------         -----   ----------------------
  *
  * 04 Sep 92   Paul Kranenburg         Fixed copy-on-write checking for pages
  *                                     other than anonymous (text pages, etc.)
+ * 08 Apr 93   Bruce Evans             Several VM system fixes
  */
 
 #define IPCREG
  */
 
 #define IPCREG
@@ -274,6 +275,10 @@ procxmt(p)
        switch (ipc.req) {
        case PT_READ_I:
        case PT_READ_D:
        switch (ipc.req) {
        case PT_READ_I:
        case PT_READ_D:
+               if (!useracc(ipc.addr, sizeof(ipc.data), B_READ)) {
+                       ipc.error = EFAULT;
+                       break;
+               }
                ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data));
                break;
 
                ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data));
                break;
 
@@ -288,7 +293,7 @@ procxmt(p)
        case PT_WRITE_I:
        case PT_WRITE_D: {                              /* 04 Sep 92*/
                vm_prot_t prot;         /* current protection of region */
        case PT_WRITE_I:
        case PT_WRITE_D: {                              /* 04 Sep 92*/
                vm_prot_t prot;         /* current protection of region */
-               int cow;                 /* ensure copy-on-write happens */
+               int cow;                /* ensure copy-on-write happens */
 
                if (cow = (useracc(ipc.addr, sizeof(ipc.data), B_WRITE) == 0)) {
                        vm_offset_t     addr = (vm_offset_t)ipc.addr;
 
                if (cow = (useracc(ipc.addr, sizeof(ipc.data), B_WRITE) == 0)) {
                        vm_offset_t     addr = (vm_offset_t)ipc.addr;
@@ -299,7 +304,12 @@ procxmt(p)
                        vm_object_t     object;
                        vm_offset_t     objoff;
 
                        vm_object_t     object;
                        vm_offset_t     objoff;
 
-                       if (vm_region(&p->p_vmspace->vm_map, &addr, &size,
+                       /*
+                        * XXX - the useracc check is stronger than the vm
+                        * checks because the user page tables are in the map.
+                        */
+                       if (!useracc(ipc.addr, sizeof(ipc.data), B_READ) ||
+                           vm_region(&p->p_vmspace->vm_map, &addr, &size,
                                        &prot, &max_prot, &inh, &shared,
                                        &object, &objoff) != KERN_SUCCESS ||
                            vm_protect(&p->p_vmspace->vm_map, ipc.addr,
                                        &prot, &max_prot, &inh, &shared,
                                        &object, &objoff) != KERN_SUCCESS ||
                            vm_protect(&p->p_vmspace->vm_map, ipc.addr,
@@ -318,7 +328,6 @@ procxmt(p)
                        if (vm_protect(&p->p_vmspace->vm_map, ipc.addr,
                                        sizeof(ipc.data), FALSE,
                                        prot) != KERN_SUCCESS)
                        if (vm_protect(&p->p_vmspace->vm_map, ipc.addr,
                                        sizeof(ipc.data), FALSE,
                                        prot) != KERN_SUCCESS)
-
                                printf("ptrace: oops\n");
                break;
        }
                                printf("ptrace: oops\n");
                break;
        }
index c6fb9d3..6416ceb 100644 (file)
  *
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
  *
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
+ *
+ * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
+ * --------------------         -----   ----------------------
+ * CURRENT PATCH LEVEL:         1       00137
+ * --------------------         -----   ----------------------
+ *
+ * 08 Apr 93   Bruce Evans             Several VM system fixes
  */
 static char rcsid[] = "$Header: /usr/bill/working/sys/vm/RCS/vm_glue.c,v 1.2 92/01/21 21:58:21 william Exp $";
 
  */
 static char rcsid[] = "$Header: /usr/bill/working/sys/vm/RCS/vm_glue.c,v 1.2 92/01/21 21:58:21 william Exp $";
 
@@ -109,6 +116,22 @@ useracc(addr, len, rw)
        boolean_t rv;
        vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
 
        boolean_t rv;
        vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
 
+       /*
+        * XXX - specially disallow access to user page tables - they are
+        * in the map.
+        *
+        * XXX - don't specially disallow access to the user area - treat
+        * it as incorrectly as elsewhere.
+        *
+        * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  It was
+        * only used (as an end address) in trap.c.  Use it as an end
+        * address here too.
+        */
+       if ((vm_offset_t) addr >= VM_MAXUSER_ADDRESS + UPAGES * NBPG
+           || (vm_offset_t) addr + len > VM_MAXUSER_ADDRESS + UPAGES * NBPG
+           || (vm_offset_t) addr + len <= (vm_offset_t) addr)
+               return (FALSE);
+
        rv = vm_map_check_protection(&curproc->p_vmspace->vm_map,
            trunc_page(addr), round_page(addr+len-1), prot);
        return(rv == TRUE);
        rv = vm_map_check_protection(&curproc->p_vmspace->vm_map,
            trunc_page(addr), round_page(addr+len-1), prot);
        return(rv == TRUE);
index b421f80..b7a36e0 100644 (file)
  *
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
  *
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
+ *
+ * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
+ * --------------------         -----   ----------------------
+ * CURRENT PATCH LEVEL:         1       00137
+ * --------------------         -----   ----------------------
+ *
+ * 08 Apr 93   Yuval Yarom             Several VM system fixes
  */
 
 /*
  */
 
 /*
@@ -272,10 +279,10 @@ vm_map_entry_t vm_map_entry_create(map)
        vm_map_t        map;
 {
        vm_map_entry_t  entry;
        vm_map_t        map;
 {
        vm_map_entry_t  entry;
-       extern vm_map_t         kernel_map, kmem_map, mb_map, buffer_map;
+       extern vm_map_t         kernel_map, kmem_map, mb_map, buffer_map, pager_map;
 
        if (map == kernel_map || map == kmem_map || map == mb_map
 
        if (map == kernel_map || map == kmem_map || map == mb_map
-               || map == buffer_map) {
+               || map == buffer_map || map == pager_map) {
                if (entry = kentry_free)
                        kentry_free = kentry_free->next;
        } else
                if (entry = kentry_free)
                        kentry_free = kentry_free->next;
        } else
@@ -296,10 +303,10 @@ void vm_map_entry_dispose(map, entry)
        vm_map_t        map;
        vm_map_entry_t  entry;
 {
        vm_map_t        map;
        vm_map_entry_t  entry;
 {
-       extern vm_map_t         kernel_map, kmem_map, mb_map, buffer_map;
+       extern vm_map_t         kernel_map, kmem_map, mb_map, buffer_map, pager_map;
 
        if (map == kernel_map || map == kmem_map || map == mb_map
 
        if (map == kernel_map || map == kmem_map || map == mb_map
-               || map == buffer_map) {
+               || map == buffer_map || map == pager_map) {
                entry->next = kentry_free;
                kentry_free = entry;
        } else
                entry->next = kentry_free;
                kentry_free = entry;
        } else
index 28fefe8..a399bd4 100644 (file)
  * from: Utah $Hdr: vm_mmap.c 1.3 90/01/21$
  *
  *     @(#)vm_mmap.c   7.5 (Berkeley) 6/28/91
  * from: Utah $Hdr: vm_mmap.c 1.3 90/01/21$
  *
  *     @(#)vm_mmap.c   7.5 (Berkeley) 6/28/91
+ *
+ * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
+ * --------------------         -----   ----------------------
+ * CURRENT PATCH LEVEL:         1       00137
+ * --------------------         -----   ----------------------
+ *
+ * 08 Apr 93   Yuval Yarom             Several VM system fixes
  */
 
 /*
  */
 
 /*
@@ -149,6 +156,8 @@ smmap(p, uap, retval)
        if ((uap->flags & MAP_FIXED) && (addr & page_mask) || uap->len < 0)
                return(EINVAL);
        size = (vm_size_t) round_page(uap->len);
        if ((uap->flags & MAP_FIXED) && (addr & page_mask) || uap->len < 0)
                return(EINVAL);
        size = (vm_size_t) round_page(uap->len);
+       if ((uap->flags & MAP_FIXED) && (addr + size > VM_MAXUSER_ADDRESS))
+               return(EINVAL);
        /*
         * XXX if no hint provided for a non-fixed mapping place it after
         * the end of the largest possible heap.
        /*
         * XXX if no hint provided for a non-fixed mapping place it after
         * the end of the largest possible heap.
@@ -306,6 +315,8 @@ munmap(p, uap, retval)
        size = (vm_size_t) round_page(uap->len);
        if (size == 0)
                return(0);
        size = (vm_size_t) round_page(uap->len);
        if (size == 0)
                return(0);
+       if (addr + size >= VM_MAXUSER_ADDRESS)
+               return(EINVAL);
        if (!vm_map_is_allocated(&p->p_vmspace->vm_map, addr, addr+size,
            FALSE))
                return(EINVAL);
        if (!vm_map_is_allocated(&p->p_vmspace->vm_map, addr, addr+size,
            FALSE))
                return(EINVAL);
@@ -473,6 +484,13 @@ vm_mmap(map, addr, size, prot, flags, handle, foff)
                                vm_object_deallocate(object);
                        goto out;
                }
                                vm_object_deallocate(object);
                        goto out;
                }
+               /*
+                * The object of unnamed anonymous regions was just created
+                * find it for pager_cache.
+                */
+               if (handle == NULL)
+                       object = vm_object_lookup(pager);
+
                /*
                 * Don't cache anonymous objects.
                 * Loses the reference gained by vm_pager_allocate.
                /*
                 * Don't cache anonymous objects.
                 * Loses the reference gained by vm_pager_allocate.
index b8bab15..2dca777 100644 (file)
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
- * CURRENT PATCH LEVEL:         1       00074
+ * CURRENT PATCH LEVEL:         1       00137
  * --------------------         -----   ----------------------
  *
  * 22 Jan 93   Paul Mackerras          Fixed bug where pages got lost
  * --------------------         -----   ----------------------
  *
  * 22 Jan 93   Paul Mackerras          Fixed bug where pages got lost
+ * 08 Apr 93   Yuval Yarom             Several VM system fixes
  *
  */
 
  *
  */
 
@@ -263,7 +264,7 @@ vm_offset_t vm_page_startup(start, end, vaddr)
         */
 
        vm_page_free_count = npages =
         */
 
        vm_page_free_count = npages =
-               (end - start)/(PAGE_SIZE + sizeof(struct vm_page));
+               (end - start + sizeof(struct vm_page))/(PAGE_SIZE + sizeof(struct vm_page));
 
        /*
         *      Initialize the mem entry structures now, and
 
        /*
         *      Initialize the mem entry structures now, and
index de7cc30..c89e884 100644 (file)
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
- * CURRENT PATCH LEVEL:         1       00007
+ * CURRENT PATCH LEVEL:         1       00137
  * --------------------         -----   ----------------------
  *
  * 20 Aug 92   David Greenman          Removed un-necessary call to
  *                                     swapout_thread
  * --------------------         -----   ----------------------
  *
  * 20 Aug 92   David Greenman          Removed un-necessary call to
  *                                     swapout_thread
+ * 08 Aug 93   Paul Kranenburg         Add counters for vmstat
  */
 
 /*
  */
 
 /*
 #include "vm.h"
 #include "vm_page.h"
 #include "vm_pageout.h"
 #include "vm.h"
 #include "vm_page.h"
 #include "vm_pageout.h"
+#include "vmmeter.h"
 
 int    vm_pages_needed;                /* Event on which pageout daemon sleeps */
 int    vm_pageout_free_min = 0;        /* Stop pageout to wait for pagers at this free level */
 
 int    vm_page_free_min_sanity = 40;
 
 
 int    vm_pages_needed;                /* Event on which pageout daemon sleeps */
 int    vm_pageout_free_min = 0;        /* Stop pageout to wait for pagers at this free level */
 
 int    vm_page_free_min_sanity = 40;
 
+int    vm_page_pagesfreed;             /* Pages freed by page daemon */
+
 /*
  *     vm_pageout_scan does the dirty work for the pageout daemon.
  */
 /*
  *     vm_pageout_scan does the dirty work for the pageout daemon.
  */
@@ -335,6 +339,7 @@ vm_pageout_scan()
                page_shortage--;
        }
 
                page_shortage--;
        }
 
+       vm_page_pagesfreed += pages_freed;
        vm_page_unlock_queues();
 }
 
        vm_page_unlock_queues();
 }
 
@@ -389,6 +394,7 @@ void vm_pageout()
        while (TRUE) {
                thread_sleep((int) &vm_pages_needed, &vm_pages_needed_lock,
                             FALSE);
        while (TRUE) {
                thread_sleep((int) &vm_pages_needed, &vm_pages_needed_lock,
                             FALSE);
+               cnt.v_scan++;
                vm_pageout_scan();
                vm_pager_sync();
                simple_lock(&vm_pages_needed_lock);
                vm_pageout_scan();
                vm_pager_sync();
                simple_lock(&vm_pages_needed_lock);