]> Zhao Yanbai Git Server - minix.git/commitdiff
Add "expected size" parameter to getsysinfo()
authorDavid van Moolenbroek <david@minix3.org>
Sun, 11 Dec 2011 21:30:35 +0000 (22:30 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Sun, 11 Dec 2011 21:34:14 +0000 (22:34 +0100)
This patch provides basic protection against damage resulting from
differently compiled servers blindly copying tables to one another.
In every getsysinfo() call, the caller is provided with the expected
size of the requested data structure. The callee fails the call if
the expected size does not match the data structure's actual size.

17 files changed:
common/include/minix/com.h
common/include/minix/sysinfo.h
lib/libsys/getsysinfo.c
servers/avfs/misc.c
servers/avfs/param.h
servers/ds/store.c
servers/is/dmp_ds.c
servers/is/dmp_fs.c
servers/is/dmp_pm.c
servers/is/dmp_rs.c
servers/pm/main.c
servers/pm/misc.c
servers/pm/param.h
servers/procfs/tree.c
servers/rs/request.c
servers/vfs/misc.c
servers/vfs/param.h

index d3d5d2809ec690875ae3e1bed4354de6adcb6ee7..6786376733f91fda4bf75e7c38b0fed130bc52ae 100644 (file)
 #define COMMON_GETSYSINFO      (COMMON_RQ_BASE+2)
 #      define SI_WHAT          m1_i1
 #      define SI_WHERE         m1_p1
+#      define SI_SIZE          m1_i2
 
 /* PM field names */
 /* BRK */
index d2b602c7dc5f4d10d6f2e3932b3d858937fc3bf6..ddb8afbd76638578e4d7d5d32f75116585e9d445 100644 (file)
@@ -5,14 +5,13 @@
 #include <minix/endpoint.h>
 #include <minix/type.h>
 
-_PROTOTYPE( int getsysinfo, (endpoint_t who, int what, void *where)       );
+_PROTOTYPE( int getsysinfo, (endpoint_t who, int what, void *where,
+       size_t size) );
 
 /* What system info to retrieve with sysgetinfo(). */
 #define SI_PROC_TAB       2    /* copy of entire process table */
 #define SI_DMAP_TAB       3    /* get device <-> driver mappings */
 #define SI_DATA_STORE     5    /* get copy of data store mappings */
-#define SI_SUBSCRIPTION           6    /* get copy of data store subscriptions */
-#define SI_LOADINFO       7    /* get copy of load average structure */
 #define SI_CALL_STATS     9    /* system call statistics */
 #define SI_PROCPUB_TAB    11   /* copy of public entries of process table */
 
index 575a900512f3a244ec6267c45d3ed3dc6089e7dc..79eacb2fe3a0d3066c8f9c80ffc9da94700162ae 100644 (file)
@@ -3,14 +3,17 @@
 #include <minix/sysinfo.h>
 #include <minix/com.h>
 
-PUBLIC int getsysinfo(who, what, where)
-endpoint_t who;                        /* from whom to request info */
-int what;                      /* what information is requested */
-void *where;                   /* where to put it */
+PUBLIC int getsysinfo(
+  endpoint_t who,              /* from whom to request info */
+  int what,                    /* what information is requested */
+  void *where,                 /* where to put it */
+  size_t size                  /* how big it should be */
+)
 {
   message m;
   m.SI_WHAT = what;
   m.SI_WHERE = where;
+  m.SI_SIZE = size;
   if (_syscall(who, COMMON_GETSYSINFO, &m) < 0) return(-1);
   return(0);
 }
index 89e8ac067f79e06b56492f2dc44e22f2bb1c891b..f05352619774feba5bc2ab4b4a811dded74fc9d1 100644 (file)
@@ -70,7 +70,7 @@ PUBLIC int do_getsysinfo()
 
   if (!super_user) return(EPERM);
 
-  switch(m_in.info_what) {
+  switch(m_in.SI_WHAT) {
     case SI_PROC_TAB:
        src_addr = (vir_bytes) fproc;
        len = sizeof(struct fproc) * NR_PROCS;
@@ -89,7 +89,10 @@ PUBLIC int do_getsysinfo()
        return(EINVAL);
   }
 
-  dst_addr = (vir_bytes) m_in.info_where;
+  if (len != m_in.SI_SIZE)
+       return(EINVAL);
+
+  dst_addr = (vir_bytes) m_in.SI_WHERE;
   return sys_datacopy(SELF, src_addr, who_e, dst_addr, len);
 }
 
index ad910762530d8f969348770c49fa23915266af77..ea05621bb2e701c455642fa85624e5400b224c31 100644 (file)
@@ -45,8 +45,6 @@
 #define whence       m2_i2
 #define svrctl_req    m2_i1
 #define svrctl_argp   m2_p1
-#define info_what     m1_i1
-#define info_where    m1_p1
 #define md_label       m2_p1
 #define md_label_len   m2_l1
 #define md_major       m2_i1
index 401dc15ad2973bf05ef2295440c1915cef8b7628..1c8efa4b05e09e505f423cd618c40f245988fe14 100644 (file)
@@ -776,21 +776,20 @@ PUBLIC int do_getsysinfo(const message *m_ptr)
   size_t length;
   int s;
 
-  switch(m_ptr->m1_i1) {
+  switch(m_ptr->SI_WHAT) {
   case SI_DATA_STORE:
        src_addr = (vir_bytes)ds_store;
        length = sizeof(struct data_store) * NR_DS_KEYS;
        break;
-  case SI_SUBSCRIPTION:
-       src_addr = (vir_bytes)ds_subs;
-       length = sizeof(struct subscription) * NR_DS_SUBS;
-       break;
   default:
        return EINVAL;
   }
 
+  if (length != m_ptr->SI_SIZE)
+       return EINVAL;
+
   if (OK != (s=sys_datacopy(SELF, src_addr,
-               m_ptr->m_source, (vir_bytes)m_ptr->m1_p1, length))) {
+               m_ptr->m_source, (vir_bytes)m_ptr->SI_WHERE, length))) {
        printf("DS: copy failed: %d\n", s);
        return s;
   }
