From b8b8f537bdfd55181dcf910d048c3d1db29901de Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Thu, 2 Jul 2009 16:25:31 +0000 Subject: [PATCH] IPC privileges fixes 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 --- commands/swifi/run_t1 | 2 +- etc/drivers.conf | 4 +- kernel/main.c | 13 +- kernel/priv.h | 4 +- kernel/proc.c | 56 ++++---- kernel/proto.h | 2 + kernel/system.c | 42 ++++++ kernel/system/do_privctl.c | 34 ++--- kernel/table.c | 20 ++- servers/is/dmp_kernel.c | 5 +- servers/rs/manager.c | 272 +++++++++++++++++++++++++------------ servers/rs/service.c | 9 +- tools/Makefile | 4 +- 13 files changed, 297 insertions(+), 170 deletions(-) diff --git a/commands/swifi/run_t1 b/commands/swifi/run_t1 index 1bb2d524f..bea5420fb 100755 --- a/commands/swifi/run_t1 +++ b/commands/swifi/run_t1 @@ -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" ] diff --git a/etc/drivers.conf b/etc/drivers.conf index 8abc793f9..67501ad69 100644 --- a/etc/drivers.conf +++ b/etc/drivers.conf @@ -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 ; }; diff --git a/kernel/main.c b/kernel/main.c index 0c26fe171..3fdf0b867 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -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; jp_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 */ diff --git a/kernel/priv.h b/kernel/priv.h index 6d50cde2c..6775be7fb 100755 --- a/kernel/priv.h +++ b/kernel/priv.h @@ -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 diff --git a/kernel/proc.c b/kernel/proc.c index 0b5f43c36..bb3d8543f 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -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; diff --git a/kernel/proto.h b/kernel/proto.h index a3070efdd..c22930991 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -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) ); diff --git a/kernel/system.c b/kernel/system.c index 77642f62b..1af2b4920 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -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 * *===========================================================================*/ diff --git a/kernel/system/do_privctl.c b/kernel/system/do_privctl.c index c76706dc9..175da2bf7 100644 --- a/kernel/system/do_privctl.c +++ b/kernel/system/do_privctl.c @@ -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; ip_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; ip_priv->s_ipc_to, i)) { - set_sys_bit(priv_addr(i)->s_ipc_to, priv_id(rp)); - } - } - for (i=0; ip_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. */ diff --git a/kernel/table.c b/kernel/table.c index 408819bef..01a0c0edb 100755 --- a/kernel/table.c +++ b/kernel/table.c @@ -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" }, diff --git a/servers/is/dmp_kernel.c b/servers/is/dmp_kernel.c index 47c433565..a5a9c6960 100644 --- a/servers/is/dmp_kernel.c +++ b/servers/is/dmp_kernel.c @@ -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) { diff --git a/servers/rs/manager.c b/servers/rs/manager.c index e7c09c919..e9ae77aa1 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -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; rrpr_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; is_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; is_ipc_sendrec)*8; i++) + for (i= 0; is_ipc_sendrec.chunk[chunk] |= (1 << bit); + if (i != USER_PRIV_ID) + set_sys_bit(privp->s_ipc_to, i); } } } diff --git a/servers/rs/service.c b/servers/rs/service.c index a3b12b1bb..2351b4f77 100644 --- a/servers/rs/service.c +++ b/servers/rs/service.c @@ -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) { diff --git a/tools/Makefile b/tools/Makefile index e0f465a73..f81db6a0c 100755 --- a/tools/Makefile +++ b/tools/Makefile @@ -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 -- 2.44.0