]> Zhao Yanbai Git Server - minix.git/commitdiff
vm: fix a null dereference on out-of-memory
authorBen Gras <ben@minix3.org>
Fri, 9 Nov 2012 15:50:31 +0000 (16:50 +0100)
committerBen Gras <ben@minix3.org>
Fri, 9 Nov 2012 17:36:51 +0000 (18:36 +0100)
. also make other out-of-memory conditions less fatal
. add a test case for a user program using all the memory
  it can
. remove some diagnostic prints for situations that are normal
  when running out of memory so running the test isn't noisy

servers/pm/forkexit.c
servers/vm/arch/i386/pagetable.c
servers/vm/exit.c
servers/vm/fork.c
servers/vm/region.c
test/Makefile
test/run
test/test64.c [new file with mode: 0644]

index 345f386c6a09d28fbf0bb5e74cc16f90a308baa8..6e01f41eeaf84c68631e1b98c3a6e02c5e953926 100644 (file)
@@ -75,7 +75,6 @@ int do_fork()
 
   /* Memory part of the forking. */
   if((s=vm_fork(rmp->mp_endpoint, next_child, &child_ep)) != OK) {
-       printf("PM: vm_fork failed: %d\n", s);
        return s;
   }
 
@@ -176,7 +175,6 @@ int do_srv_fork()
        panic("do_fork finds wrong child slot: %d", next_child);
 
   if((s=vm_fork(rmp->mp_endpoint, next_child, &child_ep)) != OK) {
-       printf("PM: vm_fork failed: %d\n", s);
        return s;
   }
 
index 1e5f6e8e4304756261ac9a194c1a343c8d0e7ecf..67a21ed4b1d30e4e71e73bfb6aa2ef8a3da44fc0 100644 (file)
@@ -478,7 +478,6 @@ int pt_ptalloc_in_range(pt_t *pt, vir_bytes start, vir_bytes end,
                                 * and pt_ptalloc leaves the directory
                                 * and other data in a consistent state.
                                 */
-                               printf("pt_ptalloc_in_range: pt_ptalloc failed\n");
                                return r;
                        }
                }
@@ -692,9 +691,6 @@ int pt_writemap(struct vmproc * vmp,
                int pde = I386_VM_PDE(v);
                int pte = I386_VM_PTE(v);
 
-               if(!v) { printf("VM: warning: making zero page for %d\n",
-                       vmp->vm_endpoint); }
-
                assert(!(v % I386_PAGE_SIZE));
                assert(pte >= 0 && pte < I386_VM_PT_ENTRIES);
                assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
@@ -825,7 +821,7 @@ int pt_new(pt_t *pt)
  * its physical address as we'll need that in the future. Verify it's
  * page-aligned.
  */
-       int i;
+       int i, r;
 
        /* Don't ever re-allocate/re-move a certain process slot's
         * page directory once it's been created. This is a fraction
@@ -847,8 +843,8 @@ int pt_new(pt_t *pt)
        pt->pt_virtop = 0;
 
         /* Map in kernel. */
-        if(pt_mapkernel(pt) != OK)
-                panic("pt_new: pt_mapkernel failed");
+        if((r=pt_mapkernel(pt)) != OK)
+               return r;
 
        return OK;
 }
@@ -1122,12 +1118,13 @@ int pt_mapkernel(pt_t *pt)
 
        /* Kernel also wants various mappings of its own. */
        for(i = 0; i < kernmappings; i++) {
-               if(pt_writemap(NULL, pt,
+               int r;
+               if((r=pt_writemap(NULL, pt,
                        kern_mappings[i].vir_addr,
                        kern_mappings[i].phys_addr,
                        kern_mappings[i].len,
-                       kern_mappings[i].flags, 0) != OK) {
-                       panic("pt_mapkernel: pt_writemap failed");
+                       kern_mappings[i].flags, 0)) != OK) {
+                       return r;
                }
        }
 
index 894a131939423cb646868caf3b57b10ae78faa74..0c64c5165d715bbb18e55131da97b0099fc318a7 100644 (file)
@@ -120,7 +120,8 @@ int do_procctl(message *msg)
                                && msg->m_source != VFS_PROC_NR)
                                return EPERM;
                        free_proc(vmp);