index 38cc18335c1e169c532fac7cac29e0156a10347c..513a93727408bd1bdc387d7c36faf7297d47c7f8 100644 (file)
@@ -9,10 +9,10 @@ PUBLIC void data_store_dmp()
 {
   struct data_store *p;
   static int prev_i = 0;
-  int r, i, n = 0;
+  int i, n = 0;
 
-  if((r=getsysinfo(DS_PROC_NR, SI_DATA_STORE, ds_store)) != OK) {
-       printf("Couldn't talk to DS: %d.\n", r);
+  if (getsysinfo(DS_PROC_NR, SI_DATA_STORE, ds_store, sizeof(ds_store)) != OK) {
+       printf("Error obtaining table from DS. Perhaps recompile IS?\n");
        return;
   }
 
index ad5522ab6b22691b2cc6913973c3936c897459a5..92b7cd7a9c563c9080899cf5eef08f8e2509ce1d 100644 (file)
@@ -33,7 +33,10 @@ PUBLIC void fproc_dmp()
   int i, n=0;
   static int prev_i;
 
-  getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc);
+  if (getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc, sizeof(fproc)) != OK) {
+       printf("Error obtaining table from VFS. Perhaps recompile IS?\n");
+       return;
+  }
 
   printf("File System (FS) process table dump\n");
   printf("-nr- -pid- -tty- -umask- --uid-- --gid-- -ldr- -sus-rev-proc-\n");
