]> Zhao Yanbai Git Server - minix.git/commitdiff
IPC privileges fixes
authorDavid van Moolenbroek <david@minix3.org>
Thu, 2 Jul 2009 16:25:31 +0000 (16:25 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 2 Jul 2009 16:25:31 +0000 (16:25 +0000)
Kernel:
o Remove s_ipc_sendrec, instead using s_ipc_to for all send primitives
o Centralize s_ipc_to bit manipulation,
  - disallowing assignment of bits pointing to unused priv structs;
  - preventing send-to-self by not setting bit for own priv struct;
  - preserving send mask matrix symmetry in all cases
o Add IPC send mask checks to SENDA, which were missing entirely somehow
o Slightly improve IPC stats accounting for SENDA
o Remove SYSTEM from user processes' send mask
o Half-fix the dependency between boot image order and process numbers,
  - correcting the table order of the boot processes;
  - documenting the order requirement needed for proper send masks;
  - warning at boot time if the order is violated

RS:
o Add support in /etc/drivers.conf for servers that talk to user processes,
  - disallowing IPC to user processes if no "ipc" field is present
  - adding a special "USER" label to explicitly allow IPC to user processes
o Always apply IPC masks when specified; remove -i flag from service(8)
o Use kernel send mask symmetry to delay adding IPC permissions for labels
  that do not exist yet, adding them to that label's process upon creation
o Add VM to ipc permissions list for rtl8139 and fxp in drivers.conf

Left to future fixes:
o Removal of the table order vs process numbers dependency altogether,
  possibly using per-process send list structures as used for SYSTEM calls
o Proper assignment of send masks to boot processes;
  some of the assigned (~0) masks are much wider than necessary
o Proper assignment of IPC send masks for many more servers in drivers.conf
o Removal of the debugging warning about the now legitimate case where RS's
  add_forward_ipc cannot find the IPC destination's label yet

13 files changed:
commands/swifi/run_t1
etc/drivers.conf
kernel/main.c
kernel/priv.h
kernel/proc.c
kernel/proto.h
kernel/system.c
kernel/system/do_privctl.c
kernel/table.c
servers/is/dmp_kernel.c
servers/rs/manager.c
servers/rs/service.c
tools/Makefile

index 1bb2d524fd69071c87092b64e07f6e65e787774e..bea5420fbf38681073ffdd118b95e065920d989e 100755 (executable)
@@ -103,7 +103,7 @@ esac
 # Start our own driver.
 service down $LABEL
 sleep 2        # Allow driver to die
-service -i up $EXE -script `pwd`/rs.restart_imm -config /etc/drivers.conf -period 3HZ $DEV
+service up $EXE -script `pwd`/rs.restart_imm -config /etc/drivers.conf -period 3HZ $DEV
 
 i=0
 while [ $i -lt "$count" ]
index 8abc793f92c404468328767e570a7333fb850d23..67501ad694bc87876c20b98fc356efe89f813e6f 100644 (file)
@@ -93,7 +93,7 @@ driver rtl8139
        ;
        pci device      10ec/8139;
        ipc
-               SYSTEM PM RS LOG TTY DS
+               SYSTEM PM RS LOG TTY DS VM
                pci inet amddev
                ;
 };
@@ -116,7 +116,7 @@ driver fxp
        ;
        pci device      8086/1229;
        ipc
-               SYSTEM PM RS LOG TTY DS
+               SYSTEM PM RS LOG TTY DS VM
                pci inet amddev
                ;
 };
index 0c26fe1715bd7aa0d435c11adc642e99c3ad7894..3fdf0b867dbc78be2d42b7caa6c8b1c30509fe10 100755 (executable)
@@ -83,6 +83,10 @@ PUBLIC void main()
        priv(rp)->s_flags = ip->flags;                  /* process flags */
        priv(rp)->s_trap_mask = ip->trap_mask;          /* allowed traps */
 
