#include "../../kernel/proc.h"
#include "../../servers/pm/mproc.h"
+#include "../../servers/pm/const.h"
#include "../../servers/vfs/fproc.h"
#include "../../servers/vfs/const.h"
#include "../../servers/mfs/const.h"
if(endpoints) bufp->ps_pid = ps_proc[p_ki].p_endpoint;
else bufp->ps_pid = ps_mproc[p_nr].mp_pid;
bufp->ps_ppid = ps_mproc[ps_mproc[p_nr].mp_parent].mp_pid;
+ /* Assume no parent when the parent and the child share the same pid.
+ * This is what PM currently assumes.
+ */
+ if(bufp->ps_ppid == bufp->ps_pid) {
+ bufp->ps_ppid = NO_PID;
+ }
bufp->ps_pgrp = ps_mproc[p_nr].mp_procgrp;
bufp->ps_mflags = ps_mproc[p_nr].mp_flags;
} else {
if(endpoints) bufp->ps_pid = ps_proc[p_ki].p_endpoint;
- else bufp->ps_pid = 0;
- bufp->ps_ppid = 0;
+ else bufp->ps_pid = NO_PID;
+ bufp->ps_ppid = NO_PID;
bufp->ps_ruid = bufp->ps_euid = 0;
bufp->ps_pgrp = 0;
bufp->ps_mflags = 0;
#define VM_PROC_NR 8 /* memory server */
#define INIT_PROC_NR 9 /* init -- goes multiuser */
+/* Root system process and root user process. */
+#define ROOT_SYS_PROC_NR RS_PROC_NR
+#define ROOT_USR_PROC_NR INIT_PROC_NR
+
/* Number of processes contained in the system image. */
#define NR_BOOT_PROCS (NR_TASKS + INIT_PROC_NR + 1)
#define SYS_ALL_CALLS (NR_SYS_CALLS)
/* Subfunctions for SYS_PRIVCTL */
-#define SYS_PRIV_INIT 1 /* Initialize a privilege structure */
-#define SYS_PRIV_ADD_IO 2 /* Add I/O range (struct io_range) */
-#define SYS_PRIV_ADD_MEM 3 /* Add memory range (struct mem_range)
- */
-#define SYS_PRIV_ADD_IRQ 4 /* Add IRQ */
-#define SYS_PRIV_USER 5 /* Make a process an oridinary user
- * process.
+#define SYS_PRIV_ALLOW 1 /* Allow process to run */
+#define SYS_PRIV_DISALLOW 2 /* Disallow process to run */
+#define SYS_PRIV_SET_SYS 3 /* Set a system privilege structure */
+#define SYS_PRIV_SET_USER 4 /* Set a user privilege structure */
+#define SYS_PRIV_ADD_IO 5 /* Add I/O range (struct io_range) */
+#define SYS_PRIV_ADD_MEM 6 /* Add memory range (struct mem_range)
*/
-#define SYS_PRIV_QUERY_MEM 6 /* Verify memory privilege. */
+#define SYS_PRIV_ADD_IRQ 7 /* Add IRQ */
+#define SYS_PRIV_QUERY_MEM 8 /* Verify memory privilege. */
/* Subfunctions for SYS_SETGRANT */
#define SYS_PARAM_SET_GRANT 1 /* Set address and size of grant table */
# define GET_BIOSBUFFER 14 /* get a buffer for BIOS calls */
# define GET_LOADINFO 15 /* get load average information */
# define GET_IRQACTIDS 16 /* get the IRQ masks */
-# define GET_PRIVID 17 /* get ID of privilege structure */
+# define GET_PRIV 17 /* get privilege structure */
# define GET_HZ 18 /* get HZ value */
# define GET_WHOAMI 19 /* get own name and endpoint */
# define GET_RANDOMNESS_BIN 20 /* get one randomness bin */
# define GET_IDLETSC 21 /* get cumulative idle time stamp counter */
+# define GET_AOUTHEADER 22 /* get a.out headers from the boot image */
#define I_ENDPT m7_i4 /* calling process */
#define I_VAL_PTR m7_p1 /* virtual address at caller */
#define I_VAL_LEN m7_i1 /* max length of value */
#define SERVARNAME "cttyline"
/* Bits for the system property flags in boot image processes. */
+#define PROC_FULLVM 0x100 /* VM sets and manages full pagetable */
+
+/* Bits for s_flags in the privilege structure. */
#define PREEMPTIBLE 0x02 /* kernel tasks are not preemptible */
#define BILLABLE 0x04 /* some processes are not billable */
+#define DYN_PRIV_ID 0x08 /* privilege id assigned dynamically */
#define SYS_PROC 0x10 /* system processes have own priv structure */
#define CHECK_IO_PORT 0x20 /* check if I/O request is allowed */
#define CHECK_IRQ 0x40 /* check if IRQ can be used */
#define CHECK_MEM 0x80 /* check if (VM) mem map request is allowed */
-#define PROC_FULLVM 0x100 /* VM sets and manages full pagetable */
-
* retrieve/set a process-virtual timer.
*/
_PROTOTYPE( int sys_times, (endpoint_t proc_ep, clock_t *user_time,
- clock_t *sys_time, clock_t *uptime));
+ clock_t *sys_time, clock_t *uptime, time_t *boottime));
_PROTOTYPE(int sys_setalarm, (clock_t exp_time, int abs_time));
_PROTOTYPE( int sys_vtimer, (endpoint_t proc_nr, int which, clock_t *newval,
clock_t *oldval));
#define sys_getmonparams(v,vl) sys_getinfo(GET_MONPARAMS, v,vl, 0,0)
#define sys_getschedinfo(v1,v2) sys_getinfo(GET_SCHEDINFO, v1,0, v2,0)
#define sys_getlocktimings(dst) sys_getinfo(GET_LOCKTIMING, dst, 0,0,0)
-#define sys_getprivid(nr) sys_getinfo(GET_PRIVID, 0, 0,0, nr)
+#define sys_getpriv(dst, nr) sys_getinfo(GET_PRIV, dst, 0,0, nr)
#define sys_getidletsc(dst) sys_getinfo(GET_IDLETSC, dst, 0,0,0)
+#define sys_getaoutheader(dst,nr) sys_getinfo(GET_AOUTHEADER, dst, 0,0,nr)
_PROTOTYPE(int sys_getinfo, (int request, void *val_ptr, int val_len,
void *val_ptr2, int val_len2) );
_PROTOTYPE(int sys_whoami, (endpoint_t *ep, char *name, int namelen));
#include "config.h"
#include "debug.h"
-/* Map a process number to a privilege structure id. */
-#define s_nr_to_id(n) (NR_TASKS + (n) + 1)
-
/* Translate a pointer to a field in a structure to a pointer to the structure
* itself. So it translates '&struct_ptr->field' back to 'struct_ptr'.
*/
ktsb = (reg_t) t_stack;
for (i=0; i < NR_BOOT_PROCS; ++i) {
- int ci;
+ int schedulable_proc, proc_nr;
+ int ipc_to_m, kcalls;
bitchunk_t fv;
ip = &image[i]; /* process' attributes */
rp->p_quantum_size = ip->quantum; /* quantum size in ticks */
rp->p_ticks_left = ip->quantum; /* current credit */
strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
- (void) get_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */
- 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) && (ip->flags & SYS_PROC))
- 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.
+ /* See if this process is immediately schedulable.
+ * In that case, set its privileges now and allow it to run.
+ * Only kernel tasks and the root system process get to run immediately.
+ * All the other system processes are inhibited from running by the
+ * RTS_NO_PRIV flag. They can only be scheduled once the root system
+ * process has set their privileges.
*/
- if(ip->nr_k_calls == 1 && ip->k_calls[0] == SYS_ALL_CALLS)
- fv = ~0; /* fill call mask */
- else
- fv = 0; /* clear call mask */
-
- for(ci = 0; ci < CALL_MASK_SIZE; ci++) /* fill or clear call mask */
- priv(rp)->s_k_call_mask[ci] = fv;
- if(!fv) /* not all full? enter calls bit by bit */
- for(ci = 0; ci < ip->nr_k_calls; ci++)
- SET_BIT(priv(rp)->s_k_call_mask,
- ip->k_calls[ci]-KERNEL_CALL);
-
- 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? */
+ proc_nr = proc_nr(rp);
+ schedulable_proc = (iskerneln(proc_nr) || isrootsysn(proc_nr));
+ if(schedulable_proc) {
+ /* Assign privilege structure. Force a static privilege id. */
+ (void) get_priv(rp, static_priv_id(proc_nr));
+
+ /* Priviliges for kernel tasks. */
+ if(iskerneln(proc_nr)) {
+ /* Privilege flags. */
+ priv(rp)->s_flags = (proc_nr == IDLE ? IDL_F : TSK_F);
+ /* Allowed traps. */
+ priv(rp)->s_trap_mask = (proc_nr == CLOCK
+ || proc_nr == SYSTEM ? CSK_T : TSK_T);
+ ipc_to_m = TSK_M; /* allowed targets */
+ kcalls = TSK_KC; /* allowed kernel calls */
+ }
+ /* Priviliges for the root system process. */
+ else if(isrootsysn(proc_nr)) {
+ priv(rp)->s_flags= RSYS_F; /* privilege flags */
+ priv(rp)->s_trap_mask= RSYS_T; /* allowed traps */
+ ipc_to_m = RSYS_M; /* allowed targets */
+ kcalls = RSYS_KC; /* allowed kernel calls */
+ }
+
+ /* Fill in target mask. */
+ for (j=0; j < NR_SYS_PROCS; j++) {
+ if (ipc_to_m & (1 << j))
+ set_sendto_bit(rp, j);
+ else
+ unset_sendto_bit(rp, j);
+ }
+
+ /* Fill in kernel call mask. */
+ for(j = 0; j < CALL_MASK_SIZE; j++) {
+ priv(rp)->s_k_call_mask[j] = (kcalls == NO_C ? 0 : (~0));
+ }
+ }
+ else {
+ /* Don't let the process run for now. */
+ RTS_SET(rp, RTS_NO_PRIV);
+ }
+
+ if (iskerneln(proc_nr)) { /* part of the kernel? */
if (ip->stksize > 0) { /* HARDWARE stack size is 0 */
rp->p_priv->s_stack_guard = (reg_t *) ktsb;
*rp->p_priv->s_stack_guard = STACK_GUARD;
rp->p_reg.sp = ktsb; /* this task's initial stack ptr */
hdrindex = 0; /* all use the first a.out header */
} else {
- hdrindex = 1 + i-NR_TASKS; /* servers, drivers, INIT */
+ hdrindex = 1 + i-NR_TASKS; /* system/user processes */
}
/* Architecture-specific way to find out aout header of this
* access I/O; this is not allowed to less-privileged processes
*/
rp->p_reg.pc = (reg_t) ip->initial_pc;
- rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW;
+ rp->p_reg.psw = (iskerneln(proc_nr)) ? INIT_TASK_PSW : INIT_PSW;
/* Initialize the server stack pointer. Take it down one word
* to give crtso.s something to use as "argc".
*/
- if (isusern(proc_nr(rp))) { /* user-space process? */
+ if (isusern(proc_nr)) { /* user-space process? */
rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
rp->p_reg.sp -= sizeof(reg_t);
* PT up and manage it. VM will signal the kernel when it has
* done this; until then, don't let it run.
*/
- if(priv(rp)->s_flags & PROC_FULLVM)
+ if(ip->flags & PROC_FULLVM)
RTS_SET(rp, RTS_VMINHIBIT);
-
+
/* Set ready. The HARDWARE task is never ready. */
if (rp->p_nr == HARDWARE) RTS_SET(rp, RTS_PROC_STOP);
/* IDLE task is never put on a run queue as it is never ready to run */
* between common and privileged process fields and is very space efficient.
*
* Changes:
- * Jul 01, 2005 Created. (Jorrit N. Herder)
+ * Nov 22, 2009 rewrite of privilege management (Cristiano Giuffrida)
+ * Jul 01, 2005 Created. (Jorrit N. Herder)
*/
#include <minix/com.h>
#include "const.h"
/* Guard word for task stacks. */
#define STACK_GUARD ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF))
+/* Static privilege id definitions. */
+#define NR_STATIC_PRIV_IDS NR_BOOT_PROCS
+#define is_static_priv_id(id) (id >= 0 && id < NR_STATIC_PRIV_IDS)
+#define static_priv_id(n) (NR_TASKS + (n))
+
/* Magic system structure table addresses. */
-#define BEG_PRIV_ADDR (&priv[0])
-#define END_PRIV_ADDR (&priv[NR_SYS_PROCS])
+#define BEG_PRIV_ADDR (&priv[0])
+#define END_PRIV_ADDR (&priv[NR_SYS_PROCS])
+#define BEG_STATIC_PRIV_ADDR BEG_PRIV_ADDR
+#define END_STATIC_PRIV_ADDR (BEG_STATIC_PRIV_ADDR + NR_STATIC_PRIV_IDS)
+#define BEG_DYN_PRIV_ADDR END_STATIC_PRIV_ADDR
+#define END_DYN_PRIV_ADDR END_PRIV_ADDR
#define priv_addr(i) (ppriv_addr)[(i)]
#define priv_id(rp) ((rp)->p_priv->s_id)
#define may_send_to(rp, nr) (get_sys_bit(priv(rp)->s_ipc_to, nr_to_id(nr)))
+/* Privilege management shorthands. */
+#define spi_to(n) (1 << (static_priv_id(n)))
+#define unset_usr_to(m) ((m) & ~(1 << USER_PRIV_ID))
+
/* 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
EXTERN struct priv priv[NR_SYS_PROCS]; /* system properties table */
EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
-/* Unprivileged user processes all share the same privilege structure.
+/* Unprivileged user processes all share the privilege structure of the
+ * root user process.
* This id must be fixed because it is used to check send mask entries.
*/
-#define USER_PRIV_ID 0
+#define USER_PRIV_ID static_priv_id(ROOT_USR_PROC_NR)
+/* Specifies a null privilege id.
+ */
+#define NULL_PRIV_ID -1
/* Make sure the system can boot. The following sanity check verifies that
* the system privileges table is large enough for the number of processes
#error NR_SYS_PROCS must be larger than NR_BOOT_PROCS
#endif
+/*
+ * Privileges masks used by the kernel.
+ */
+#define IDL_F (SYS_PROC | BILLABLE) /* idle task is not preemptible as we
+ * don't want it to interfere with the
+ * timer tick interrupt handler code.
+ * Unlike other processes idle task is
+ * handled in a special way and is
+ * preempted always if timer tick occurs
+ * and there is another runnable process
+ */
+#define TSK_F (SYS_PROC) /* other kernel tasks */
+#define RSYS_F (SYS_PROC | PREEMPTIBLE) /* root system proc */
+#define DEF_SYS_F (RSYS_F | DYN_PRIV_ID) /* default sys proc */
+
+/* allowed traps */
+#define CSK_T (1 << RECEIVE) /* clock and system */
+#define TSK_T 0 /* other kernel tasks */
+#define RSYS_T (~0) /* root system proc */
+#define DEF_SYS_T RSYS_T /* default sys proc */
+
+/* allowed targets */
+#define TSK_M 0 /* all kernel tasks */
+#define RSYS_M (~0) /* root system proc */
+#define DEF_SYS_M unset_usr_to(RSYS_M) /* default sys proc */
+
+/* allowed kernel calls */
+#define NO_C 0 /* no calls allowed */
+#define ALL_C 1 /* all calls allowed */
+#define TSK_KC NO_C /* all kernel tasks */
+#define RSYS_KC ALL_C /* root system proc */
+#define DEF_SYS_KC RSYS_KC /* default sys proc */
+
#endif /* PRIV_H */
}
/* Destination is not ready to receive the notification. Add it to the
- * bit map with pending notifications. Note the indirectness: the system id
+ * bit map with pending notifications. Note the indirectness: the privilege id
* instead of the process number is used in the pending bit map.
*/
src_id = priv(caller_ptr)->s_id;
#define iskerneln(n) ((n) < 0)
#define isuserp(p) isusern((p) >= BEG_USER_ADDR)
#define isusern(n) ((n) >= 0)
+#define isrootsysp(p) isrootsysn((p)->p_nr)
+#define isrootsysn(n) ((n) == ROOT_SYS_PROC_NR)
#ifndef __ASSEMBLY__
* clear_endpoint: remove a process' ability to send and receive messages
*
* Changes:
+* Nov 22, 2009 get_priv supports static priv ids (Cristiano Giuffrida)
* Aug 04, 2005 check if system call is allowed (Jorrit N. Herder)
* Jul 20, 2005 send signal to services with message (Jorrit N. Herder)
* Jan 15, 2005 new, generalized virtual copy function (Jorrit N. Herder)
/*===========================================================================*
* get_priv *
*===========================================================================*/
-PUBLIC int get_priv(rc, proc_type)
+PUBLIC int get_priv(rc, priv_id)
register struct proc *rc; /* new (child) process pointer */
-int proc_type; /* system or user process flag */
+int priv_id; /* privilege id */
{
-/* Get a privilege structure. All user processes share the same privilege
- * structure. System processes get their own privilege structure.
+/* Allocate a new privilege structure for a system process. Privilege ids
+ * can be assigned either statically or dynamically.
*/
- register struct priv *sp; /* privilege structure */
-
- if (proc_type == SYS_PROC) { /* find a new slot */
- for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp)
- if (sp->s_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break;
- if (sp >= END_PRIV_ADDR) return(ENOSPC);
- rc->p_priv = sp; /* assign new slot */
- rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */
- rc->p_priv->s_flags = SYS_PROC; /* mark as privileged */
-
- /* Clear some fields */
- sp->s_asyntab= -1;
- sp->s_asynsize= 0;
- } else {
- rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */
- rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */
+ register struct priv *sp; /* privilege structure */
- /* s_flags of this shared structure are to be once at system startup. */
+ if(priv_id == NULL_PRIV_ID) { /* allocate slot dynamically */
+ for (sp = BEG_DYN_PRIV_ADDR; sp < END_DYN_PRIV_ADDR; ++sp)
+ if (sp->s_proc_nr == NONE) break;
+ if (sp >= END_DYN_PRIV_ADDR) return(ENOSPC);
+ }
+ else { /* allocate slot from id */
+ if(!is_static_priv_id(priv_id)) {
+ return EINVAL; /* invalid static priv id */
+ }
+ if(priv[priv_id].s_proc_nr != NONE) {
+ return EBUSY; /* slot already in use */
+ }
+ sp = &priv[priv_id];
}
+ rc->p_priv = sp; /* assign new slot */
+ rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */
+
+ /* Clear some fields */
+ sp->s_asyntab= -1;
+ sp->s_asynsize= 0;
+
return(OK);
}
/* 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
+ /* Disallow the process from sending to a process privilege structure with no
* associated process, and disallow the process from sending to itself.
*/
- if (id_to_nr(id) == NONE || priv_id(rp) == id)
+ if (id_to_nr(id) == NONE || priv_id(rp) == id) {
+ unset_sys_bit(priv(rp)->s_ipc_to, 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.
+ /* The process that this process can now send to, must be able to reply (or
+ * vice versa). Therefore, its send mask should be updated as well. Ignore
+ * receivers that don't support traps other than RECEIVE, they can't reply
+ * or send messages anyway.
*/
- rrp = proc_addr(id_to_nr(id));
- if (!iskernelp(rrp))
- set_sys_bit(priv(rrp)->s_ipc_to, priv_id(rp));
+ if (priv_addr(id)->s_trap_mask & ~((1 << RECEIVE)))
+ set_sys_bit(priv_addr(id)->s_ipc_to, priv_id(rp));
}
/*===========================================================================*
*/
#include <string.h>
+#include <minix/endpoint.h>
#include "../system.h"
#include "../vm.h"
int proc_nr, nr_e, nr, r;
struct proc *caller;
int wipe_rnd_bin = -1;
+ struct exec e_hdr;
caller = proc_addr(who_p);
src_vir = (vir_bytes) proc_addr(nr);
break;
}
+ case GET_PRIV: {
+ nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
+ who_e : m_ptr->I_VAL_LEN2_E;
+ if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
+ length = sizeof(struct priv);
+ src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
+ break;
+ }
case GET_WHOAMI: {
int len;
/* GET_WHOAMI uses m3 and only uses the message contents for info. */
src_vir = (vir_bytes) irq_actids;
break;
}
- case GET_PRIVID: {
- if (!isokendpt(m_ptr->I_VAL_LEN2_E, &proc_nr))
- return EINVAL;
- return proc_addr(proc_nr)->p_priv->s_id;
- }
case GET_IDLETSC: {
#ifdef CONFIG_IDLE_TSC
length = sizeof(idle_tsc);
return(EINVAL);
#endif
}
+ case GET_AOUTHEADER: {
+ int hdrindex, index = m_ptr->I_VAL_LEN2_E;
+ if(index < 0 || index >= NR_BOOT_PROCS) {
+ return EINVAL;
+ }
+ if (iskerneln(_ENDPOINT_P(image[index].endpoint))) {
+ hdrindex = 0;
+ } else {
+ hdrindex = 1 + index-NR_TASKS;
+ }
+ arch_get_aout_headers(hdrindex, &e_hdr);
+ length = sizeof(e_hdr);
+ src_vir = (vir_bytes) &e_hdr;
+ break;
+ }
+
default:
kprintf("do_getinfo: invalid request %d\n", m_ptr->I_REQUEST);
return(EINVAL);
#if USE_PRIVCTL
-#define FILLED_MASK (~0)
-
/*===========================================================================*
* do_privctl *
*===========================================================================*/
register struct proc *rp;
int proc_nr;
int priv_id;
+ int ipc_to_m, kcalls;
int i, r;
struct io_range io_range;
struct mem_range mem_range;
switch(m_ptr->CTL_REQUEST)
{
- case SYS_PRIV_INIT:
+ case SYS_PRIV_ALLOW:
+ /* Allow process to run. Make sure its privilege structure has already
+ * been set.
+ */
+ if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
+ return(EPERM);
+ }
+ RTS_LOCK_UNSET(rp, RTS_NO_PRIV);
+ return(OK);
+
+ case SYS_PRIV_DISALLOW:
+ /* Disallow process from running. */
+ if (RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
+ RTS_LOCK_SET(rp, RTS_NO_PRIV);
+ return(OK);
+
+ case SYS_PRIV_SET_SYS:
+ /* Set a privilege structure of a blocked system process. */
if (! RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
+ /* Check whether a static or dynamic privilege id must be allocated. */
+ priv_id = NULL_PRIV_ID;
+ if (m_ptr->CTL_ARG_PTR)
+ {
+ /* Copy privilege structure from caller */
+ if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
+ SYSTEM, (vir_bytes) &priv, sizeof(priv))) != OK)
+ return r;
+
+ /* See if the caller wants to assign a static privilege id. */
+ if(!(priv.s_flags & DYN_PRIV_ID)) {
+ priv_id = priv.s_id;
+ }
+ }
+
/* Make sure this process has its own privileges structure. This may
* fail, since there are only a limited number of system processes.
- * Then copy the privileges from the caller and restore some defaults.
+ * Then copy privileges from the caller and restore some defaults.
*/
- if ((i=get_priv(rp, SYS_PROC)) != OK)
+ if ((i=get_priv(rp, priv_id)) != OK)
{
- kprintf("do_privctl: out of priv structures\n");
+ kprintf("do_privctl: unable to allocate priv_id %d: %d\n",
+ priv_id, i);
return(i);
}
priv_id = priv(rp)->s_id; /* backup privilege id */
priv(rp)->s_int_pending = 0; /* - interrupts */
sigemptyset(&priv(rp)->s_sig_pending); /* - signals */
- /* Now update the process' privileges as requested. */
- rp->p_priv->s_trap_mask = 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);
+ /* Set defaults for privilege bitmaps. */
+ priv(rp)->s_flags= DEF_SYS_F; /* privilege flags */
+ priv(rp)->s_trap_mask= DEF_SYS_T; /* allowed traps */
+ ipc_to_m = DEF_SYS_M; /* allowed targets */
+ kcalls = DEF_SYS_KC; /* allowed kernel calls */
+ for(i = 0; i < CALL_MASK_SIZE; i++) {
+ priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
}
- /* No I/O resources, no memory resources, no IRQs, no grant table */
+ /* Set defaults for resources: no I/O resources, no memory resources,
+ * no IRQs, no grant table
+ */
priv(rp)->s_nr_io_range= 0;
priv(rp)->s_nr_mem_range= 0;
priv(rp)->s_nr_irq= 0;
priv(rp)->s_grant_table= 0;
priv(rp)->s_grant_entries= 0;
+ /* Override defaults if the caller has supplied a privilege structure. */
if (m_ptr->CTL_ARG_PTR)
{
- /* Copy privilege structure from caller */
- if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
- SYSTEM, (vir_bytes) &priv, sizeof(priv))) != OK)
- return r;
-
- /* Copy the call mask */
- for (i= 0; i<CALL_MASK_SIZE; i++)
- priv(rp)->s_k_call_mask[i]= priv.s_k_call_mask[i];
+ /* Copy s_flags. */
+ priv(rp)->s_flags = priv.s_flags;
/* Copy IRQs */
- if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
- return EINVAL;
- priv(rp)->s_nr_irq= priv.s_nr_irq;
- for (i= 0; i<priv.s_nr_irq; i++)
- {
- priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
+ if(priv.s_flags & CHECK_IRQ) {
+ if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
+ return EINVAL;
+ priv(rp)->s_nr_irq= priv.s_nr_irq;
+ for (i= 0; i<priv.s_nr_irq; i++)
+ {
+ priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
#if 0
- kprintf("do_privctl: adding IRQ %d for %d\n",
- priv(rp)->s_irq_tab[i], rp->p_endpoint);
+ kprintf("do_privctl: adding IRQ %d for %d\n",
+ priv(rp)->s_irq_tab[i], rp->p_endpoint);
#endif
+ }
}
- priv(rp)->s_flags |= CHECK_IRQ; /* Check requests for IRQs */
-
/* Copy I/O ranges */
- if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
- return EINVAL;
- priv(rp)->s_nr_io_range= priv.s_nr_io_range;
- for (i= 0; i<priv.s_nr_io_range; i++)
- {
- priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
+ if(priv.s_flags & CHECK_IO_PORT) {
+ if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
+ return EINVAL;
+ priv(rp)->s_nr_io_range= priv.s_nr_io_range;
+ for (i= 0; i<priv.s_nr_io_range; i++)
+ {
+ priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
+#if 0
+ kprintf("do_privctl: adding I/O range [%x..%x] for %d\n",
+ priv(rp)->s_io_tab[i].ior_base,
+ priv(rp)->s_io_tab[i].ior_limit,
+ rp->p_endpoint);
+#endif
+ }
+ }
+
+ /* Copy memory ranges */
+ if(priv.s_flags & CHECK_MEM) {
+ if (priv.s_nr_mem_range < 0 || priv.s_nr_mem_range > NR_MEM_RANGE)
+ return EINVAL;
+ priv(rp)->s_nr_mem_range= priv.s_nr_mem_range;
+ for (i= 0; i<priv.s_nr_mem_range; i++)
+ {
+ priv(rp)->s_mem_tab[i]= priv.s_mem_tab[i];
#if 0
- kprintf("do_privctl: adding I/O range [%x..%x] for %d\n",
- priv(rp)->s_io_tab[i].ior_base,
- priv(rp)->s_io_tab[i].ior_limit,
- rp->p_endpoint);
+ kprintf("do_privctl: adding mem range [%x..%x] for %d\n",
+ priv(rp)->s_mem_tab[i].mr_base,
+ priv(rp)->s_mem_tab[i].mr_limit,
+ rp->p_endpoint);
#endif
+ }
}
- /* Check requests for IRQs */
- priv(rp)->s_flags |= CHECK_IO_PORT;
+ /* Copy trap mask. */
+ priv(rp)->s_trap_mask = priv.s_trap_mask;
+
+ /* Copy target mask. */
+ memcpy(&ipc_to_m, &priv.s_ipc_to, sizeof(ipc_to_m));
+ /* Copy kernel call mask. */
memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
sizeof(priv(rp)->s_k_call_mask));
+ }
- /* 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);
- }
+ /* Fill in target mask. */
+ for (i=0; i < NR_SYS_PROCS; i++) {
+ if (ipc_to_m & (1 << i))
+ set_sendto_bit(rp, i);
+ else
+ unset_sendto_bit(rp, i);
}
- /* Done. Privileges have been set. Allow process to run again. */
- RTS_LOCK_UNSET(rp, RTS_NO_PRIV);
return(OK);
- case SYS_PRIV_USER:
- /* Make this process an ordinary user process. */
+
+ case SYS_PRIV_SET_USER:
+ /* Set a privilege structure of a blocked user process. */
if (!RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
- if ((i=get_priv(rp, 0)) != OK) return(i);
- RTS_LOCK_UNSET(rp, RTS_NO_PRIV);
+
+ /* Link the process to the privilege structure of the root user
+ * process all the user processes share.
+ */
+ priv(rp) = priv_addr(USER_PRIV_ID);
+
return(OK);
case SYS_PRIV_ADD_IO:
* include 'boot_image' (this file) and 'idt' and 'gdt' (protect.c).
*
* Changes:
+ * Nov 22, 2009 rewrite of privilege management (Cristiano Giuffrida)
* Aug 02, 2005 set privileges and minimal boot image (Jorrit N. Herder)
* Oct 17, 2004 updated above and tasktab comments (Jorrit N. Herder)
* May 01, 2004 changed struct for system image (Jorrit N. Herder)
/* Stack space for all the task stacks. Declared as (char *) to align it. */
#define TOT_STACK_SPACE (IDL_S + HRD_S + (2 * TSK_S))
PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
-
-/* Define flags for the various process types. */
-#define IDL_F (SYS_PROC | BILLABLE) /* idle task is not preemptible as we
- * don't want it to interfere with the
- * timer tick interrupt handler code.
- * Unlike other processes idle task is
- * handled in a special way and is
- * preempted always if timer tick occurs
- * and there is another runnable process
- */
-#define TSK_F (SYS_PROC) /* kernel tasks */
-#define SRV_F (SYS_PROC | PREEMPTIBLE) /* system services */
-#define VM_F (SYS_PROC) /* vm */
-#define USR_F (BILLABLE | PREEMPTIBLE | PROC_FULLVM) /* user processes */
-#define SVM_F (SRV_F | PROC_FULLVM) /* servers with VM */
-/* Define system call traps for the various process types. These call masks
- * determine what system call traps a process is allowed to make.
- */
-#define TSK_T (1 << RECEIVE) /* clock and system */
-#define SRV_T (~0) /* system services */
-#define USR_T ((1 << SENDREC)) /* user processes */
-
-/* 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 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 SRV_M (~0)
-#define SYS_M (~0)
-#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.
- * Note that the reincarnation server has all bits on, because it should
- * be allowed to distribute rights to services that it starts.
- *
- * Calls are unordered lists, converted by the kernel to bitmasks
- * once at runtime.
- */
-#define FS_C SYS_KILL, SYS_VIRCOPY, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, \
- SYS_VIRVCOPY, SYS_UMAP, SYS_GETINFO, SYS_EXIT, SYS_TIMES, SYS_SETALARM, \
- SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
-#define DRV_C FS_C, SYS_SEGCTL, SYS_IRQCTL, SYS_INT86, SYS_DEVIO, \
- SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
-
-PRIVATE int
- fs_c[] = { FS_C },
- pm_c[] = { SYS_ALL_CALLS },
- rs_c[] = { SYS_ALL_CALLS },
- ds_c[] = { SYS_ALL_CALLS },
- vm_c[] = { SYS_ALL_CALLS },
- drv_c[] = { DRV_C },
- usr_c[] = { SYS_SYSCTL },
- tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
- SYS_READBIOS },
- mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE };
+/* Define boot process flags. */
+#define BVM_F (PROC_FULLVM) /* boot processes with VM */
/* 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. Furthermore, the
- * order of the entries MUST agree with their process numbers. See above.
+ * in the boot image and all kernel tasks must come first.
*
* Each entry provides the process number, flags, quantum size, scheduling
- * queue, allowed traps, ipc mask, and a name for the process table. The
- * initial program counter and stack size is also provided for kernel tasks.
+ * queue, and a name for the process table. The initial program counter and
+ * stack size is also provided for kernel tasks.
*
* Note: the quantum size must be positive in all cases!
*/
-#define c(calls) calls, (sizeof(calls) / sizeof((calls)[0]))
-#define no_c { 0 }, 0
PUBLIC struct boot_image image[] = {
-/* process nr, pc,flags, qs, queue, stack, traps, ipcto, call, name */
-{IDLE, NULL,IDL_F, 0, 0, IDL_S, 0, 0, no_c,"idle" },
-{CLOCK,clock_task,TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, no_c,"clock" },
-{SYSTEM, sys_task,TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, no_c,"system"},
-{HARDWARE, 0,TSK_F, 8, TASK_Q, HRD_S, 0, 0, no_c,"kernel"},
-{PM_PROC_NR, 0,SRV_F, 32, 4, 0, SRV_T, SRV_M, c(pm_c),"pm" },
-{FS_PROC_NR, 0,SRV_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" },
-{MEM_PROC_NR, 0,SVM_F, 4, 3, 0, SRV_T, SYS_M,c(mem_c),"memory"},
-{LOG_PROC_NR, 0,SRV_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,VM_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, c(usr_c),"init" },
+/* process nr, pc, flags, qs, queue, stack, name */
+{IDLE, NULL, 0, 0, 0, IDL_S, "idle" },
+{CLOCK,clock_task, 0, 8, TASK_Q, TSK_S, "clock" },
+{SYSTEM, sys_task, 0, 8, TASK_Q, TSK_S, "system"},
+{HARDWARE, 0, 0, 8, TASK_Q, HRD_S, "kernel"},
+{PM_PROC_NR, 0, 0, 32, 4, 0, "pm" },
+{FS_PROC_NR, 0, 0, 32, 5, 0, "vfs" },
+{RS_PROC_NR, 0, 0, 4, 4, 0, "rs" },
+{MEM_PROC_NR, 0, BVM_F, 4, 3, 0, "memory"},
+{LOG_PROC_NR, 0, BVM_F, 4, 2, 0, "log" },
+{TTY_PROC_NR, 0, BVM_F, 4, 1, 0, "tty" },
+{DS_PROC_NR, 0, BVM_F, 4, 4, 0, "ds" },
+{MFS_PROC_NR, 0, BVM_F, 32, 5, 0, "mfs" },
+{VM_PROC_NR, 0, 0, 32, 2, 0, "vm" },
+{INIT_PROC_NR, 0, BVM_F, 8, USER_Q, 0, "init" },
};
/* Verify the size of the system image table at compile time. Also verify that
unsigned char quantum; /* quantum (tick count) */
int priority; /* scheduling priority */
int stksize; /* stack size for tasks */
- short trap_mask; /* allowed system call traps */
- bitchunk_t ipc_to; /* send mask protection */
- int *k_calls; /* kern. call protection */
- int nr_k_calls;
char proc_name[P_NAME_LEN]; /* name in process table */
endpoint_t endpoint; /* endpoint number when started */
};
#include "syslib.h"
-PUBLIC int sys_times(proc_ep, user_time, sys_time, uptime)
+PUBLIC int sys_times(proc_ep, user_time, sys_time, uptime, boottime)
endpoint_t proc_ep; /* proc_ep whose times are needed */
clock_t *user_time; /* time spend in the process itself */
clock_t *sys_time; /* time spend in system on behalf of the
* process
*/
clock_t *uptime; /* time the system is running */
+time_t *boottime; /* boot time */
{
/* Fetch the accounting info for a proc_ep. */
message m;
if (user_time) *user_time = m.T_USER_TIME;
if (sys_time) *sys_time = m.T_SYSTEM_TIME;
if (uptime) *uptime = m.T_BOOT_TICKS;
+ if (boottime) *boottime = m.T_BOOTTIME;
return(r);
}
int fd; /* generally useful */
int linenr; /* loop variable */
int check; /* check if a new process must be spawned */
+ int sn; /* signal number */
struct slotent *slotp; /* slots[] pointer */
struct ttyent *ttyp; /* ttytab entry */
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
+ /* Default: Ignore every signal (except those that follow). */
+ sa.sa_handler = SIG_IGN;
+ for (sn = 1; sn < _NSIG; sn++) {
+ sigaction(sn, &sa, NULL);
+ }
+
/* Hangup: Reexamine /etc/ttytab for newly enabled terminal lines. */
sa.sa_handler = onhup;
sigaction(SIGHUP, &sa, NULL);
FORWARD _PROTOTYPE( char *s_traps_str, (int flags) );
FORWARD _PROTOTYPE( char *s_flags_str, (int flags) );
FORWARD _PROTOTYPE( char *p_rts_flags_str, (int flags) );
+FORWARD _PROTOTYPE( char *boot_flags_str, (int flags) );
/* Some global data that is shared among several dumping procedures.
* Note that the process table copy has the same name as in the kernel
printf("\n");
}
+/*===========================================================================*
+ * boot_flags_str *
+ *===========================================================================*/
+PRIVATE char *boot_flags_str(int flags)
+{
+ static char str[10];
+ str[0] = (flags & PROC_FULLVM) ? 'V' : '-';
+ str[1] = '\0';
+
+ return str;
+}
+
/*===========================================================================*
* image_dmp *
*===========================================================================*/
{
int m, i,j,r;
struct boot_image *ip;
- static char ipc_to[BITCHUNK_BITS*2];
if ((r = sys_getimage(image)) != OK) {
report("IS","warning: couldn't get copy of image table", r);
return;
}
printf("Image table dump showing all processes included in system image.\n");
- printf("---name-- -nr- -flags- -traps- -sq- ----pc- -stack- -ipc_to[0]--------\n");
+ printf("---name- -nr- ----pc- flags -qs- -queue- -stack-\n");
for (m=0; m<NR_BOOT_PROCS; m++) {
ip = &image[m];
- for (i=j=0; i < BITCHUNK_BITS; i++, j++) {
- ipc_to[j] = (ip->ipc_to & (1<<i)) ? '1' : '0';
- if (i % 8 == 7) ipc_to[++j] = ' ';
- }
- ipc_to[j] = '\0';
- printf("%8s %4d %s %s %3d %7lu %7lu %s\n",
- ip->proc_name, ip->proc_nr,
- s_flags_str(ip->flags), s_traps_str(ip->trap_mask),
- ip->priority, (long)ip->initial_pc, ip->stksize, ipc_to);
+ printf("%8s %4d %7lu %5s %4d %7d %7lu\n",
+ ip->proc_name, ip->proc_nr, (long)ip->initial_pc,
+ boot_flags_str(ip->flags), ip->quantum, ip->priority, ip->stksize);
}
printf("\n");
}
printf("\n");
}
+/*===========================================================================*
+ * s_flags_str *
+ *===========================================================================*/
PRIVATE char *s_flags_str(int flags)
{
static char str[10];
- str[0] = (flags & PREEMPTIBLE) ? 'P' : '-';
- str[1] = '-';
- str[2] = (flags & BILLABLE) ? 'B' : '-';
- str[3] = (flags & SYS_PROC) ? 'S' : '-';
- str[4] = '-';
- str[5] = '\0';
+ str[0] = (flags & PREEMPTIBLE) ? 'P' : '-';
+ str[1] = (flags & BILLABLE) ? 'B' : '-';
+ str[2] = (flags & DYN_PRIV_ID) ? 'D' : '-';
+ str[3] = (flags & SYS_PROC) ? 'S' : '-';
+ str[4] = (flags & CHECK_IO_PORT) ? 'I' : '-';
+ str[5] = (flags & CHECK_IRQ) ? 'Q' : '-';
+ str[6] = (flags & CHECK_MEM) ? 'M' : '-';
+ str[7] = '\0';
return str;
}
+/*===========================================================================*
+ * s_traps_str *
+ *===========================================================================*/
PRIVATE char *s_traps_str(int flags)
{
static char str[10];
return;
}
- printf("\n--nr-id-name---- -flags- -traps- grants -ipc_to-- -system calls--\n");
+ printf("-nr- -id- -name-- -flags- traps grants -ipc_to-- -kernel calls-\n");
PROCLOOP(rp, oldrp)
r = -1;
if (r == -1 && !isemptyp(rp)) {
sp = &priv[USER_PRIV_ID];
}
- printf("(%02u) %-7.7s %s %s %7d",
+ printf("(%02u) %-7.7s %s %s %7d",
sp->s_id, rp->p_name,
s_flags_str(sp->s_flags), s_traps_str(sp->s_trap_mask),
sp->s_grant_entries);
}
}
+/*===========================================================================*
+ * p_rts_flags_str *
+ *===========================================================================*/
PRIVATE char *p_rts_flags_str(int flags)
{
static char str[10];
#include <timers.h>
#include <minix/rs.h>
#include "../../kernel/priv.h"
-#include "../rs/manager.h"
+#include "../rs/const.h"
+#include "../rs/type.h"
PUBLIC struct rproc rproc[NR_SYS_PROCS];
getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc);
printf("Reincarnation Server (RS) system process table dump\n");
- printf("-endpoint-flag--dev- -T---checked----alive-starts-backoff-label command-\n");
+ printf("----label---- endpoint- -pid- flags -dev- -T- alive_tm starts command\n");
for (i=prev_i; i<NR_SYS_PROCS; i++) {
rp = &rproc[i];
if (! rp->r_flags & RS_IN_USE) continue;
if (++n > 22) break;
- printf("%9d %s %3d/%2d %3u %8u %8u %4dx %3d %s %s",
- rp->r_proc_nr_e,
- s_flags_str(rp->r_flags),
- rp->r_dev_nr, rp->r_dev_style,
- rp->r_period,
- rp->r_check_tm, rp->r_alive_tm,
- rp->r_restarts, rp->r_backoff,
- rp->r_label,
+ printf("%13s %9d %5d %5s %3d/%1d %3u %8u %5dx %s",
+ rp->r_label, rp->r_proc_nr_e, rp->r_pid,
+ s_flags_str(rp->r_flags), rp->r_dev_nr, rp->r_dev_style,
+ rp->r_period, rp->r_alive_tm, rp->r_restarts,
rp->r_cmd
);
printf("\n");
PRIVATE char *s_flags_str(int flags)
{
- static char str[5];
- str[0] = (flags & RS_IN_USE) ? 'U' : '-';
- str[1] = (flags & RS_EXITING) ? 'E' : '-';
- str[2] = '-';
- str[3] = '\0';
+ static char str[10];
+ str[0] = (flags & RS_IN_USE) ? 'U' : '-';
+ str[1] = (flags & RS_EXITING) ? 'E' : '-';
+ str[2] = (flags & RS_REFRESHING) ? 'R' : '-';
+ str[3] = (flags & RS_NOPINGREPLY) ? 'N' : '-';
+ str[4] = '-';
+ str[5] = '\0';
return(str);
}
* a 'short' instead of pid_t.)
*/
-#define PM_PID 0 /* PM's process id number */
+#define NO_PID 0 /* pid value indicating no process */
#define INIT_PID 1 /* INIT's process id number */
#define NO_TRACER 0 /* process is not being traced */
if (rmp->mp_flags & ALARM_ON) set_alarm(rmp, (clock_t) 0);
/* Do accounting: fetch usage times and accumulate at parent. */
- if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL)) != OK)
+ if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL, NULL)) != OK)
panic(__FILE__,"exit_proc: sys_times failed", r);
p_mp = &mproc[rmp->mp_parent]; /* process' parent */
*===========================================================================*/
PRIVATE void pm_init()
{
- int failed = 0;
- int f = 0;
/* Initialize the process manager.
* Memory use info is collected from the boot monitor, the kernel, and
* all processes compiled into the system image. Initially this information
/* Set process details found in the image table. */
rmp = &mproc[ip->proc_nr];
strncpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN);
-#if 0
- rmp->mp_parent = RS_PROC_NR;
-#endif
rmp->mp_nice = get_nice_value(ip->priority);
sigemptyset(&rmp->mp_sig2mess);
sigemptyset(&rmp->mp_ignore);
sigemptyset(&rmp->mp_sigmask);
sigemptyset(&rmp->mp_catch);
if (ip->proc_nr == INIT_PROC_NR) { /* user process */
+ /* INIT is root, we make it father of itself. This is
+ * not really OK, INIT should have no father, i.e.
+ * a father with pid NO_PID. But PM currently assumes
+ * that mp_parent always points to a valid slot number.
+ */
+ rmp->mp_parent = INIT_PROC_NR;
rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
rmp->mp_flags |= IN_USE;
}
else { /* system process */
+ if(ip->proc_nr == RS_PROC_NR) {
+ rmp->mp_parent = INIT_PROC_NR;
+ }
+ else {
+ rmp->mp_parent = RS_PROC_NR;
+ }
rmp->mp_pid = get_free_pid();
rmp->mp_flags |= IN_USE | PRIV_PROC;
for (sig_ptr = mess_sigs;
mess.PR_ENDPT = rmp->mp_endpoint;
if (OK != (s=send(FS_PROC_NR, &mess)))
panic(__FILE__,"can't sync up with FS", s);
-
- /* Register proces with ds */
- s= ds_publish_u32(rmp->mp_name, rmp->mp_endpoint);
- if (s != OK)
- failed++;
}
}
- if(failed > 0)
- printf("PM: failed to register %d/%d boot processes\n",
- failed, NR_BOOT_PROCS);
-
- /* Override some details. INIT, PM, FS and RS are somewhat special. */
- mproc[PM_PROC_NR].mp_pid = PM_PID; /* PM has magic pid */
-#if 0
- mproc[RS_PROC_NR].mp_parent = INIT_PROC_NR; /* INIT is root */
-#endif
+ /* Override some details for PM. */
sigfillset(&mproc[PM_PROC_NR].mp_ignore); /* guard against signals */
/* Tell FS that no more system processes follow and synchronize. */
strcpy(uts_val.machine + 1, itoa(getprocessor()));
#endif
- if(f > 0) printf("PM: failed to register %d processes with DS.\n", f);
-
system_hz = sys_hz();
/* Map out our own text and data. This is normally done in crtso.o
clock_t user_time, sys_time, uptime;
int s;
- if (OK != (s=sys_times(who_e, &user_time, &sys_time, &uptime)))
+ if (OK != (s=sys_times(who_e, &user_time, &sys_time, &uptime, NULL)))
panic(__FILE__,"do_times couldn't get times", s);
rmp->mp_reply.reply_t1 = user_time; /* user time */
rmp->mp_reply.reply_t2 = sys_time; /* system time */
LIBS = -lsys
UTIL_OBJ = service.o
-OBJ = exec.o main.o manager.o
+OBJ = exec.o main.o manager.o table.o utility.o memory.o
# build local binary
all build: $(SERVER) $(UTIL)
$(CC) -o $@ $(LDFLAGS) $(UTIL_OBJ) $(UTIL_LIBS)
$(SERVER): $(OBJ)
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
- install -S 32k $@
+ install -S 350k $@
# install with other servers
install: /bin/$(UTIL) /usr/sbin/$(SERVER)
--- /dev/null
+/* Global constants used in RS.
+ */
+#ifndef RS_CONST_H
+#define RS_CONST_H
+
+/* Space reserved for program and arguments. */
+#define MAX_COMMAND_LEN 512 /* maximum argument string length */
+#define MAX_LABEL_LEN 16 /* Unique name of (this instance of)
+ * the driver
+ */
+#define MAX_SCRIPT_LEN 256 /* maximum restart script name length */
+#define MAX_NR_ARGS 4 /* maximum number of arguments */
+#define MAX_RESCUE_DIR_LEN 64 /* maximum rescue dir length */
+
+#define MAX_IPC_LIST 256 /* Max size of list for IPC target
+ * process names
+ */
+#define MAX_VM_LIST 256
+
+/* Flag values. */
+#define RS_IN_USE 0x001 /* set when process slot is in use */
+#define RS_EXITING 0x004 /* set when exit is expected */
+#define RS_REFRESHING 0x008 /* set when refresh must be done */
+#define RS_NOPINGREPLY 0x010 /* driver failed to reply to a ping request */
+#define RS_KILLED 0x020 /* driver is killed */
+#define RS_CRASHED 0x040 /* driver crashed */
+#define RS_LATEREPLY 0x080 /* no reply sent to RS_DOWN caller yet */
+#define RS_SIGNALED 0x100 /* driver crashed */
+
+/* Sys flag values. */
+#define SF_CORE_PROC 0x001 /* set for core system processes
+ * XXX FIXME: This should trigger a system
+ * panic when a CORE_PROC service cannot
+ * be restarted. We need better error-handling
+ * in RS to change this.
+ */
+#define SF_NEED_COPY 0x004 /* set when process needs copy to restart */
+#define SF_USE_COPY 0x008 /* set when process has a copy in memory */
+
+/* Constants determining RS period and binary exponential backoff. */
+#define RS_DELTA_T 60 /* check every T ticks */
+#define BACKOFF_BITS (sizeof(long)*8) /* bits in backoff field */
+#define MAX_BACKOFF 30 /* max backoff in RS_DELTA_T */
+
+/* Magic process table addresses. */
+#define BEG_RPROC_ADDR (&rproc[0])
+#define END_RPROC_ADDR (&rproc[NR_SYS_PROCS])
+#define NIL_RPROC ((struct mproc *) 0)
+
+
+/* Definitions for boot info tables. */
+#define NULL_BOOT_NR NR_BOOT_PROCS /* marks a null boot entry */
+#define DEFAULT_BOOT_NR NR_BOOT_PROCS /* marks the default boot entry */
+#define SYS_ALL_C (NR_SYS_CALLS+0) /* specifies all calls */
+#define SYS_NULL_C (NR_SYS_CALLS+1) /* marks a null call entry */
+
+/* Define privilege flags for the various process types. */
+#define SRV_F (SYS_PROC | PREEMPTIBLE) /* system services */
+#define DSRV_F (SRV_F | DYN_PRIV_ID | CHECK_IO_PORT | CHECK_IRQ)
+ /* dynamic system services */
+#define VM_F (SYS_PROC) /* vm */
+#define RUSR_F (BILLABLE | PREEMPTIBLE) /* root user proc */
+
+/* Define system call traps for the various process types. These call masks
+ * determine what system call traps a process is allowed to make.
+ */
+#define SRV_T (~0) /* system services */
+#define DSRV_T SRV_T /* dynamic system services */
+#define RUSR_T (1 << SENDREC) /* root user proc */
+
+/* Send masks determine to whom processes can send messages or notifications. */
+#define SRV_M (~0) /* system services */
+#define RUSR_M \
+ ( spi_to(PM_PROC_NR) | spi_to(FS_PROC_NR) | spi_to(RS_PROC_NR) \
+ | spi_to(VM_PROC_NR) ) /* root user proc */
+
+/* Define sys flags for the various process types. */
+#define SRV_SF (SF_CORE_PROC | SF_NEED_COPY) /* system services */
+#define SRVC_SF (SRV_SF | SF_USE_COPY) /* system services with a copy */
+#define DSRV_SF (0) /* dynamic system services */
+
+#endif /* RS_CONST_H */
+
--- /dev/null
+/* Global variables used in RS.
+ */
+#ifndef RS_GLO_H
+#define RS_GLO_H
+
+#ifdef _TABLE
+#undef EXTERN
+#define EXTERN
+#endif
+
+/* The boot image priv table. This table has entries for all system
+ * services in the boot image.
+ */
+extern struct boot_image_priv boot_image_priv_table[];
+
+/* The boot image sys table. This table has entries for system services in
+ * the boot image that override default sys properties.
+ */
+extern struct boot_image_sys boot_image_sys_table[];
+
+/* The boot image dev table. This table has entries for system services in
+ * the boot image that support dev properties.
+ */
+extern struct boot_image_dev boot_image_dev_table[];
+
+/* The system process table. This table only has entries for system
+ * services (servers and drivers), and thus is not directly indexed by
+ * slot number.
+ */
+EXTERN struct rproc rproc[NR_SYS_PROCS];
+EXTERN struct rproc *rproc_ptr[NR_PROCS]; /* mapping for fast access */
+
+/* Pipe for detection of exec failures. The pipe is close-on-exec, and
+ * no data will be written to the pipe if the exec succeeds. After an
+ * exec failure, the slot number is written to the pipe. After each exit,
+ * a non-blocking read retrieves the slot number from the pipe.
+ */
+EXTERN int exec_pipe[2];
+
+/* Enable/disable verbose output. */
+EXTERN long rs_verbose;
+
+#endif /* RS_GLO_H */
+
#define _SYSTEM 1 /* get OK and negative error codes */
#define _MINIX 1 /* tell headers to include MINIX stuff */
-#define VERBOSE 0 /* display diagnostics */
-
#include <ansi.h>
#include <sys/types.h>
#include <limits.h>
#include <minix/keymap.h>
#include <minix/bitmap.h>
#include <minix/rs.h>
+#include <minix/dmap.h>
+#include <minix/endpoint.h>
#include <archtypes.h>
#include <timers.h> /* For priv.h */
#include "../../kernel/priv.h"
+#include "../../kernel/ipc.h"
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include "proto.h"
-#include "manager.h"
+#include "const.h"
+#include "type.h"
+#include "glo.h"
* services to see whether they are still alive. The system services are
* expected to periodically send a heartbeat message.
*
- * Created:
- * Jul 22, 2005 by Jorrit N. Herder
+ * Changes:
+ * Nov 22, 2009: rewrite of boot process (Cristiano Giuffrida)
+ * Jul 22, 2005: Created (Jorrit N. Herder)
*/
#include "inc.h"
#include <fcntl.h>
-#include <minix/endpoint.h>
+#include <a.out.h>
+#include <minix/crtso.h>
#include "../../kernel/const.h"
#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+#include "../pm/mproc.h"
+#include "../pm/const.h"
/* Declare some local functions. */
+FORWARD _PROTOTYPE(void exec_image_copy, ( int boot_proc_idx,
+ struct boot_image *ip, struct rproc *rp) );
+FORWARD _PROTOTYPE(void boot_image_info_lookup, ( endpoint_t endpoint,
+ struct boot_image *image,
+ struct boot_image **ip, struct boot_image_priv **pp,
+ struct boot_image_sys **sp, struct boot_image_dev **dp) );
+FORWARD _PROTOTYPE(void fill_call_mask, ( int *calls, int tot_nr_calls,
+ bitchunk_t *call_mask, int call_base) );
FORWARD _PROTOTYPE(void init_server, (void) );
FORWARD _PROTOTYPE(void sig_handler, (void) );
FORWARD _PROTOTYPE(void get_work, (message *m) );
FORWARD _PROTOTYPE(void reply, (int whom, message *m_out) );
-/* Data buffers to retrieve info during initialization. */
-PRIVATE struct boot_image image[NR_BOOT_PROCS];
+/* The buffer where the boot image is copied during initialization. */
+PRIVATE int boot_image_buffer_size;
+PRIVATE char *boot_image_buffer;
-long rs_verbose = 0;
+/* Macro to identify a system service in the boot image. This rules out
+ * kernel tasks and the root system process (RS).
+ */
+#define isbootsrvprocn(n) (!iskerneln((n)) && !isrootsysn((n)))
+
+/* Flag set when memory unmapping can be done. */
+EXTERN int unmap_ok;
/*===========================================================================*
* main *
}
}
+/*===========================================================================*
+ * exec_image_copy *
+ *===========================================================================*/
+PRIVATE void exec_image_copy(boot_proc_idx, ip, rp)
+int boot_proc_idx;
+struct boot_image *ip;
+struct rproc *rp;
+{
+/* Copy the executable image of the given boot process. */
+ int s;
+ struct exec header;
+ static char *boot_image_ptr = NULL;
+
+ if(boot_image_ptr == NULL) {
+ boot_image_ptr = boot_image_buffer;
+ }
+ s = NO_NUM;
+
+ /* Get a.out header. */
+ if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < sizeof(header)
+ || (s = sys_getaoutheader(&header, boot_proc_idx)) != OK) {
+ panic("RS", "unable to get copy of a.out header", s);
+ }
+ memcpy(boot_image_ptr, &header, header.a_hdrlen);
+ boot_image_ptr += header.a_hdrlen;
+
+ /* Get text segment. */
+ if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < header.a_text
+ || (s = rs_startup_segcopy(ip->endpoint, T, D, (vir_bytes) boot_image_ptr,
+ header.a_text)) != OK) {
+ panic("RS", "unable to get copy of text segment", s);
+ }
+ boot_image_ptr += header.a_text;
+
+ /* Get data segment. */
+ if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < header.a_data
+ || (s = rs_startup_segcopy(ip->endpoint, D, D, (vir_bytes) boot_image_ptr,
+ header.a_data)) != OK) {
+ panic("RS", "unable to get copy of data segment", s);
+ }
+ boot_image_ptr += header.a_data;
+
+ /* Set the executable image for the given boot process. */
+ rp->r_exec_len = header.a_hdrlen + header.a_text + header.a_data;
+ rp->r_exec = boot_image_ptr - rp->r_exec_len;
+}
+
+/*===========================================================================*
+ * boot_image_info_lookup *
+ *===========================================================================*/
+PRIVATE void boot_image_info_lookup(endpoint, image, ip, pp, sp, dp)
+endpoint_t endpoint;
+struct boot_image *image;
+struct boot_image **ip;
+struct boot_image_priv **pp;
+struct boot_image_sys **sp;
+struct boot_image_dev **dp;
+{
+/* Lookup entries in boot image tables. */
+ int i;
+
+ /* When requested, locate the corresponding entry in the boot image table
+ * or panic if not found.
+ */
+ if(ip) {
+ for (i=0; i < NR_BOOT_PROCS; i++) {
+ if(image[i].endpoint == endpoint) {
+ *ip = &image[i];
+ break;
+ }
+ }
+ if(i == NR_BOOT_PROCS) {
+ panic("RS", "boot image table lookup failed", NO_NUM);
+ }
+ }
+
+ /* When requested, locate the corresponding entry in the boot image priv table
+ * or panic if not found.
+ */
+ if(pp) {
+ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+ if(boot_image_priv_table[i].endpoint == endpoint) {
+ *pp = &boot_image_priv_table[i];
+ break;
+ }
+ }
+ if(i == NULL_BOOT_NR) {
+ panic("RS", "boot image priv table lookup failed", NO_NUM);
+ }
+ }
+
+ /* When requested, locate the corresponding entry in the boot image sys table
+ * or resort to the default entry if not found.
+ */
+ if(sp) {
+ for (i=0; boot_image_sys_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
+ if(boot_image_sys_table[i].endpoint == endpoint) {
+ *sp = &boot_image_sys_table[i];
+ break;
+ }
+ }
+ if(boot_image_sys_table[i].endpoint == DEFAULT_BOOT_NR) {
+ *sp = &boot_image_sys_table[i]; /* accept the default entry */
+ }
+ }
+
+ /* When requested, locate the corresponding entry in the boot image dev table
+ * or resort to the default entry if not found.
+ */
+ if(dp) {
+ for (i=0; boot_image_dev_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
+ if(boot_image_dev_table[i].endpoint == endpoint) {
+ *dp = &boot_image_dev_table[i];
+ break;
+ }
+ }
+ if(boot_image_dev_table[i].endpoint == DEFAULT_BOOT_NR) {
+ *dp = &boot_image_dev_table[i]; /* accept the default entry */
+ }
+ }
+}
+
+/*===========================================================================*
+ * fill_call_mask *
+ *===========================================================================*/
+PRIVATE void fill_call_mask(calls, tot_nr_calls, call_mask, call_base)
+int *calls; /* the unordered set of calls */
+int tot_nr_calls; /* the total number of calls */
+bitchunk_t *call_mask; /* the call mask to fill in */
+int call_base; /* the base offset for the calls */
+{
+/* Fill a call mask from an unordered set of calls. */
+ int i;
+ bitchunk_t fv;
+ int call_mask_size, nr_calls;
+
+ call_mask_size = BITMAP_CHUNKS(tot_nr_calls);
+
+ /* Count the number of calls to fill in. */
+ nr_calls = 0;
+ for(i=0; calls[i] != SYS_NULL_C; i++) {
+ nr_calls++;
+ }
+
+ /* See if all calls are allowed and call mask must be completely filled. */
+ fv = 0;
+ if(nr_calls == 1 && calls[0] == SYS_ALL_C) {
+ fv = (~0);
+ }
+
+ /* Fill or clear call mask. */
+ for(i=0; i < call_mask_size; i++) {
+ call_mask[i] = fv;
+ }
+
+ /* Not all calls allowed? Enter calls bit by bit. */
+ if(!fv) {
+ for(i=0; i < nr_calls; i++) {
+ SET_BIT(call_mask, calls[i] - call_base);
+ }
+ }
+}
/*===========================================================================*
* init_server *
/* Initialize the reincarnation server. */
struct sigaction sa;
struct boot_image *ip;
- int s,t;
+ int s,i,j;
+ int nr_image_srvs, nr_image_priv_srvs;
+ struct rproc *rp;
+ struct boot_image image[NR_BOOT_PROCS];
+ struct mproc mproc[NR_PROCS];
+ struct exec header;
+ struct boot_image_priv *boot_image_priv;
+ struct boot_image_sys *boot_image_sys;
+ struct boot_image_dev *boot_image_dev;
+
+ /* See if we run in verbose mode. */
+ env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
+
+ /* Get a copy of the boot image table. */
+ if ((s = sys_getimage(image)) != OK) {
+ panic("RS", "unable to get copy of boot image table", s);
+ }
+
+ /* Determine the number of system services in the boot image table and
+ * compute the size required for the boot image buffer.
+ */
+ nr_image_srvs = 0;
+ boot_image_buffer_size = 0;
+ for(i=0;i<NR_BOOT_PROCS;i++) {
+ ip = &image[i];
+
+ /* System services only. */
+ if(!isbootsrvprocn(_ENDPOINT_P(ip->endpoint))) {
+ continue;
+ }
+ nr_image_srvs++;
+
+ /* Lookup the corresponding entry in the boot image sys table. */
+ boot_image_info_lookup(ip->endpoint, image,
+ NULL, NULL, &boot_image_sys, NULL);
+
+ /* If we must keep a copy of this system service, read the header
+ * and increase the size of the boot image buffer.
+ */
+ if(boot_image_sys->flags & SF_USE_COPY) {
+ if((s = sys_getaoutheader(&header, i)) != OK) {
+ panic("RS", "unable to get copy of a.out header", s);
+ }
+ boot_image_buffer_size += header.a_hdrlen
+ + header.a_text + header.a_data;
+ }
+ }
+
+ /* Determine the number of entries in the boot image priv table and make sure
+ * it matches the number of system services in the boot image table.
+ */
+ nr_image_priv_srvs = 0;
+ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+ boot_image_priv = &boot_image_priv_table[i];
+
+ /* System services only. */
+ if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+ continue;
+ }
+ nr_image_priv_srvs++;
+ }
+ if(nr_image_srvs != nr_image_priv_srvs) {
+ panic("RS", "boot image table and boot image priv table mismatch",
+ NO_NUM);
+ }
+
+ /* Allocate boot image buffer. */
+ if(boot_image_buffer_size > 0) {
+ boot_image_buffer = rs_startup_sbrk(boot_image_buffer_size);
+ if(boot_image_buffer == (char *) -1) {
+ panic("RS", "unable to allocate boot image buffer", NO_NUM);
+ }
+ }
+
+ /* Initialize the system process table in 3 steps, each of them following
+ * the appearance of system services in the boot image priv table.
+ * - Step 1: get a copy of the executable image of every system service that
+ * requires it while it is not yet running.
+ * In addition, set priviliges, sys properties, and dev properties (if any)
+ * for every system service.
+ */
+ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+ boot_image_priv = &boot_image_priv_table[i];
+
+ /* System services only. */
+ if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+ continue;
+ }
+
+ /* Lookup the corresponding entries in other tables. */
+ boot_image_info_lookup(boot_image_priv->endpoint, image,
+ &ip, NULL, &boot_image_sys, &boot_image_dev);
+ rp = &rproc[boot_image_priv - boot_image_priv_table];
+
+ /*
+ * Get a copy of the executable image if required.
+ */
+ rp->r_exec_len = 0;
+ rp->r_exec = NULL;
+ if(boot_image_sys->flags & SF_USE_COPY) {
+ exec_image_copy(ip - image, ip, rp);
+ }
+
+ /*
+ * Set privileges.
+ * XXX FIXME: We should also let RS set vm calls allowed for each sys
+ * service by using vm_set_priv(). We need a more uniform privilege
+ * management scheme in VM for this change.
+ */
+ /* Force a static privilege id for system services in the boot image. */
+ rp->r_priv.s_id = static_priv_id(_ENDPOINT_P(boot_image_priv->endpoint));
+
+ /* Initialize privilege bitmaps. */
+ rp->r_priv.s_flags = boot_image_priv->flags; /* privilege flags */
+ rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* allowed traps */
+ memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
+ sizeof(rp->r_priv.s_ipc_to)); /* allowed targets */
+
+ /* Initialize call mask bitmap from unordered set. */
+ fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS,
+ rp->r_priv.s_k_call_mask, KERNEL_CALL);
+
+ /* Set the privilege structure. */
+ if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv)))
+ != OK) {
+ panic("RS", "unable to set privilege structure", s);
+ }
+
+ /* Synch the privilege structure with the kernel. */
+ if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) {
+ panic("RS", "unable to synch privilege structure", s);
+ }
+
+ /*
+ * Set sys properties.
+ */
+ rp->r_sys_flags = boot_image_sys->flags; /* sys flags */
+
+ /*
+ * Set dev properties.
+ */
+ rp->r_dev_nr = boot_image_dev->dev_nr; /* major device number */
+ rp->r_dev_style = boot_image_dev->dev_style; /* device style */
+ rp->r_period = boot_image_dev->period; /* heartbeat period */
+ }
+
+ /* - Step 2: allow every system service in the boot image to run.
+ */
+ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+ boot_image_priv = &boot_image_priv_table[i];
+
+ /* System services only. */
+ if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+ continue;
+ }
+
+ /* Lookup the corresponding entry in the boot image table. */
+ boot_image_info_lookup(boot_image_priv->endpoint, image,
+ &ip, NULL, NULL, NULL);
+
+ /* Allow the process to run. */
+ if ((s = sys_privctl(ip->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
+ panic("RS", "unable to initialize privileges", s);
+ }
+ }
+
+ /* - Step 3: all the system services in the boot image are now running. Use
+ * the boot image table from the kernel and PM process table to complete
+ * the initialization of the system process table.
+ */
+ if ((s = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) {
+ panic("RS", "unable to get copy of PM process table", s);
+ }
+ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+ boot_image_priv = &boot_image_priv_table[i];
+
+ /* System services only. */
+ if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+ continue;
+ }
+
+ /* Lookup the corresponding entry in the boot image table. */
+ boot_image_info_lookup(boot_image_priv->endpoint, image,
+ &ip, NULL, NULL, NULL);
+ rp = &rproc[boot_image_priv - boot_image_priv_table];
+
+ /* Get label. */
+ strcpy(rp->r_label, ip->proc_name);
+
+ /* Get command settings. */
+ rp->r_cmd[0]= '\0';
+ rp->r_argv[0] = rp->r_cmd;
+ rp->r_argv[1] = NULL;
+ rp->r_argc = 1;
+ rp->r_script[0]= '\0';
+
+ /* Get settings from the boot image table. */
+ rp->r_nice = ip->priority;
+ rp->r_proc_nr_e = ip->endpoint;
+
+ /* Get pid from PM process table. */
+ rp->r_pid = NO_PID;
+ for (j = 0; j < NR_PROCS; j++) {
+ if (mproc[j].mp_endpoint == rp->r_proc_nr_e) {
+ rp->r_pid = mproc[j].mp_pid;
+ break;
+ }
+ }
+ if(j == NR_PROCS) {
+ panic("RS", "unable to get pid", NO_NUM);
+ }
+
+ /* Set some defaults. */
+ rp->r_uid = 0; /* root */
+ rp->r_check_tm = 0; /* not checked yet */
+ getuptime(&rp->r_alive_tm); /* currently alive */
+ rp->r_stop_tm = 0; /* not exiting yet */
+ rp->r_restarts = 0; /* no restarts so far */
+ rp->r_set_resources = 0; /* no resources */
+
+ /* Mark as in use. */
+ rp->r_flags = RS_IN_USE;
+ rproc_ptr[_ENDPOINT_P(rp->r_proc_nr_e)]= rp;
+
+ /* Publish the new system service. */
+ s = publish_service(rp);
+ if (s != OK) {
+ panic("RS", "unable to publish boot system service", s);
+ }
+ }
+
+ /*
+ * Now complete RS initialization process in collaboration with other
+ * system services.
+ */
+ /* Let the rest of the system know about our dynamically allocated buffer. */
+ if(boot_image_buffer_size > 0) {
+ boot_image_buffer = rs_startup_sbrk_synch(boot_image_buffer_size);
+ if(boot_image_buffer == (char *) -1) {
+ panic("RS", "unable to synch boot image buffer", NO_NUM);
+ }
+ }
+
+ /* Set alarm to periodically check service status. */
+ if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
+ panic("RS", "couldn't set alarm", s);
/* Install signal handlers. Ask PM to transform signal into message. */
sa.sa_handler = SIG_MESS;
if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
- /* Initialize the system process table. Use the boot image from the kernel
- * and the device map from the FS to gather all needed information.
- */
- if ((s = sys_getimage(image)) != OK)
- panic("RS","warning: couldn't get copy of image table", s);
-
- /* Set alarm to periodically check driver status. */
- if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
- panic("RS", "couldn't set alarm", s);
-
- /* See if we run in verbose mode. */
- env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
-
/* Initialize the exec pipe. */
if (pipe(exec_pipe) == -1)
panic("RS", "pipe failed", errno);
{
panic("RS", "fcntl set O_NONBLOCK on pipe input failed", errno);
}
+
+ /* Map out our own text and data. This is normally done in crtso.o
+ * but RS is an exception - we don't get to talk to VM so early on.
+ * That's why we override munmap() and munmap_text() in utility.c.
+ *
+ * _minix_unmapzero() is the same code in crtso.o that normally does
+ * it on startup. It's best that it's there as crtso.o knows exactly
+ * what the ranges are of the filler data.
+ */
+ unmap_ok = 1;
+ _minix_unmapzero();
}
/*===========================================================================*
panic("RS","receive failed", s);
}
-
/*===========================================================================*
* reply *
*===========================================================================*/
printf("RS: unable to send reply to %d: %d\n", who, s);
}
-
-
-
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/vm.h>
-#include <minix/dmap.h>
-#include <minix/ds.h>
-#include <minix/endpoint.h>
#include <minix/vm.h>
#include <lib.h>
-#include <timers.h> /* For priv.h */
-#include "../../kernel/priv.h"
-
-/* Allocate variables. */
-struct rproc rproc[NR_SYS_PROCS]; /* system process table */
-struct rproc *rproc_ptr[NR_PROCS]; /* mapping for fast access */
+#include <minix/sysutil.h>
/* Prototypes for internal functions that do the hard work. */
FORWARD _PROTOTYPE( int caller_is_root, (endpoint_t endpoint) );
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( int set_privs, (endpoint_t endpoint, struct priv *privp,
+ int req) );
FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
PRIVATE int shutting_down = FALSE;
-extern int rs_verbose;
-
/*===========================================================================*
* caller_is_root *
*===========================================================================*/
rp->r_uid= 0;
rp->r_nice= 0;
+ rp->r_sys_flags = DSRV_SF;
rp->r_exec= NULL;
if (do_copy)
s= read_exec(rp);
if (s != OK)
return s;
+
+ rp->r_sys_flags |= SF_USE_COPY;
}
/* Initialize some fields. */
else
rp->r_ipc_list[0]= '\0';
+ rp->r_sys_flags = DSRV_SF;
rp->r_exec= NULL;
if (rs_start.rss_flags & RF_COPY) {
int exst_cpy;
for(i = 0; i < NR_SYS_PROCS; i++) {
rp2 = &rproc[i];
if(strcmp(rp->r_cmd, rp2->r_cmd) == 0 &&
- rp2->r_exec != NULL) {
+ (rp2->r_sys_flags & SF_USE_COPY)) {
/* We have found the same binary that's
* already been copied */
exst_cpy = 1;
if (s != OK)
return s;
+
+ rp->r_sys_flags |= SF_USE_COPY;
}
+ /* All dynamically created services get the same privilege flags, and
+ * allowed traps. Other privilege settings can be specified at runtime.
+ * The privilege id is dynamically allocated by the kernel.
+ */
+ rp->r_priv.s_flags = DSRV_F; /* privilege flags */
+ rp->r_priv.s_trap_mask = DSRV_T; /* allowed traps */
+
/* Copy granted resources */
if (rs_start.rss_nr_irq > NR_IRQ)
{
rp->r_priv.s_io_tab[i].ior_base= rs_start.rss_io[i].base;
rp->r_priv.s_io_tab[i].ior_limit=
rs_start.rss_io[i].base+rs_start.rss_io[i].len-1;
-#if 0
if(rs_verbose)
printf("RS: do_start: I/O [%x..%x]\n",
rp->r_priv.s_io_tab[i].ior_base,
rp->r_priv.s_io_tab[i].ior_limit);
-#endif
}
if (rs_start.rss_nr_pci_id > RSS_NR_PCI_ID)
rp->r_dev_nr = rs_start.rss_major;
rp->r_dev_style = STYLE_DEV;
rp->r_restarts = -1; /* will be incremented */
- rp->r_set_resources= 1; /* new style, enforece
+ rp->r_set_resources= 1; /* new style, enforce
* I/O resources
*/
if (sizeof(rp->r_vm) == sizeof(rs_start.rss_vm) &&
return(r);
}
}
-#if VERBOSE
- printf("RS: do_restart: '%s' not found\n", label);
-#endif
+ if(rs_verbose) {
+ printf("RS: do_restart: '%s' not found\n", label);
+ }
+
return(ESRCH);
}
for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
-#if VERBOSE
- printf("RS: refreshing %s (%d)\n", rp->r_label, rp->r_pid);
-#endif
+ if(rs_verbose) {
+ printf("RS: refreshing %s (%d)\n", rp->r_label, rp->r_pid);
+ }
stop_service(rp,RS_REFRESHING);
return(OK);
}
}
-#if VERBOSE
- printf("RS: do_refresh: '%s' not found\n", label);
-#endif
+ if(rs_verbose) {
+ printf("RS: do_refresh: '%s' not found\n", label);
+ }
+
return(ESRCH);
}
rp->r_cmd, rp->r_backoff);
rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
- if (rp->r_exec != NULL && rp->r_backoff > 1)
+ if ((rp->r_sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
rp->r_backoff= 1;
}
else {
* check and, if so request the system service's status.
*/
else if (now - rp->r_check_tm > rp->r_period) {
+#if 0
if(rs_verbose)
- printf("RS: status request sent to %d\n", rp->r_proc_nr_e);
+ printf("RS: status request sent to %d\n", rp->r_proc_nr_e);
+#endif
notify(rp->r_proc_nr_e); /* request status */
rp->r_check_tm = now; /* mark time */
}
message m;
char * null_env = NULL;
- use_copy= (rp->r_exec != NULL);
-
+ use_copy= (rp->r_sys_flags & SF_USE_COPY);
+
+ /* See if we are not using a copy but we do need one to start the service. */
+ if(!use_copy && (rp->r_sys_flags & SF_NEED_COPY)) {
+ printf("RS: unable to start service %s without an in-memory copy\n",
+ rp->r_label);
+ return(EPERM);
+ }
+
/* Now fork and branch for parent and child process (and check for error). */
if (use_copy) {
if(rs_verbose) printf("RS: fork_nb..\n");
* That will also cause the child process to start running.
* This call should succeed: we tested number in use above.
*/
- if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_INIT, privp)) < 0) {
- report("RS","sys_privctl call failed", s); /* to let child run */
+ if ((s = set_privs(child_proc_nr_e, privp, SYS_PRIV_SET_SYS)) != OK) {
+ report("RS","set_privs failed", s);
kill(child_pid, SIGKILL); /* kill driver */
rp->r_flags |= RS_EXITING; /* expect exit */
return(s); /* return error */
}
- /* The child is now running. Publish its endpoint in DS. */
- s= ds_publish_u32(rp->r_label, child_proc_nr_e);
- if (s != OK)
- printf("RS: start_service: ds_publish_u32 failed: %d\n", s);
- else if(rs_verbose)
- printf("RS: start_service: ds_publish_u32 done: %s -> %d\n",
- rp->r_label, child_proc_nr_e);
-
/* The purpose of non-blocking forks is to avoid involving VFS in the forking
* process, because VFS may be blocked on a sendrec() to a MFS that is
* waiting for a endpoint update for a dead driver. We have just published
if (use_copy)
setuid(0);
+ /* Publish the new system service. */
+ s = publish_service(rp);
+ if (s != OK) {
+ printf("RS: warning: publish_service failed: %d\n", s);
+ }
if (rp->r_dev_nr > 0) { /* set driver map */
if ((s=mapdriver5(rp->r_label, strlen(rp->r_label),
rp->r_dev_nr, rp->r_dev_style, !!use_copy /* force */)) < 0) {
rp->r_script, strerror(errno));
exit(1);
default:
- /* Set the privilege structure for the child process to let it
+ /* Set the privilege structure for the child process and let it
* run.
*/
proc_nr_e = getnprocnr(pid);
- r= sys_privctl(proc_nr_e, SYS_PRIV_USER, NULL);
- if (r < 0)
- printf("RS: run_script: sys_privctl call failed: %d\n", r);
-
+ if ((r= set_privs(proc_nr_e, NULL, SYS_PRIV_SET_USER)) != OK) {
+ printf("RS: run_script: set_privs call failed: %d\n",r);
+ }
/* Do not wait for the child */
break;
}
char label[MAX_LABEL_LEN+1], *p;
struct rproc *tmp_rp;
endpoint_t proc_nr_e;
+ int r;
int slot_nr, priv_id;
+ struct priv priv;
p = rp->r_ipc_list;
proc_nr_e= tmp_rp->r_proc_nr_e;
}
- priv_id= sys_getprivid(proc_nr_e);
- if (priv_id < 0)
+ if ((r = sys_getpriv(&priv, proc_nr_e)) < 0)
{
printf(
"add_forward_ipc: unable to get priv_id for '%s': %d\n",
- label, priv_id);
+ label, r);
continue;
}
+ priv_id= priv.s_id;
set_sys_bit(privp->s_ipc_to, priv_id);
}
}
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;
- }
+ priv_id= rrp->r_priv.s_id;
set_sys_bit(privp->s_ipc_to, priv_id);
}
}
}
+/*===========================================================================*
+ * set_privs *
+ *===========================================================================*/
+PRIVATE int set_privs(endpoint, privp, req)
+endpoint_t endpoint;
+struct priv *privp;
+int req;
+{
+ int r;
+
+ /* Set the privilege structure. */
+ if ((r = sys_privctl(endpoint, req, privp)) != OK) {
+ return r;
+ }
+
+ /* Synch the privilege structure with the kernel for system services. */
+ if(req == SYS_PRIV_SET_SYS) {
+ if ((r = sys_getpriv(privp, endpoint)) != OK) {
+ return r;
+ }
+ }
+
+ /* Allow the process to run. */
+ if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
+ return r;
+ }
+
+ return(OK);
+}
/*===========================================================================*
* init_pci *
--- /dev/null
+/* This file contains memory management routines for RS.
+ *
+ * Changes:
+ * Nov 22, 2009: Created (Cristiano Giuffrida)
+ */
+
+#include "inc.h"
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+EXTERN char *_brksize;
+
+PRIVATE char * _rs_startbrksize = NULL;
+PRIVATE char * _rs_endbrksize = NULL;
+
+#define munmap _munmap
+#define munmap_text _munmap_text
+#include <sys/mman.h>
+#undef munmap
+#undef munmap_text
+
+PUBLIC int unmap_ok = 0;
+
+/*===========================================================================*
+ * check_mem_available *
+ *===========================================================================*/
+PRIVATE int check_mem_available(char *new_brksize)
+{
+/* Check if enough memory is available to grow break size. */
+ register struct mem_map *mem_sp, *mem_dp;
+ vir_clicks sp_click, gap_base, sp_lower;
+ int s;
+ long base_of_stack, sp_delta; /* longs avoid certain problems */
+ vir_bytes sp;
+ struct proc proc;
+ vir_clicks data_clicks;
+
+ /* Get stack pointer and pointers to data/stack segment maps. */
+ if ((s=sys_getproc(&proc, SELF)) != OK) {
+ return(s);
+ }
+ sp = proc.p_reg.sp; /* stack pointer */
+ mem_dp = &proc.p_memmap[D]; /* pointer to data segment map */
+ mem_sp = &proc.p_memmap[S]; /* pointer to stack segment map */
+
+ /* Compute how many clicks the data segment is to become. */
+ data_clicks = (vir_clicks) ( ((long) new_brksize + CLICK_SIZE - 1) >>
+ CLICK_SHIFT) - mem_dp->mem_vir;
+
+ /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
+ base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
+ sp_click = sp >> CLICK_SHIFT; /* click containing sp */
+ if (sp_click >= base_of_stack)
+ {
+ return(ENOMEM); /* sp too high */
+ }
+
+ /* Compute size of gap between stack and data segments. */
+ sp_delta = (long) mem_sp->mem_vir - (long) sp_click;
+ sp_lower = (sp_delta > 0 ? sp_click : mem_sp->mem_vir);
+
+ /* Add a safety margin for future stack growth. Impossible to do right. */
+#define SAFETY_BYTES (384 * sizeof(char *))
+#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
+ gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
+ if (sp_lower < gap_base)
+ {
+ return(ENOMEM); /* data and stack collided */
+ }
+
+ return(OK);
+}
+
+/*===========================================================================*
+ * rs_startup_sbrk *
+ *===========================================================================*/
+PUBLIC void* rs_startup_sbrk(size)
+size_t size; /* the size to grow */
+{
+/* RS's own sbrk() used at startup. */
+ void* addr;
+ char* new_brksize;
+
+ /* Check input for non-positive size or size overflows. */
+ new_brksize = _brksize + size;
+ if (size <= 0 || new_brksize < _brksize) {
+ return( (char *) -1);
+ }
+
+ /* Check if enough memory is available. */
+ if(check_mem_available(new_brksize) != OK) {
+ return( (char *) -1);
+ }
+
+ /* Save initial break size. */
+ if(_rs_startbrksize == NULL) {
+ _rs_startbrksize = _brksize;
+ }
+
+ /* Set address and adjust break size. */
+ addr = _brksize;
+ _brksize = new_brksize;
+ _rs_endbrksize = _brksize;
+
+ return addr;
+}
+
+/*===========================================================================*
+ * rs_startup_sbrk_synch *
+ *===========================================================================*/
+PUBLIC void* rs_startup_sbrk_synch(size)
+size_t size; /* the size to grow */
+{
+/* Synchronize RS's own sbrk() with the rest of the system right after
+ * startup. We use the original sbrk() here.
+ */
+ void* addr;
+
+ /* Restore original break size. */
+ _brksize = _rs_startbrksize;
+
+ /* Call original sbrk() and see if we observe the same effect. */
+ addr = (void*)sbrk(size);
+ if(_rs_startbrksize != addr) {
+ printf("Unable to synch rs_startup_sbrk() and sbrk(): addr 0x%x!=0x%x\n",
+ (int) _rs_startbrksize, (int) addr);
+ return( (char *) -1);
+ }
+ if(_rs_endbrksize != _brksize) {
+ printf("Unable to synch rs_startup_sbrk() and sbrk(): size 0x%x!=0x%x\n",
+ (int) _rs_endbrksize, (int) _brksize);
+ return( (char *) -1);
+ }
+
+ return addr;
+}
+
+/*===========================================================================*
+ * rs_startup_segcopy *
+ *===========================================================================*/
+PUBLIC int rs_startup_segcopy(src_proc, src_seg, dst_seg, dst_vir, bytes)
+endpoint_t src_proc; /* source process */
+int src_seg; /* source memory segment */
+int dst_seg; /* destination memory segment */
+vir_bytes dst_vir; /* destination virtual address */
+phys_bytes bytes; /* how many bytes */
+{
+/* Copy a process's T, D, S segment to RS's address space. Used at startup. */
+ struct proc src_p, dst_p;
+ phys_bytes src_phys, dst_phys;
+ int s;
+
+ /* Check input. */
+ if((src_seg != T && src_seg != D && src_seg != S) || bytes <= 0) {
+ return EINVAL;
+ }
+
+ /* We don't override normal behavior when not copying to our data segment. */
+ if(dst_seg != D) {
+ s = sys_vircopy(src_proc, src_seg, 0, SELF, dst_seg, dst_vir, bytes);
+ return(s);
+ }
+
+ /* Get kernel process slot for both source and destination. */
+ if ((s=sys_getproc(&src_p, src_proc)) != OK) {
+ return(s);
+ }
+ if ((s=sys_getproc(&dst_p, SELF)) != OK) {
+ return(s);
+ }
+
+ /* Map source address to physical address. */
+ src_phys = (phys_bytes) src_p.p_memmap[src_seg].mem_phys << CLICK_SHIFT;
+
+ /* Check if destination address is out of bounds or overflows. */
+ if(dst_vir+bytes > (vir_bytes)_rs_endbrksize
+ || dst_vir < (vir_bytes)_rs_startbrksize || dst_vir+bytes < dst_vir) {
+ return EFAULT;
+ }
+
+ /* Map destination address to physical address. */
+ dst_phys = (phys_bytes) dst_p.p_memmap[D].mem_phys << CLICK_SHIFT;
+ dst_phys += dst_vir - (dst_p.p_memmap[D].mem_vir << CLICK_SHIFT);
+
+ /* Make a physical copy for the requested data. */
+ s = sys_abscopy(src_phys, dst_phys, bytes);
+
+ return(s);
+}
+
+/*===========================================================================*
+ * munmap *
+ *===========================================================================*/
+PUBLIC int munmap(void *addrstart, vir_bytes len)
+{
+ if(!unmap_ok)
+ return ENOSYS;
+
+ return _munmap(addrstart, len);
+}
+
+/*===========================================================================*
+ * munmap_text *
+ *===========================================================================*/
+PUBLIC int munmap_text(void *addrstart, vir_bytes len)
+{
+ if(!unmap_ok)
+ return ENOSYS;
+
+ return _munmap_text(addrstart, len);
+}
+
/* Function prototypes. */
+/* Structs used in prototypes must be declared as such first. */
+struct rproc;
+
/* exec.c */
_PROTOTYPE( int dev_execve, (int proc_e,
char *exec, size_t exec_len, char *argv[], char **env));
_PROTOTYPE( void do_exit, (message *m));
_PROTOTYPE( int do_getsysinfo, (message *m));
+/* utility.c */
+_PROTOTYPE( int publish_service, (struct rproc *rp));
+
+/* memory.c */
+_PROTOTYPE( void* rs_startup_sbrk, (size_t size));
+_PROTOTYPE( void* rs_startup_sbrk_synch, (size_t size));
+_PROTOTYPE( int rs_startup_segcopy, (endpoint_t src_proc, int src_s,
+ int dst_s, vir_bytes dst_vir, phys_bytes bytes));
--- /dev/null
+/* This file contains the definition of the boot image info tables.
+ *
+ * Changes:
+ * Nov 22, 2009: Created (Cristiano Giuffrida)
+ */
+
+#define _TABLE
+
+#include "inc.h"
+
+/* 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.
+ *
+ * Calls are unordered lists, converted by RS to bitmasks
+ * once at runtime.
+ */
+#define FS_KC SYS_KILL, SYS_VIRCOPY, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, \
+ SYS_VIRVCOPY, SYS_UMAP, SYS_GETINFO, SYS_EXIT, SYS_TIMES, SYS_SETALARM, \
+ SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
+#define DRV_KC FS_KC, SYS_SEGCTL, SYS_IRQCTL, SYS_INT86, SYS_DEVIO, \
+ SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
+
+PRIVATE int
+ fs_kc[] = { FS_KC, SYS_NULL_C },
+ pm_kc[] = { SYS_ALL_C, SYS_NULL_C },
+ ds_kc[] = { SYS_ALL_C, SYS_NULL_C },
+ vm_kc[] = { SYS_ALL_C, SYS_NULL_C },
+ drv_kc[] = { DRV_KC, SYS_NULL_C },
+ tty_kc[] = { DRV_KC, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
+ SYS_READBIOS, SYS_NULL_C },
+ mem_kc[] = { DRV_KC, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE, SYS_NULL_C },
+ rusr_kc[] = { SYS_NULL_C },
+
+ no_kc[] = { SYS_NULL_C }; /* no kernel call */
+
+/* Definition of the boot image priv table. */
+PUBLIC struct boot_image_priv boot_image_priv_table[] = {
+ /*endpoint, priv flags, traps, ipcto, kcalls */
+ { VM_PROC_NR, VM_F, SRV_T, SRV_M, vm_kc },
+ { PM_PROC_NR, SRV_F, SRV_T, SRV_M, pm_kc },
+ { FS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_kc },
+ { DS_PROC_NR, SRV_F, SRV_T, SRV_M, ds_kc },
+ { TTY_PROC_NR, SRV_F, SRV_T, SRV_M, tty_kc },
+ { MEM_PROC_NR, SRV_F, SRV_T, SRV_M, mem_kc },
+ { LOG_PROC_NR, SRV_F, SRV_T, SRV_M, drv_kc },
+ { MFS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_kc },
+ { INIT_PROC_NR, RUSR_F, RUSR_T, RUSR_M, rusr_kc },
+ { NULL_BOOT_NR, 0, 0, 0, no_kc } /* null entry */
+};
+
+/* Definition of the boot image sys table. */
+PUBLIC struct boot_image_sys boot_image_sys_table[] = {
+ /*endpoint, sys flags */
+ { LOG_PROC_NR, SRVC_SF },
+ { MFS_PROC_NR, SRVC_SF },
+ { DEFAULT_BOOT_NR, SRV_SF } /* default entry */
+};
+
+/* Definition of the boot image dev table. */
+PUBLIC struct boot_image_dev boot_image_dev_table[] = {
+ /*endpoint, dev_nr, dev_style, period */
+ { TTY_PROC_NR, TTY_MAJOR, STYLE_TTY, 0 },
+ { MEM_PROC_NR, MEMORY_MAJOR, STYLE_DEV, 0 },
+ { LOG_PROC_NR, LOG_MAJOR, STYLE_DEV, 0 },
+ { DEFAULT_BOOT_NR, 0, STYLE_NDEV, 0 } /* default entry */
+};
+
--- /dev/null
+/* Type definitions used in RS.
+ */
+#ifndef RS_TYPE_H
+#define RS_TYPE_H
+
+/* Definition of an entry of the boot image priv table. */
+struct boot_image_priv {
+ endpoint_t endpoint; /* process endpoint number */
+
+ int flags; /* privilege flags */
+ short trap_mask; /* allowed system call traps */
+ int ipc_to; /* send mask protection */
+ int *k_calls; /* kernel call protection */
+};
+
+/* Definition of an entry of the boot image sys table. */
+struct boot_image_sys {
+ endpoint_t endpoint; /* process endpoint number */
+
+ int flags; /* system flags */
+};
+
+/* Definition of an entry of the boot image dev table. */
+struct boot_image_dev {
+ endpoint_t endpoint; /* process endpoint number */
+
+ dev_t dev_nr; /* major device number */
+ int dev_style; /* device style */
+ long period; /* heartbeat period (or zero) */
+};
+
+/* Definition of an entry of the system process table. */
+struct rproc {
+ endpoint_t r_proc_nr_e; /* process endpoint number */
+ pid_t r_pid; /* process id, -1 if the process is not there */
+ dev_t r_dev_nr; /* major device number */
+ int r_dev_style; /* device style */
+
+ int r_restarts; /* number of restarts (initially zero) */
+ long r_backoff; /* number of periods to wait before revive */
+ unsigned r_flags; /* status and policy flags */
+ unsigned r_sys_flags; /* sys flags */
+
+ long r_period; /* heartbeat period (or zero) */
+ clock_t r_check_tm; /* timestamp of last check */
+ clock_t r_alive_tm; /* timestamp of last heartbeat */
+ clock_t r_stop_tm; /* timestamp of SIGTERM signal */
+ endpoint_t r_caller; /* RS_LATEREPLY caller */
+
+ char *r_exec; /* Executable image */
+ size_t r_exec_len; /* Length of image */
+
+ char r_label[MAX_LABEL_LEN]; /* unique name of this driver */
+ char r_cmd[MAX_COMMAND_LEN]; /* raw command plus arguments */
+ char r_script[MAX_SCRIPT_LEN]; /* name of the restart script executable */
+ char *r_argv[MAX_NR_ARGS+2]; /* parsed arguments vector */
+ int r_argc; /* number of arguments */
+
+ /* Resources */
+ int r_set_resources;
+ struct priv r_priv; /* Privilege structure to be passed to the
+ * kernel.
+ */
+ uid_t r_uid;
+ int r_nice;
+ int r_nr_pci_id; /* Number of PCI devices IDs */
+ struct { u16_t vid; u16_t did; } r_pci_id[RSS_NR_PCI_ID];
+ int r_nr_pci_class; /* Number of PCI class IDs */
+ struct { u32_t class; u32_t mask; } r_pci_class[RSS_NR_PCI_CLASS];
+
+ u32_t r_call_mask[RSS_NR_SYSTEM];
+ char r_ipc_list[MAX_IPC_LIST];
+ bitchunk_t r_vm[RSS_VM_CALL_SIZE];
+ int r_nr_control;
+ char r_control[RSS_NR_CONTROL][MAX_LABEL_LEN];
+};
+
+#endif /* RS_TYPE_H */
--- /dev/null
+/* This file contains some utility routines for RS.
+ *
+ * Changes:
+ * Nov 22, 2009: Created (Cristiano Giuffrida)
+ */
+
+#include "inc.h"
+
+#include <minix/ds.h>
+
+/*===========================================================================*
+ * publish_service *
+ *===========================================================================*/
+PUBLIC int publish_service(rp)
+struct rproc *rp; /* pointer to process slot */
+{
+/* A new system service has been started. Publish the necessary information. */
+ int s;
+
+ /* Register its label with DS. */
+ s= ds_publish_u32(rp->r_label, rp->r_proc_nr_e);
+ if (s != OK) {
+ return s;
+ }
+ if (rs_verbose) {
+ printf("RS: publish_service: DS label registration done: %s -> %d\n",
+ rp->r_label, rp->r_proc_nr_e);
+ }
+
+ return(OK);
+}
+