@@ -107,7 +110,10 @@ PUBLIC void dtab_dmp()
 {
     int i;
 
-    getsysinfo(VFS_PROC_NR, SI_DMAP_TAB, dmap);
+    if (getsysinfo(VFS_PROC_NR, SI_DMAP_TAB, dmap, sizeof(dmap)) != OK) {
+        printf("Error obtaining table from VFS. Perhaps recompile IS?\n");
+        return;
+    }
     
     printf("File System (FS) device <-> driver mappings\n");
     printf("    Label     Major Driver ept Flags     Style   \n");
index ab757bc698bfa68a1ea96a596f359474a96849e4..921f6a31d80e6b0c0ecd8c6858c2bc0624f0c411 100644 (file)
@@ -45,10 +45,12 @@ PUBLIC void mproc_dmp()
   int i, n=0;
   static int prev_i = 0;
 
-  printf("Process manager (PM) process table dump\n");
-
-  getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
+  if (getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc, sizeof(mproc)) != OK) {
+       printf("Error obtaining table from PM. Perhaps recompile IS?\n");
+       return;
+  }
 
+  printf("Process manager (PM) process table dump\n");
   printf("-process- -nr-pnr-tnr- --pid--ppid--pgrp- -uid--  -gid--  -nice- -flags-------\n");
   for (i=prev_i; i<NR_PROCS; i++) {
        mp = &mproc[i];
@@ -77,11 +79,13 @@ PUBLIC void sigaction_dmp()
   static int prev_i = 0;
   clock_t uptime;
 
-  printf("Process manager (PM) signal action dump\n");
-
-  getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
+  if (getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc, sizeof(mproc)) != OK) {
+       printf("Error obtaining table from PM. Perhaps recompile IS?\n");
+       return;
+  }
   getuptime(&uptime);
 
+  printf("Process manager (PM) signal action dump\n");
   printf("-process- -nr- --ignore- --catch- --block- -pending- -alarm---\n");
   for (i=prev_i; i<NR_PROCS; i++) {
        mp = &mproc[i];
index dd8ec994cab1448a39d4171fc9d7fcd3069ec844..ed6b9937a95ad475b509a6e310e60607156c7b45 100644 (file)
@@ -29,8 +29,11 @@ PUBLIC void rproc_dmp()
   int i, n=0;
   static int prev_i=0;
 
-  getsysinfo(RS_PROC_NR, SI_PROCPUB_TAB, rprocpub);
-  getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc);
+  if (getsysinfo(RS_PROC_NR, SI_PROCPUB_TAB, rprocpub, sizeof(rprocpub)) != OK
+       || getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc, sizeof(rproc)) != OK) {
+       printf("Error obtaining table from RS. Perhaps recompile IS?\n");
+       return;
+  }
 
   printf("Reincarnation Server (RS) system process table dump\n");
   printf("----label---- endpoint- -pid- flags- -dev- -T- alive_tm starts command\n");
index 12b41daf0163c65c36d0a38cc918f2ebca88cb51..96637e0f51015136fedb3dd07f60b4b4302f918a 100644 (file)
@@ -178,7 +178,7 @@ PRIVATE void sef_local_startup()
 /*===========================================================================*
  *                         sef_cb_init_fresh                                *
  *===========================================================================*/
-PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
+PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
 {
 /* Initialize the process manager. 
  * Memory use info is collected from the boot monitor, the kernel, and
index a2347ec191e0c158f879618cf41ba84605bab7b2..ea28e2d8f130126f8fafc77d352793c04458ff04 100644 (file)
@@ -155,9 +155,7 @@ PUBLIC int do_sysuname()
 PUBLIC int do_getsysinfo()
 {
   vir_bytes src_addr, dst_addr;
-  struct loadinfo loadinfo;
   size_t len;
-  int s;
 
   /* This call leaks important information. In the future, requests from
    * non-system processes should be denied.
@@ -170,16 +168,11 @@ PUBLIC int do_getsysinfo()
        return EPERM;
   }
 
-  switch(m_in.info_what) {
+  switch(m_in.SI_WHAT) {
   case SI_PROC_TAB:                    /* copy entire process table */
         src_addr = (vir_bytes) mproc;
         len = sizeof(struct mproc) * NR_PROCS;
         break;
-  case SI_LOADINFO:                    /* loadinfo is obtained via PM */
-        sys_getloadinfo(&loadinfo);
-        src_addr = (vir_bytes) &loadinfo;
-        len = sizeof(struct loadinfo);
-        break;
 #if ENABLE_SYSCALL_STATS
   case SI_CALL_STATS:
        src_addr = (vir_bytes) calls_stats;
@@ -190,10 +183,11 @@ PUBLIC int do_getsysinfo()
        return(EINVAL);
   }
 