+       /* Warn about violations of the boot image table order consistency. */
+       if (priv_id(rp) != s_nr_to_id(ip->proc_nr))
+               kprintf("Warning: boot image table has wrong process order\n");
+
        /* Initialize call mask bitmap from unordered set.
         * A single SYS_ALL_CALLS is a special case - it
         * means all calls are allowed.
@@ -99,12 +103,9 @@ PUBLIC void main()
                        SET_BIT(priv(rp)->s_k_call_mask,
                                ip->k_calls[ci]-KERNEL_CALL);
 
-       priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to;       /* restrict targets */
-
-       for (j=0; j<BITMAP_CHUNKS(NR_SYS_PROCS); j++) {
-               rp->p_priv->s_ipc_sendrec.chunk[j] = ~0L;
-       }
-       unset_sys_bit(rp->p_priv->s_ipc_sendrec, USER_PRIV_ID);
+       for (j = 0; j < NR_SYS_PROCS && j < BITCHUNK_BITS; j++)
+               if (ip->ipc_to & (1 << j))
+                       set_sendto_bit(rp, j);  /* restrict targets */
 
        if (iskerneln(proc_nr(rp))) {           /* part of the kernel? */ 
                if (ip->stksize > 0) {          /* HARDWARE stack size is 0 */
index 6d50cde2c3ce04528a6e2090de2aad96c3c67029..6775be7fb82adb0acf5e5299ce3da3398eebb974 100755 (executable)
@@ -36,9 +36,7 @@ struct priv {
                                 */
 
   short s_trap_mask;           /* allowed system call traps */
-  sys_map_t s_ipc_from;                /* allowed callers to receive from */
   sys_map_t s_ipc_to;          /* allowed destination processes */
-  sys_map_t s_ipc_sendrec;     /* allowed sendrec processes */
 
   /* allowed kernel calls */
 #define CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_CALLS)
@@ -78,6 +76,8 @@ struct priv {
 #define id_to_nr(id)   priv_addr(id)->s_proc_nr
 #define nr_to_id(nr)    priv(proc_addr(nr))->s_id
 
+#define may_send_to(rp, nr) (get_sys_bit(priv(rp)->s_ipc_to, nr_to_id(nr)))
+
 /* The system structures table and pointers to individual table slots. The 
  * pointers allow faster access because now a process entry can be found by 
  * indexing the psys_addr array, while accessing an element i requires a 
index 0b5f43c36af6ff32ef7bd0e8dcd5ca3c6c5bf113..bb3d8543f34d5fd84ecb85771a70f2f3983d8882 100755 (executable)
@@ -178,8 +178,7 @@ long bit_map;                       /* notification event set or flags */
    * addition to a real endpoint). The other calls (SEND, SENDREC,
    * and NOTIFY) require an endpoint to corresponds to a process. In addition,
    * it is necessary to check whether a process is allowed to send to a given
-   * destination. For SENDREC we check s_ipc_sendrec, and for SEND,
-   * and NOTIFY we check s_ipc_to.
+   * destination.
    */
   if (call_nr == SENDA)
   {
@@ -201,13 +200,6 @@ long bit_map;                      /* notification event set or flags */
   }
   else
   {
-       if(caller_ptr->p_endpoint == src_dst_e) {
-#if DEBUG_ENABLE_IPC_WARNINGS
-               kprintf("sys_call: trap %d by %d with self %d\n", 
-                       call_nr, proc_nr(caller_ptr), src_dst_e);
-#endif
-               return EINVAL;
-       }
        /* Require a valid source and/or destination process. */
        if(!isokendpt(src_dst_e, &src_dst_p)) {
 #if DEBUG_ENABLE_IPC_WARNINGS
@@ -219,29 +211,13 @@ long bit_map;                     /* notification event set or flags */
                return EDEADSRCDST;
        }
 
-       /* If the call is to send to a process, i.e., for SEND,
+       /* If the call is to send to a process, i.e., for SEND, SENDNB,
         * SENDREC or NOTIFY, verify that the caller is allowed to send to
         * the given destination. 
         */
-       if (call_nr == SENDREC)
-       {
-               if (! get_sys_bit(priv(caller_ptr)->s_ipc_sendrec,
-                       nr_to_id(src_dst_p))) {
-#if DEBUG_ENABLE_IPC_WARNINGS
-                       kprintf(
-       "sys_call: ipc sendrec mask denied trap %d from %d ('%s') to %d\n",
-                               call_nr, proc_nr(caller_ptr),
-                               caller_ptr->p_name, src_dst_p);
-#endif
-                       if (caller_ptr->p_endpoint == ipc_stats_target)
-                               ipc_stats.dst_not_allowed++;
-                       return(ECALLDENIED);    /* call denied by ipc mask */
-               }
-       }
-       else if (call_nr == SEND || call_nr == SENDNB || call_nr == NOTIFY)
+       if (call_nr != RECEIVE)
        {
-               if (! get_sys_bit(priv(caller_ptr)->s_ipc_to,
-                       nr_to_id(src_dst_p))) {
+               if (!may_send_to(caller_ptr, src_dst_p)) {
 #if DEBUG_ENABLE_IPC_WARNINGS
                        kprintf(
                        "sys_call: ipc mask denied trap %d from %d to %d\n",
@@ -823,6 +799,9 @@ size_t size;
                if (!isokendpt(tabent.dst, &dst_p))
                {
                        /* Bad destination, report the error */
+                       if (caller_ptr->p_endpoint == ipc_stats_target)
+                               ipc_stats.bad_endpoint++;
+
                        tabent.result= EDEADSRCDST;
                        A_INSERT(i, result);
                        tabent.flags= flags | AMF_DONE;
@@ -833,6 +812,22 @@ size_t size;
                        continue;
                }
 
+               if (!may_send_to(caller_ptr, dst_p))
+               {
+                       /* Send denied by IPC mask */
+                       if (caller_ptr->p_endpoint == ipc_stats_target)
+                               ipc_stats.dst_not_allowed++;
+
+                       tabent.result= ECALLDENIED;
+                       A_INSERT(i, result);
+                       tabent.flags= flags | AMF_DONE;
+                       A_INSERT(i, flags);
+
+                       if (flags & AMF_NOTIFY)
+                               do_notify= 1;
+                       continue;
+               }
+
 #if 0
                kprintf("mini_senda: entry[%d]: flags 0x%x dst %d/%d\n",
                        i, tabent.flags, tabent.dst, dst_p);
@@ -843,6 +838,9 @@ size_t size;
                /* NO_ENDPOINT should be removed */
                if (dst_ptr->p_rts_flags & NO_ENDPOINT)
                {
+                       if (caller_ptr->p_endpoint == ipc_stats_target)
+                               ipc_stats.dst_died++;
+
                        tabent.result= EDSTDIED;
                        A_INSERT(i, result);
                        tabent.flags= flags | AMF_DONE;
@@ -928,6 +926,8 @@ struct proc *caller_ptr;
                        privp->s_proc_nr);
 #endif
                src_ptr= proc_addr(privp->s_proc_nr);
+               if (!may_send_to(src_ptr, proc_nr(caller_ptr)))
+                       continue;
                r= try_one(src_ptr, caller_ptr);
                if (r == OK)
                        return r;
index a3070efdd3c3bb0931a39c25ad7d39ad73ff8670..c229309916eb556ffed91071de8b4cd7b05e47a6 100755 (executable)
@@ -55,6 +55,8 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
 
 /* system.c */
 _PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type)    );
+_PROTOTYPE( void set_sendto_bit, (struct proc *rc, int id)             );
+_PROTOTYPE( void unset_sendto_bit, (struct proc *rc, int id)           );
 _PROTOTYPE( void send_sig, (int proc_nr, int sig_nr)                   );
 _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr)                  );
 _PROTOTYPE( void sys_task, (void)                                      );
index 77642f62bc0acbfbac082f4a3a2ee7af830d115e..1af2b4920c29cadfea458bc24c1ecb95c9c2a6dd 100755 (executable)
@@ -12,6 +12,8 @@
  * In addition to the main sys_task() entry point, which starts the main loop,
  * there are several other minor entry points:
  *   get_priv:         assign privilege structure to user or system process
+ *   set_sendto_bit:   allow a process to send messages to a new target
+ *   unset_sendto_bit: disallow a process from sending messages to a target
  *   send_sig:         send a signal directly to a system process
  *   cause_sig:                take action to cause a signal to occur via PM
  *   umap_bios:                map virtual address in BIOS_SEG to physical 
@@ -290,6 +292,46 @@ int proc_type;                             /* system or user process flag */
   return(OK);
 }
 
+/*===========================================================================*
+ *                             set_sendto_bit                               *
+ *===========================================================================*/
+PUBLIC void set_sendto_bit(struct proc *rp, int id)
+{
+/* Allow a process to send messages to the process(es) associated with the
+ * system privilege structure with the given ID. 
+ */
+  struct proc *rrp;                    /* receiver process */
+
+  /* Disallow the process from sending to a system privilege structure with no
+   * associated process, and disallow the process from sending to itself.
+   */
+  if (id_to_nr(id) == NONE || priv_id(rp) == id)
+       return;
+
+  set_sys_bit(priv(rp)->s_ipc_to, id);
+
+  /* The process that this process can now send to, must be able to reply.
+   * Therefore, its send mask should be updated as well.
+   */
+  rrp = proc_addr(id_to_nr(id));
+  if (!iskernelp(rrp))
+       set_sys_bit(priv(rrp)->s_ipc_to, priv_id(rp));
+}
+
+/*===========================================================================*
+ *                             unset_sendto_bit                             *
+ *===========================================================================*/
+PUBLIC void unset_sendto_bit(struct proc *rp, int id)
+{
+/* Prevent a process from sending to another process. Retain the send mask
+ * symmetry by also unsetting the bit for the other direction.
+ */
+
+  unset_sys_bit(priv(rp)->s_ipc_to, id);
+
+  unset_sys_bit(priv_addr(id)->s_ipc_to, priv_id(rp));
+}
+
 /*===========================================================================*
  *                             send_sig                                     *
  *===========================================================================*/
index c76706dc921b628aaceb9028723316fda706a37b..175da2bf777ca077f0c1f1dd1723b21054ddcf05 100644 (file)
@@ -70,24 +70,14 @@ message *m_ptr;                     /* pointer to request message */
 
        /* Now update the process' privileges as requested. */
        rp->p_priv->s_trap_mask = FILLED_MASK;
-       for (i=0; i<BITMAP_CHUNKS(NR_SYS_PROCS); i++) {
-               rp->p_priv->s_ipc_to.chunk[i] = FILLED_MASK;
-       }
-       unset_sys_bit(rp->p_priv->s_ipc_to, USER_PRIV_ID);
-
-       /* All process that this process can send to must be able to reply. 
-        * Therefore, their send masks should be updated as well. 
-        */
-       for (i=0; i<NR_SYS_PROCS; i++) {
-           if (get_sys_bit(rp->p_priv->s_ipc_to, i)) {
-                 set_sys_bit(priv_addr(i)->s_ipc_to, priv_id(rp));
-           }
-       }
 
-       for (i=0; i<BITMAP_CHUNKS(NR_SYS_PROCS); i++) {
-               rp->p_priv->s_ipc_sendrec.chunk[i] = FILLED_MASK;
+       /* Set a default send mask. */
+       for (i=0; i < NR_SYS_PROCS; i++) {
+               if (i != USER_PRIV_ID)
+                       set_sendto_bit(rp, i);
+               else
+                       unset_sendto_bit(rp, i);
        }
-       unset_sys_bit(rp->p_priv->s_ipc_sendrec, USER_PRIV_ID);
 
        /* No I/O resources, no memory resources, no IRQs, no grant table */
        priv(rp)->s_nr_io_range= 0;
@@ -142,10 +132,14 @@ message *m_ptr;                   /* pointer to request message */
 
                memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
                        sizeof(priv(rp)->s_k_call_mask));
-               memcpy(&priv(rp)->s_ipc_to, &priv.s_ipc_to,
-                       sizeof(priv(rp)->s_ipc_to));
-               memcpy(&priv(rp)->s_ipc_sendrec, &priv.s_ipc_sendrec,
-                       sizeof(priv(rp)->s_ipc_sendrec));
+
+               /* Set a custom send mask. */
+               for (i=0; i < NR_SYS_PROCS; i++) {
+                       if (get_sys_bit(priv.s_ipc_to, i))
+                               set_sendto_bit(rp, i);
+                       else
+                               unset_sendto_bit(rp, i);
+               }
        }
 
        /* Done. Privileges have been set. Allow process to run again. */
index 408819befec0fe7bf91a508da1262d6959f2b967..01a0c0edb403a9fdd4d68871958c9cf33c91382f 100755 (executable)
@@ -60,18 +60,15 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
 
 /* Send masks determine to whom processes can send messages or notifications. 
  * The values here are used for the processes in the boot image. We rely on 
- * the initialization code in main() to match the s_nr_to_id() mapping for the
- * processes in the boot image, so that the send mask that is defined here 
- * can be directly copied onto map[0] of the actual send mask. Privilege
- * structure 0 is shared by user processes. 
+ * the boot image table itself to match the order of the process numbers, so
+ * that the send mask that is defined here can be interpreted properly.
+ * Privilege structure 0 is shared by user processes. 
  */
 #define s(n)   (1 << (s_nr_to_id(n)))
-#define NUL_M   0
 #define SRV_M  (~0)
 #define SYS_M  (~0)
-#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(SYSTEM) | \
-       s(VM_PROC_NR))
-#define DRV_M (USR_M | s(SYSTEM) | s(CLOCK) | s(DS_PROC_NR) | s(LOG_PROC_NR) | s(TTY_PROC_NR))
+#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(VM_PROC_NR))
+#define DRV_M (USR_M | s(SYSTEM) | s(DS_PROC_NR) | s(LOG_PROC_NR) | s(TTY_PROC_NR))
 
 /* Define kernel calls that processes are allowed to make. This is not looking
  * very nice, but we need to define the access rights on a per call basis. 
@@ -100,7 +97,8 @@ PRIVATE int
 
 /* The system image table lists all programs that are part of the boot image. 
  * The order of the entries here MUST agree with the order of the programs
- * in the boot image and all kernel tasks must come first.
+ * in the boot image and all kernel tasks must come first. Furthermore, the
+ * order of the entries MUST agree with their process numbers. See above.
  *
  * Each entry provides the process number, flags, quantum size, scheduling
  * queue, allowed traps, ipc mask, and a name for the process table. The 
@@ -120,10 +118,10 @@ PUBLIC struct boot_image image[] = {
 {PM_PROC_NR,    0,SVM_F, 32,      4, 0,     SRV_T, SRV_M, c(pm_c),"pm"    },
 {FS_PROC_NR,    0,SVM_F, 32,      5, 0,     SRV_T, SRV_M, c(fs_c),"vfs"   },
 {RS_PROC_NR,    0,SVM_F,  4,      4, 0,     SRV_T, SYS_M, c(rs_c),"rs"    },
-{DS_PROC_NR,    0,SVM_F,  4,      4, 0,     SRV_T, SYS_M, c(ds_c),"ds"    },
-{TTY_PROC_NR,   0,SVM_F,  4,      1, 0,     SRV_T, SYS_M,c(tty_c),"tty"   },
 {MEM_PROC_NR,   0,SVM_F,  4,      3, 0,     SRV_T, SYS_M,c(mem_c),"memory"},
 {LOG_PROC_NR,   0,SVM_F,  4,      2, 0,     SRV_T, SYS_M,c(drv_c),"log"   },
+{TTY_PROC_NR,   0,SVM_F,  4,      1, 0,     SRV_T, SYS_M,c(tty_c),"tty"   },
+{DS_PROC_NR,    0,SVM_F,  4,      4, 0,     SRV_T, SYS_M, c(ds_c),"ds"    },
 {MFS_PROC_NR,   0,SVM_F, 32,      5, 0,     SRV_T, SRV_M, c(fs_c),"mfs"   },
 {VM_PROC_NR,    0,SRV_F, 32,      2, 0,     SRV_T, SRV_M, c(vm_c),"vm"    },
 {INIT_PROC_NR,  0,USR_F,  8, USER_Q, 0,     USR_T, USR_M, no_c,"init"  },
index 47c433565a6e16d63c99bf6cdeaa5ff9c716975f..a5a9c69605b602a7ebcbaad66c4eb22b34edeb88 100644 (file)
@@ -363,7 +363,7 @@ PUBLIC void privileges_dmp()
       return;
   }
 
-  printf("\n--nr-id-name---- -flags- -traps- grants -ipc_to-- -ipc_sr-- -system calls--\n");
+  printf("\n--nr-id-name---- -flags- -traps- grants -ipc_to-- -system calls--\n");
 
   PROCLOOP(rp, oldrp)
         r = -1;
@@ -379,9 +379,6 @@ PUBLIC void privileges_dmp()
         for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
            printf(" %04x", get_sys_bits(sp->s_ipc_to, i));
                }
-        for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
-           printf(" %04x", get_sys_bits(sp->s_ipc_sendrec, i));
-               }
 
        printf(" ");
         for (i=0; i < NR_SYS_CALLS; i += BITCHUNK_BITS) {
index e7c09c919e511637bbc09df3be41b0a60a361f33..e9ae77aa16d2b1cb0ee6064d0a51f62ef73f6eb8 100644 (file)
@@ -30,6 +30,12 @@ FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
 FORWARD _PROTOTYPE( int fork_nb, (void) );
 FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
 FORWARD _PROTOTYPE( void run_script, (struct rproc *rp) );
+FORWARD _PROTOTYPE( char *get_next_label, (char *ptr, char *label,
+       char *caller_label) );
+FORWARD _PROTOTYPE( void add_forward_ipc, (struct rproc *rp,
+       struct priv *privp) );
+FORWARD _PROTOTYPE( void add_backward_ipc, (struct rproc *rp,
+       struct priv *privp) );
 FORWARD _PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
 FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
 
@@ -1043,6 +1049,176 @@ struct rproc *rp;
 }
 
 
+/*===========================================================================*
+ *                             get_next_label                               *
+ *===========================================================================*/
+PRIVATE char *get_next_label(ptr, label, caller_label)
+char *ptr;
+char *label;
+char *caller_label;
+{
+       /* Get the next label from the list of (IPC) labels.
+        */
+       char *p, *q;
+       size_t len;
+
+       for (p= ptr; p[0] != '\0'; p= q)
+       {
+               /* Skip leading space */
+               while (p[0] != '\0' && isspace((unsigned char)p[0]))
+                       p++;
+
+               /* Find start of next word */
+               q= p;
+               while (q[0] != '\0' && !isspace((unsigned char)q[0]))
+                       q++;
+               if (q == p)
+                       continue;
+               len= q-p;
+               if (len > MAX_LABEL_LEN)
+               {
+                       printf(
+       "rs:get_next_label: bad ipc list entry '.*s' for %s: too long\n",
+                               len, p, caller_label);
+                       continue;
+               }
+               memcpy(label, p, len);
+               label[len]= '\0';
+
+               return q; /* found another */
+       }
+
+       return NULL; /* done */
+}
+
+/*===========================================================================*
+ *                             add_forward_ipc                              *
+ *===========================================================================*/
+PRIVATE void add_forward_ipc(rp, privp)
+struct rproc *rp;
+struct priv *privp;
+{
+       /* Add IPC send permissions to a process based on that process's IPC
+        * list.
+        */
+       char label[MAX_LABEL_LEN+1], *p;
+       struct rproc *tmp_rp;
+       endpoint_t proc_nr_e;
+       int slot_nr, priv_id;
+
+       p = rp->r_ipc_list;
+
+       while ((p = get_next_label(p, label, rp->r_label)) != NULL) {
+
+               if (strcmp(label, "SYSTEM") == 0)
+                       proc_nr_e= SYSTEM;
+               else if (strcmp(label, "USER") == 0)
+                       proc_nr_e= INIT_PROC_NR; /* all user procs */
+               else if (strcmp(label, "PM") == 0)
+                       proc_nr_e= PM_PROC_NR;
+               else if (strcmp(label, "VFS") == 0)
+                       proc_nr_e= FS_PROC_NR;
+               else if (strcmp(label, "RS") == 0)
+                       proc_nr_e= RS_PROC_NR;
+               else if (strcmp(label, "LOG") == 0)
+                       proc_nr_e= LOG_PROC_NR;
+               else if (strcmp(label, "TTY") == 0)
+                       proc_nr_e= TTY_PROC_NR;
+               else if (strcmp(label, "DS") == 0)
+                       proc_nr_e= DS_PROC_NR;
+               else if (strcmp(label, "VM") == 0)
+                       proc_nr_e= VM_PROC_NR;
+               else
+               {
+                       /* Try to find process */
+                       for (slot_nr = 0; slot_nr < NR_SYS_PROCS;
+                               slot_nr++)
+                       {
+                               tmp_rp = &rproc[slot_nr];
+                               if (!(tmp_rp->r_flags & RS_IN_USE))
+                                       continue;
+                               if (strcmp(tmp_rp->r_label, label) == 0)
+                                       break;
+                       }
+                       if (slot_nr >= NR_SYS_PROCS)
+                       {
+                               printf(
+                               "add_forward_ipc: unable to find '%s'\n",
+                                       label);
+                               continue;
+                       }
+                       proc_nr_e= tmp_rp->r_proc_nr_e;
+               }
+
+               priv_id= sys_getprivid(proc_nr_e);
+               if (priv_id < 0)
+               {
+                       printf(
+               "add_forward_ipc: unable to get priv_id for '%s': %d\n",
+                               label, priv_id);
+                       continue;
+               }
+               set_sys_bit(privp->s_ipc_to, priv_id);
+       }
+}
+
+
+/*===========================================================================*
+ *                             add_backward_ipc                             *
+ *===========================================================================*/
+PRIVATE void add_backward_ipc(rp, privp)
+struct rproc *rp;
+struct priv *privp;
+{
+       /* Add IPC send permissions to a process based on other processes' IPC
+        * lists. This is enough to allow each such two processes to talk to
+        * each other, as the kernel guarantees send mask symmetry. We need to
+        * add these permissions now because the current process may not yet
+        * have existed at the time that the other process was initialized.
+        */
+       char label[MAX_LABEL_LEN+1], *p;
+       struct rproc *rrp;
+       int priv_id, found;
+
+       for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
+               if (!(rrp->r_flags & RS_IN_USE))
+                       continue;
+
+               /* If an IPC target list was provided for the process being
+                * checked here, make sure that the label of the new process
+                * is in that process's list.
+                */
+               if (rrp->r_ipc_list[0]) {
+                       found = 0;
+
+                       p = rrp->r_ipc_list;
+
+                       while ((p = get_next_label(p, label, rp->r_label)) !=
+                                                                       NULL) {
+                               if (!strcmp(rp->r_label, label)) {
+                                       found = 1;
+                                       break;
+                               }
+                       }
+
+                       if (!found)
+                               continue;
+               }
+
+               priv_id= sys_getprivid(rrp->r_proc_nr_e);
+               if (priv_id < 0)
+               {
+                       printf(
+               "add_backward_ipc: unable to get priv_id for '%s': %d\n",
+                               label, priv_id);
+                       continue;
+               }
+
+               set_sys_bit(privp->s_ipc_to, priv_id);
+       }
+}
+
+
 /*===========================================================================*
  *                             init_privs                                   *
  *===========================================================================*/
