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
This commit is contained in:
parent
aa84986819
commit
b8b8f537bd
@ -103,7 +103,7 @@ esac
|
|||||||
# Start our own driver.
|
# Start our own driver.
|
||||||
service down $LABEL
|
service down $LABEL
|
||||||
sleep 2 # Allow driver to die
|
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
|
i=0
|
||||||
while [ $i -lt "$count" ]
|
while [ $i -lt "$count" ]
|
||||||
|
@ -93,7 +93,7 @@ driver rtl8139
|
|||||||
;
|
;
|
||||||
pci device 10ec/8139;
|
pci device 10ec/8139;
|
||||||
ipc
|
ipc
|
||||||
SYSTEM PM RS LOG TTY DS
|
SYSTEM PM RS LOG TTY DS VM
|
||||||
pci inet amddev
|
pci inet amddev
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
@ -116,7 +116,7 @@ driver fxp
|
|||||||
;
|
;
|
||||||
pci device 8086/1229;
|
pci device 8086/1229;
|
||||||
ipc
|
ipc
|
||||||
SYSTEM PM RS LOG TTY DS
|
SYSTEM PM RS LOG TTY DS VM
|
||||||
pci inet amddev
|
pci inet amddev
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
@ -83,6 +83,10 @@ PUBLIC void main()
|
|||||||
priv(rp)->s_flags = ip->flags; /* process flags */
|
priv(rp)->s_flags = ip->flags; /* process flags */
|
||||||
priv(rp)->s_trap_mask = ip->trap_mask; /* allowed traps */
|
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.
|
/* Initialize call mask bitmap from unordered set.
|
||||||
* A single SYS_ALL_CALLS is a special case - it
|
* A single SYS_ALL_CALLS is a special case - it
|
||||||
* means all calls are allowed.
|
* means all calls are allowed.
|
||||||
@ -99,12 +103,9 @@ PUBLIC void main()
|
|||||||
SET_BIT(priv(rp)->s_k_call_mask,
|
SET_BIT(priv(rp)->s_k_call_mask,
|
||||||
ip->k_calls[ci]-KERNEL_CALL);
|
ip->k_calls[ci]-KERNEL_CALL);
|
||||||
|
|
||||||
priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to; /* restrict targets */
|
for (j = 0; j < NR_SYS_PROCS && j < BITCHUNK_BITS; j++)
|
||||||
|
if (ip->ipc_to & (1 << j))
|
||||||
for (j=0; j<BITMAP_CHUNKS(NR_SYS_PROCS); j++) {
|
set_sendto_bit(rp, j); /* restrict targets */
|
||||||
rp->p_priv->s_ipc_sendrec.chunk[j] = ~0L;
|
|
||||||
}
|
|
||||||
unset_sys_bit(rp->p_priv->s_ipc_sendrec, USER_PRIV_ID);
|
|
||||||
|
|
||||||
if (iskerneln(proc_nr(rp))) { /* part of the kernel? */
|
if (iskerneln(proc_nr(rp))) { /* part of the kernel? */
|
||||||
if (ip->stksize > 0) { /* HARDWARE stack size is 0 */
|
if (ip->stksize > 0) { /* HARDWARE stack size is 0 */
|
||||||
|
@ -36,9 +36,7 @@ struct priv {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
short s_trap_mask; /* allowed system call traps */
|
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_to; /* allowed destination processes */
|
||||||
sys_map_t s_ipc_sendrec; /* allowed sendrec processes */
|
|
||||||
|
|
||||||
/* allowed kernel calls */
|
/* allowed kernel calls */
|
||||||
#define CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_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 id_to_nr(id) priv_addr(id)->s_proc_nr
|
||||||
#define nr_to_id(nr) priv(proc_addr(nr))->s_id
|
#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
|
/* The system structures table and pointers to individual table slots. The
|
||||||
* pointers allow faster access because now a process entry can be found by
|
* 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
|
* indexing the psys_addr array, while accessing an element i requires a
|
||||||
|
@ -178,8 +178,7 @@ long bit_map; /* notification event set or flags */
|
|||||||
* addition to a real endpoint). The other calls (SEND, SENDREC,
|
* addition to a real endpoint). The other calls (SEND, SENDREC,
|
||||||
* and NOTIFY) require an endpoint to corresponds to a process. In addition,
|
* 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
|
* 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,
|
* destination.
|
||||||
* and NOTIFY we check s_ipc_to.
|
|
||||||
*/
|
*/
|
||||||
if (call_nr == SENDA)
|
if (call_nr == SENDA)
|
||||||
{
|
{
|
||||||
@ -201,13 +200,6 @@ long bit_map; /* notification event set or flags */
|
|||||||
}
|
}
|
||||||
else
|
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. */
|
/* Require a valid source and/or destination process. */
|
||||||
if(!isokendpt(src_dst_e, &src_dst_p)) {
|
if(!isokendpt(src_dst_e, &src_dst_p)) {
|
||||||
#if DEBUG_ENABLE_IPC_WARNINGS
|
#if DEBUG_ENABLE_IPC_WARNINGS
|
||||||
@ -219,29 +211,13 @@ long bit_map; /* notification event set or flags */
|
|||||||
return EDEADSRCDST;
|
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
|
* SENDREC or NOTIFY, verify that the caller is allowed to send to
|
||||||
* the given destination.
|
* the given destination.
|
||||||
*/
|
*/
|
||||||
if (call_nr == SENDREC)
|
if (call_nr != RECEIVE)
|
||||||
{
|
{
|
||||||
if (! get_sys_bit(priv(caller_ptr)->s_ipc_sendrec,
|
if (!may_send_to(caller_ptr, src_dst_p)) {
|
||||||
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 (! get_sys_bit(priv(caller_ptr)->s_ipc_to,
|
|
||||||
nr_to_id(src_dst_p))) {
|
|
||||||
#if DEBUG_ENABLE_IPC_WARNINGS
|
#if DEBUG_ENABLE_IPC_WARNINGS
|
||||||
kprintf(
|
kprintf(
|
||||||
"sys_call: ipc mask denied trap %d from %d to %d\n",
|
"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))
|
if (!isokendpt(tabent.dst, &dst_p))
|
||||||
{
|
{
|
||||||
/* Bad destination, report the error */
|
/* Bad destination, report the error */
|
||||||
|
if (caller_ptr->p_endpoint == ipc_stats_target)
|
||||||
|
ipc_stats.bad_endpoint++;
|
||||||
|
|
||||||
tabent.result= EDEADSRCDST;
|
tabent.result= EDEADSRCDST;
|
||||||
A_INSERT(i, result);
|
A_INSERT(i, result);
|
||||||
tabent.flags= flags | AMF_DONE;
|
tabent.flags= flags | AMF_DONE;
|
||||||
@ -833,6 +812,22 @@ size_t size;
|
|||||||
continue;
|
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
|
#if 0
|
||||||
kprintf("mini_senda: entry[%d]: flags 0x%x dst %d/%d\n",
|
kprintf("mini_senda: entry[%d]: flags 0x%x dst %d/%d\n",
|
||||||
i, tabent.flags, tabent.dst, dst_p);
|
i, tabent.flags, tabent.dst, dst_p);
|
||||||
@ -843,6 +838,9 @@ size_t size;
|
|||||||
/* NO_ENDPOINT should be removed */
|
/* NO_ENDPOINT should be removed */
|
||||||
if (dst_ptr->p_rts_flags & NO_ENDPOINT)
|
if (dst_ptr->p_rts_flags & NO_ENDPOINT)
|
||||||
{
|
{
|
||||||
|
if (caller_ptr->p_endpoint == ipc_stats_target)
|
||||||
|
ipc_stats.dst_died++;
|
||||||
|
|
||||||
tabent.result= EDSTDIED;
|
tabent.result= EDSTDIED;
|
||||||
A_INSERT(i, result);
|
A_INSERT(i, result);
|
||||||
tabent.flags= flags | AMF_DONE;
|
tabent.flags= flags | AMF_DONE;
|
||||||
@ -928,6 +926,8 @@ struct proc *caller_ptr;
|
|||||||
privp->s_proc_nr);
|
privp->s_proc_nr);
|
||||||
#endif
|
#endif
|
||||||
src_ptr= proc_addr(privp->s_proc_nr);
|
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);
|
r= try_one(src_ptr, caller_ptr);
|
||||||
if (r == OK)
|
if (r == OK)
|
||||||
return r;
|
return r;
|
||||||
|
@ -55,6 +55,8 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
|
|||||||
|
|
||||||
/* system.c */
|
/* system.c */
|
||||||
_PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type) );
|
_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 send_sig, (int proc_nr, int sig_nr) );
|
||||||
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
|
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
|
||||||
_PROTOTYPE( void sys_task, (void) );
|
_PROTOTYPE( void sys_task, (void) );
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
* In addition to the main sys_task() entry point, which starts the main loop,
|
* In addition to the main sys_task() entry point, which starts the main loop,
|
||||||
* there are several other minor entry points:
|
* there are several other minor entry points:
|
||||||
* get_priv: assign privilege structure to user or system process
|
* 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
|
* send_sig: send a signal directly to a system process
|
||||||
* cause_sig: take action to cause a signal to occur via PM
|
* cause_sig: take action to cause a signal to occur via PM
|
||||||
* umap_bios: map virtual address in BIOS_SEG to physical
|
* umap_bios: map virtual address in BIOS_SEG to physical
|
||||||
@ -290,6 +292,46 @@ int proc_type; /* system or user process flag */
|
|||||||
return(OK);
|
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 *
|
* send_sig *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -70,24 +70,14 @@ message *m_ptr; /* pointer to request message */
|
|||||||
|
|
||||||
/* Now update the process' privileges as requested. */
|
/* Now update the process' privileges as requested. */
|
||||||
rp->p_priv->s_trap_mask = FILLED_MASK;
|
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.
|
/* Set a default send mask. */
|
||||||
* Therefore, their send masks should be updated as well.
|
|
||||||
*/
|
|
||||||
for (i=0; i < NR_SYS_PROCS; i++) {
|
for (i=0; i < NR_SYS_PROCS; i++) {
|
||||||
if (get_sys_bit(rp->p_priv->s_ipc_to, i)) {
|
if (i != USER_PRIV_ID)
|
||||||
set_sys_bit(priv_addr(i)->s_ipc_to, priv_id(rp));
|
set_sendto_bit(rp, i);
|
||||||
|
else
|
||||||
|
unset_sendto_bit(rp, i);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<BITMAP_CHUNKS(NR_SYS_PROCS); i++) {
|
|
||||||
rp->p_priv->s_ipc_sendrec.chunk[i] = FILLED_MASK;
|
|
||||||
}
|
|
||||||
unset_sys_bit(rp->p_priv->s_ipc_sendrec, USER_PRIV_ID);
|
|
||||||
|
|
||||||
/* No I/O resources, no memory resources, no IRQs, no grant table */
|
/* No I/O resources, no memory resources, no IRQs, no grant table */
|
||||||
priv(rp)->s_nr_io_range= 0;
|
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,
|
memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
|
||||||
sizeof(priv(rp)->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));
|
/* Set a custom send mask. */
|
||||||
memcpy(&priv(rp)->s_ipc_sendrec, &priv.s_ipc_sendrec,
|
for (i=0; i < NR_SYS_PROCS; i++) {
|
||||||
sizeof(priv(rp)->s_ipc_sendrec));
|
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. */
|
/* Done. Privileges have been set. Allow process to run again. */
|
||||||
|
@ -60,18 +60,15 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
|
|||||||
|
|
||||||
/* Send masks determine to whom processes can send messages or notifications.
|
/* 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 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
|
* the boot image table itself to match the order of the process numbers, so
|
||||||
* processes in the boot image, so that the send mask that is defined here
|
* that the send mask that is defined here can be interpreted properly.
|
||||||
* can be directly copied onto map[0] of the actual send mask. Privilege
|
* Privilege structure 0 is shared by user processes.
|
||||||
* structure 0 is shared by user processes.
|
|
||||||
*/
|
*/
|
||||||
#define s(n) (1 << (s_nr_to_id(n)))
|
#define s(n) (1 << (s_nr_to_id(n)))
|
||||||
#define NUL_M 0
|
|
||||||
#define SRV_M (~0)
|
#define SRV_M (~0)
|
||||||
#define SYS_M (~0)
|
#define SYS_M (~0)
|
||||||
#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(SYSTEM) | \
|
#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(VM_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 DRV_M (USR_M | s(SYSTEM) | s(CLOCK) | 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
|
/* 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.
|
* 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 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
|
* 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
|
* Each entry provides the process number, flags, quantum size, scheduling
|
||||||
* queue, allowed traps, ipc mask, and a name for the process table. The
|
* 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" },
|
{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" },
|
{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" },
|
{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"},
|
{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" },
|
{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" },
|
{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" },
|
{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" },
|
{INIT_PROC_NR, 0,USR_F, 8, USER_Q, 0, USR_T, USR_M, no_c,"init" },
|
||||||
|
@ -363,7 +363,7 @@ PUBLIC void privileges_dmp()
|
|||||||
return;
|
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)
|
PROCLOOP(rp, oldrp)
|
||||||
r = -1;
|
r = -1;
|
||||||
@ -379,9 +379,6 @@ PUBLIC void privileges_dmp()
|
|||||||
for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
|
for (i=0; i < NR_SYS_PROCS; i += BITCHUNK_BITS) {
|
||||||
printf(" %04x", get_sys_bits(sp->s_ipc_to, i));
|
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(" ");
|
printf(" ");
|
||||||
for (i=0; i < NR_SYS_CALLS; i += BITCHUNK_BITS) {
|
for (i=0; i < NR_SYS_CALLS; i += BITCHUNK_BITS) {
|
||||||
|
@ -30,6 +30,12 @@ FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
|
|||||||
FORWARD _PROTOTYPE( int fork_nb, (void) );
|
FORWARD _PROTOTYPE( int fork_nb, (void) );
|
||||||
FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
|
FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
|
||||||
FORWARD _PROTOTYPE( void run_script, (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_privs, (struct rproc *rp, struct priv *privp) );
|
||||||
FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
|
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 *
|
* init_privs *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
@ -1051,13 +1227,8 @@ struct rproc *rp;
|
|||||||
struct priv *privp;
|
struct priv *privp;
|
||||||
{
|
{
|
||||||
int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
|
int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
|
||||||
src_bit, call_nr, chunk, bit, priv_id, slot_nr;
|
src_bit, call_nr;
|
||||||
endpoint_t proc_nr_e;
|
|
||||||
size_t len;
|
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
char *p, *q;
|
|
||||||
struct rproc *tmp_rp;
|
|
||||||
char label[MAX_LABEL_LEN+1];
|
|
||||||
|
|
||||||
/* Clear s_k_call_mask */
|
/* Clear s_k_call_mask */
|
||||||
memset(privp->s_k_call_mask, '\0', sizeof(privp->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_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)
|
if (strlen(rp->r_ipc_list) != 0)
|
||||||
{
|
{
|
||||||
for (p= rp->r_ipc_list; p[0] != '\0'; p= q)
|
add_forward_ipc(rp, privp);
|
||||||
{
|
add_backward_ipc(rp, privp);
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
for (i= 0; i<sizeof(privp->s_ipc_to)*8; i++)
|
for (i= 0; i<NR_SYS_PROCS; i++)
|
||||||
{
|
{
|
||||||
chunk= (i / (sizeof(bitchunk_t)*8));
|
if (i != USER_PRIV_ID)
|
||||||
bit= (i % (sizeof(bitchunk_t)*8));
|
set_sys_bit(privp->s_ipc_to, i);
|
||||||
privp->s_ipc_to.chunk[chunk] |= (1 << bit);
|
|
||||||
}
|
|
||||||
for (i= 0; i<sizeof(privp->s_ipc_sendrec)*8; i++)
|
|
||||||
{
|
|
||||||
chunk= (i / (sizeof(bitchunk_t)*8));
|
|
||||||
bit= (i % (sizeof(bitchunk_t)*8));
|
|
||||||
privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,6 @@ PRIVATE int parse_arguments(int argc, char **argv)
|
|||||||
int req_nr;
|
int req_nr;
|
||||||
int c, i;
|
int c, i;
|
||||||
int c_flag;
|
int c_flag;
|
||||||
int i_flag=0;
|
|
||||||
|
|
||||||
c_flag= 0;
|
c_flag= 0;
|
||||||
while (c= getopt(argc, argv, "ci?"), c != -1)
|
while (c= getopt(argc, argv, "ci?"), c != -1)
|
||||||
@ -148,7 +147,9 @@ PRIVATE int parse_arguments(int argc, char **argv)
|
|||||||
c_flag= 1;
|
c_flag= 1;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
i_flag= 1;
|
/* Legacy - remove later */
|
||||||
|
fputs("WARNING: obsolete -i flag passed to service(8)\n",
|
||||||
|
stderr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: getopt failed: %c\n",
|
fprintf(stderr, "%s: getopt failed: %c\n",
|
||||||
@ -186,11 +187,9 @@ PRIVATE int parse_arguments(int argc, char **argv)
|
|||||||
|
|
||||||
req_nr= RS_START;
|
req_nr= RS_START;
|
||||||
|
|
||||||
rs_start.rss_flags= 0;
|
rs_start.rss_flags= RF_IPC_VALID;
|
||||||
if (c_flag)
|
if (c_flag)
|
||||||
rs_start.rss_flags |= RF_COPY;
|
rs_start.rss_flags |= RF_COPY;
|
||||||
if (i_flag)
|
|
||||||
rs_start.rss_flags |= RF_IPC_VALID;
|
|
||||||
|
|
||||||
if (do_run)
|
if (do_run)
|
||||||
{
|
{
|
||||||
|
@ -10,10 +10,10 @@ PROGRAMS= ../kernel/kernel \
|
|||||||
../servers/pm/pm \
|
../servers/pm/pm \
|
||||||
../servers/vfs/vfs \
|
../servers/vfs/vfs \
|
||||||
../servers/rs/rs \
|
../servers/rs/rs \
|
||||||
../servers/ds/ds \
|
|
||||||
../drivers/tty/tty \
|
|
||||||
../drivers/memory/memory \
|
../drivers/memory/memory \
|
||||||
../drivers/log/log \
|
../drivers/log/log \
|
||||||
|
../drivers/tty/tty \
|
||||||
|
../servers/ds/ds \
|
||||||
../servers/mfs/mfs \
|
../servers/mfs/mfs \
|
||||||
../servers/vm/vm \
|
../servers/vm/vm \
|
||||||
../servers/init/init
|
../servers/init/init
|
||||||
|
Loading…
x
Reference in New Issue
Block a user