-                       pt_new(&vmp->vm_pt);
+                       if(pt_new(&vmp->vm_pt) != OK)
+                               panic("VMPPARAM_CLEAR: pt_new failed");
                        pt_bind(&vmp->vm_pt, vmp);
                        return OK;
                default:
index 16e4dd1160a3d65822b3fdd8a9c087d39d333c27..5a8c57e066650f8876deba15b11c8d671d9f9c26 100644 (file)
@@ -71,7 +71,6 @@ int do_fork(message *msg)
 #endif
 
   if(pt_new(&vmc->vm_pt) != OK) {
-       printf("VM: fork: pt_new failed\n");
        return ENOMEM;
   }
 
index b37729f38050745465749e858e90249005d269b9..373b96bbdc86edb0587c89c54ac8cef2dd0a50eb 100644 (file)
@@ -431,9 +431,6 @@ static vir_bytes region_find_slot_range(struct vmproc *vmp,
        }
 
        if(!foundflag) {
-               printf("VM: region_find_slot: no 0x%lx bytes found for %d between 0x%lx and 0x%lx\n",
-                       length, vmp->vm_endpoint, minv, maxv);
-               util_stacktrace();
                return SLOT_FAIL;
        }
 
@@ -537,8 +534,12 @@ mem_type_t *memtype;
        }
 
        /* If a new event is specified, invoke it. */
-       if(newregion->memtype->ev_new)
-               newregion->memtype->ev_new(newregion);
+       if(newregion->memtype->ev_new) {
+               if(newregion->memtype->ev_new(newregion) != OK) {
+                       /* ev_new will have freed and removed the region */
+                       return NULL;
+               }
+       }
 
        if(mapflags & MF_PREALLOC) {
                if(map_handle_memory(vmp, newregion, 0, length, 1) != OK) {
index 104b8d6558810504725a6948981b93729bf80245..8b4c6521b0a468fe439f065851bc161d67fb7118 100644 (file)
@@ -23,7 +23,7 @@ OBJS.test57=test57loop.o
  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \
 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
-61 62
+61 62 64
 PROG+= test$(t)
 .endfor
   
index db55bac35cf89d4ce4b91d88621813883972c8d3..0802e15a88f0201e75f65aa17c316b241351ae54 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -14,7 +14,7 @@ badones=                      # list of tests that failed
 tests="   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \
          21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
          41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
-         61 62 63 \
+         61 62 63 64 \
         sh1.sh sh2.sh interp.sh"
 tests_no=`expr 0`
 
diff --git a/test/test64.c b/test/test64.c
new file mode 100644 (file)
index 0000000..52f741c
--- /dev/null
@@ -0,0 +1,48 @@
+
+/* Code to test reasonable response to out-of-memory condition
+ * of regular processes.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+#define MAX_ERROR 2
+
+#include "magic.h"
+#include "common.c"
+
+int main (int argc, char *argv[])
+{
+  pid_t f;
+  start(64);
+#define NADDRS 500
+#define LEN 4096
+  static void *addrs[NADDRS];
+  int i = 0;
+  int st;
+
+  if((f=fork()) == -1) {
+       e(1);
+       exit(1);
+  }
+
+  if(f == 0) {
+       /* child: use up as much memory as we can */
+       while((addrs[i++ % NADDRS] = minix_mmap(0, LEN, PROT_READ|PROT_WRITE,
+               MAP_PREALLOC|MAP_CONTIG|MAP_ANON, -1, 0)) != MAP_FAILED)
+                       ;
+       exit(0);
+  }
+
+  /* parent: wait for child */
+  if(waitpid(f, &st, 0) < 0) 
+       perror("waitpid");
+
+  quit();
+
+  return(0);
+}