@@ -1051,13 +1227,8 @@ struct rproc *rp;
 struct priv *privp;
 {
        int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
-               src_bit, call_nr, chunk, bit, priv_id, slot_nr;
-       endpoint_t proc_nr_e;
-       size_t len;
+               src_bit, call_nr;
        unsigned long mask;
-       char *p, *q;
-       struct rproc *tmp_rp;
-       char label[MAX_LABEL_LEN+1];
 
        /* Clear s_k_call_mask */
        memset(privp->s_k_call_mask, '\0', sizeof(privp->s_k_call_mask));
@@ -1088,98 +1259,21 @@ struct priv *privp;
                }
        }
 
-       /* Clear s_ipc_to and s_ipc_sendrec */
+       /* Clear s_ipc_to */
        memset(&privp->s_ipc_to, '\0', sizeof(privp->s_ipc_to));
-       memset(&privp->s_ipc_sendrec, '\0', sizeof(privp->s_ipc_sendrec));
 
        if (strlen(rp->r_ipc_list) != 0)
        {
-               for (p= rp->r_ipc_list; p[0] != '\0'; p= q)
-               {
-                       /* Skip leading space */
-                       while (p[0] != '\0' && isspace((unsigned char)p[0]))
-                               p++;
-
-                       /* Find start of next word */
-                       q= p;
-                       while (q[0] != '\0' && !isspace((unsigned char)q[0]))
-                               q++;
-                       if (q == p)
-                               continue;
-                       len= q-p;
-                       if (len+1 > sizeof(label))
-                       {
-                               printf(
-               "rs:init_privs: bad ipc list entry '.*s' for %s: too long\n",
-                                       len, p, rp->r_label);
-                               continue;
-                       }
-                       memcpy(label, p, len);
-                       label[len]= '\0';
-
-                       if (strcmp(label, "SYSTEM") == 0)
-                               proc_nr_e= SYSTEM;
-                       else if (strcmp(label, "PM") == 0)
-                               proc_nr_e= PM_PROC_NR;
-                       else if (strcmp(label, "VFS") == 0)
-                               proc_nr_e= FS_PROC_NR;
-                       else if (strcmp(label, "RS") == 0)
-                               proc_nr_e= RS_PROC_NR;
-                       else if (strcmp(label, "LOG") == 0)
-                               proc_nr_e= LOG_PROC_NR;
-                       else if (strcmp(label, "TTY") == 0)
-                               proc_nr_e= TTY_PROC_NR;
-                       else if (strcmp(label, "DS") == 0)
-                               proc_nr_e= DS_PROC_NR;
-                       else
-                       {
-                               /* Try to find process */
-                               for (slot_nr = 0; slot_nr < NR_SYS_PROCS;
-                                       slot_nr++)
-                               {
-                                       tmp_rp = &rproc[slot_nr];
-                                       if (!(tmp_rp->r_flags & RS_IN_USE))
-                                               continue;
-                                       if (strcmp(tmp_rp->r_label, label) == 0)
-                                               break;
-                               }
-                               if (slot_nr >= NR_SYS_PROCS)
-                               {
-                                       printf(
-                                       "init_privs: unable to find '%s'\n",
-                                               label);
-                                       continue;
-                               }
-                               proc_nr_e= tmp_rp->r_proc_nr_e;
-                       }
+               add_forward_ipc(rp, privp);
+               add_backward_ipc(rp, privp);
 
-                       priv_id= sys_getprivid(proc_nr_e);
-                       if (priv_id < 0)
-                       {
-                               printf(
-                       "init_privs: unable to get priv_id for '%s': %d\n",
-                                       label, priv_id);
-                               continue;
-                       }
-                       chunk= (priv_id / (sizeof(bitchunk_t)*8));
-                       bit= (priv_id % (sizeof(bitchunk_t)*8));
-                       privp->s_ipc_to.chunk[chunk] |= (1 << bit);
-                       privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
-               }
        }
        else
        {
-               for (i= 0; i<sizeof(privp->s_ipc_to)*8; i++)
-               {
-                       chunk= (i / (sizeof(bitchunk_t)*8));
-                       bit= (i % (sizeof(bitchunk_t)*8));
-                       privp->s_ipc_to.chunk[chunk] |= (1 << bit);
-               }
-               for (i= 0; i<sizeof(privp->s_ipc_sendrec)*8; i++)
+               for (i= 0; i<NR_SYS_PROCS; i++)
                {
-                       chunk= (i / (sizeof(bitchunk_t)*8));
-                       bit= (i % (sizeof(bitchunk_t)*8));
-                       privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
+                       if (i != USER_PRIV_ID)
+                               set_sys_bit(privp->s_ipc_to, i);
                }
        }
 }