-  dst_addr = (vir_bytes) m_in.info_where;
-  if (OK != (s=sys_datacopy(SELF, src_addr, who_e, dst_addr, len)))
-       return(s);
-  return(OK);
+  if (len != m_in.SI_SIZE)
+       return(EINVAL);
+
+  dst_addr = (vir_bytes) m_in.SI_WHERE;
+  return sys_datacopy(SELF, src_addr, who_e, dst_addr, len);
 }
 
 /*===========================================================================*
index 83024fa7ff720284490bc3d7e27b9fd72c4491d6..4c2863306b61e136c7809cbc5b724157fa264852 100644 (file)
@@ -26,8 +26,6 @@
 #define sig_set                m2_l1
 #define sig_how                m2_i1
 #define sig_context    m2_p1
-#define info_what      m1_i1
-#define info_where     m1_p1
 #define reboot_flag    m1_i1
 #define reboot_code    m1_p1
 #define reboot_strlen  m1_i2
index 404fb6fb11baa6129028c32f5829d4ef83fbea0d..2d03b7b0ffbf2cb44fd606627eec4f80b345ae0e 100644 (file)
@@ -77,47 +77,78 @@ PRIVATE int dir_is_pid(struct inode *node)
                get_inode_index(node) != NO_INDEX);
 }
 
-PRIVATE int mproc_ok(struct mproc *tab, int slots)
+/*===========================================================================*
+ *                             update_proc_table                            *
+ *===========================================================================*/
+PRIVATE int update_proc_table(void)
 {
-       int i;
+       /* Get the process table from the kernel.
+        * Check the magic number in the table entries.
+        */
+       int r, slot;
 
-       /* sanity check of mproc */
+       if ((r = sys_getproctab(proc)) != OK) return r;
+
+       for (slot = 0; slot < NR_PROCS + NR_TASKS; slot++) {
+               if (proc[slot].p_magic != PMAGIC) {
+                       printf("PROCFS: system version mismatch!\n");
 
-       for(i = 0; i < slots; i++) {
-               if(tab[i].mp_magic != MP_MAGIC) {
-                       printf("procfs: mproc table magic number mismatch\n");
-                       return 0;
+                       return EINVAL;
                }
        }
 
-       return 1;
+       return OK;
 }
 
 /*===========================================================================*
- *                             update_tables                                *
+ *                             update_mproc_table                           *
  *===========================================================================*/
-PRIVATE int update_tables(void)
+PRIVATE int update_mproc_table(void)
 {
-       /* Get the process tables from the kernel, PM, and VFS.
-        * Check the magic number in the kernel table entries.
+       /* Get the process table from PM.
+        * Check the magic number in the table entries.
         */
        int r, slot;
 
-       if ((r = sys_getproctab(proc)) != OK) return r;
+       r = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc, sizeof(mproc));
+       if (r != OK) return r;
 
-       for (slot = 0; slot < NR_PROCS + NR_TASKS; slot++) {
-               if (proc[slot].p_magic != PMAGIC) {
-                       printf("PROCFS: system version mismatch!\n");
+       for (slot = 0; slot < NR_PROCS; slot++) {
+               if (mproc[slot].mp_magic != MP_MAGIC) {
+                       printf("PROCFS: PM version mismatch!\n");
 
                        return EINVAL;
                }
        }
 
-       if ((r = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) return r;
+       return OK;
+}
+
+/*===========================================================================*
+ *                             update_fproc_table                           *
+ *===========================================================================*/
+PRIVATE int update_fproc_table(void)
+{
+       /* Get the process table from VFS.
+        */
+
+       return getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc, sizeof(fproc));
+}
+
+/*===========================================================================*
+ *                             update_tables                                *
+ *===========================================================================*/
+PRIVATE int update_tables(void)
+{
+       /* Get the process tables from the kernel, PM, and VFS.
+        */
+       int r;
+
+       if ((r = update_proc_table()) != OK) return r;
 
-       if(!mproc_ok(mproc, NR_PROCS)) return EINVAL;
+       if ((r = update_mproc_table()) != OK) return r;
 
-       if ((r = getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc)) != OK) return r;
+       if ((r = update_fproc_table()) != OK) return r;
 
        return OK;
 }
index f664f357d92fe565f4e6c594d543e6d20c71d961..6fd5d74cb272ed7304ec7e2dedcd54fb3e305797 100755 (executable)
@@ -879,7 +879,7 @@ message *m_ptr;
   if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK)
       return s;
 
-  switch(m_ptr->m1_i1) {
+  switch(m_ptr->SI_WHAT) {
   case SI_PROC_TAB:
        src_addr = (vir_bytes) rproc;
        len = sizeof(struct rproc) * NR_SYS_PROCS;
@@ -892,11 +892,12 @@ message *m_ptr;
        return(EINVAL);
   }
 
+  if (len != m_ptr->SI_SIZE)
+       return(EINVAL);
+
   dst_proc = m_ptr->m_source;
-  dst_addr = (vir_bytes) m_ptr->m1_p1;
-  if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
-       return(s);
-  return(OK);
+  dst_addr = (vir_bytes) m_ptr->SI_WHERE;
+  return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len);
 }
 
 /*===========================================================================*
index e7be635c75c098271b49c18c267a3b0991dd71af..569b3220252afe3fbd507d79269bfae6510e131b 100644 (file)
@@ -65,7 +65,6 @@ PUBLIC int do_getsysinfo()
 {
   vir_bytes src_addr, dst_addr;
   size_t len;
-  int s;
 
   /* Only su may call do_getsysinfo. This call may leak information (and is not
    * stable enough to be part of the API/ABI). In the future, requests from
@@ -74,7 +73,7 @@ PUBLIC int do_getsysinfo()
 
   if (!super_user) return(EPERM);
 
-  switch(m_in.info_what) {
+  switch(m_in.SI_WHAT) {
   case SI_PROC_TAB:
        src_addr = (vir_bytes) fproc;
        len = sizeof(struct fproc) * NR_PROCS;
@@ -93,10 +92,11 @@ PUBLIC int do_getsysinfo()
        return(EINVAL);
   }
 
-  dst_addr = (vir_bytes) m_in.info_where;
-  if (OK != (s = sys_datacopy(SELF, src_addr, who_e, dst_addr, len))) return(s);
-  return(OK);
+  if (len != m_in.SI_SIZE)
+       return(EINVAL);
 
+  dst_addr = (vir_bytes) m_in.SI_WHERE;
+  return sys_datacopy(SELF, src_addr, who_e, dst_addr, len);
 }
 
 /*===========================================================================*
index e5be4a2756ed8ce3f2948f0cbcd9b34f383c4fc3..77a27f830e8d689a347cd51cb7538166c2f765a5 100644 (file)
@@ -42,8 +42,6 @@
 #define whence       m2_i2
 #define svrctl_req    m2_i1
 #define svrctl_argp   m2_p1
-#define info_what     m1_i1
-#define info_where    m1_p1
 #define md_label       m2_p1
 #define md_label_len   m2_l1
 #define md_major       m2_i1