index a3b12b1bb7d2165cf2954d0b4c813d97d49bfc26..2351b4f776842866686011f5d344c92aebdb1a6b 100644 (file)
@@ -134,7 +134,6 @@ PRIVATE int parse_arguments(int argc, char **argv)
   int req_nr;
   int c, i;
   int c_flag;
-  int i_flag=0;
 
   c_flag= 0;
   while (c= getopt(argc, argv, "ci?"), c != -1)
@@ -148,7 +147,9 @@ PRIVATE int parse_arguments(int argc, char **argv)
                c_flag= 1;
                break;
        case 'i':
-               i_flag= 1;
+               /* Legacy - remove later */
+               fputs("WARNING: obsolete -i flag passed to service(8)\n",
+                       stderr);
                break;
        default:
                fprintf(stderr, "%s: getopt failed: %c\n",
@@ -186,11 +187,9 @@ PRIVATE int parse_arguments(int argc, char **argv)
 
        req_nr= RS_START;
 
-      rs_start.rss_flags= 0;
+      rs_start.rss_flags= RF_IPC_VALID;
       if (c_flag)
        rs_start.rss_flags |= RF_COPY;
-      if (i_flag)
-       rs_start.rss_flags |= RF_IPC_VALID;
 
       if (do_run)
       {
index e0f465a7376e0974db3a2daa501d2a11c0b489c4..f81db6a0cf2bf659aa99b45b95dff832a35d080f 100755 (executable)
@@ -10,10 +10,10 @@ PROGRAMS=   ../kernel/kernel \
        ../servers/pm/pm \
        ../servers/vfs/vfs \
        ../servers/rs/rs \
-       ../servers/ds/ds \
-       ../drivers/tty/tty \
        ../drivers/memory/memory \
        ../drivers/log/log \
+       ../drivers/tty/tty \
+       ../servers/ds/ds \
        ../servers/mfs/mfs \
        ../servers/vm/vm \
        ../servers/init/init