panic() cleanup.
[minix.git] / servers / rs / manager.c
blob01a4f256c5ce0cadff8e6dc1b120ea0c661f8ca7
1 /*
2 * Changes:
3 * Nov 22, 2009: added basic live update support (Cristiano Giuffrida)
4 * Mar 02, 2009: Extended isolation policies (Jorrit N. Herder)
5 * Jul 22, 2005: Created (Jorrit N. Herder)
6 */
8 #include "inc.h"
9 #include <ctype.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/wait.h>
15 #include <sys/vm.h>
16 #include <minix/vm.h>
17 #include <lib.h>
19 #include <minix/sysutil.h>
21 /* Prototypes for internal functions that do the hard work. */
22 FORWARD _PROTOTYPE( int caller_is_root, (endpoint_t endpoint) );
23 FORWARD _PROTOTYPE( int caller_can_control, (endpoint_t endpoint,
24 char *label) );
25 FORWARD _PROTOTYPE( int copy_label, (endpoint_t src_e,
26 struct rss_label *src_label, char *dst_label, size_t dst_len) );
27 FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags,
28 endpoint_t *ep) );
29 FORWARD _PROTOTYPE( void stop_service, (struct rproc *rp,int how) );
30 FORWARD _PROTOTYPE( int fork_nb, (void) );
31 FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
32 FORWARD _PROTOTYPE( int share_exec, (struct rproc *rp_src,
33 struct rproc *rp_dst) );
34 FORWARD _PROTOTYPE( void free_slot, (struct rproc *rp) );
35 FORWARD _PROTOTYPE( void run_script, (struct rproc *rp) );
36 FORWARD _PROTOTYPE( char *get_next_label, (char *ptr, char *label,
37 char *caller_label) );
38 FORWARD _PROTOTYPE( void add_forward_ipc, (struct rproc *rp,
39 struct priv *privp) );
40 FORWARD _PROTOTYPE( void add_backward_ipc, (struct rproc *rp,
41 struct priv *privp) );
42 FORWARD _PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
43 FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
44 FORWARD _PROTOTYPE( void update_period, (message *m_ptr) );
45 FORWARD _PROTOTYPE( void end_update, (clock_t now) );
47 PRIVATE int shutting_down = FALSE;
49 /*===========================================================================*
50 * caller_is_root *
51 *===========================================================================*/
52 PRIVATE int caller_is_root(endpoint)
53 endpoint_t endpoint; /* caller endpoint */
55 uid_t euid;
57 /* Check if caller has root user ID. */
58 euid = getnuid(endpoint);
59 if (rs_verbose && euid != 0)
61 printf("RS: got unauthorized request from endpoint %d\n", endpoint);
64 return euid == 0;
67 /*===========================================================================*
68 * caller_can_control *
69 *===========================================================================*/
70 PRIVATE int caller_can_control(endpoint, label)
71 endpoint_t endpoint;
72 char *label;
74 int control_allowed = 0;
75 register struct rproc *rp;
76 register struct rprocpub *rpub;
77 int c;
78 char *progname;
80 /* Find name of binary for given label. */
81 for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) {
82 rpub = rp->r_pub;
83 if (strcmp(rpub->label, label) == 0) {
84 break;
87 if (rp == END_RPROC_ADDR) return 0;
88 progname = strrchr(rp->r_argv[0], '/');
89 if (progname != NULL)
90 progname++;
91 else
92 progname = rp->r_argv[0];
94 /* Check if label is listed in caller's isolation policy. */
95 for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) {
96 rpub = rp->r_pub;
97 if (rpub->endpoint == endpoint) {
98 break;
101 if (rp == END_RPROC_ADDR) return 0;
102 if (rp->r_nr_control > 0) {
103 for (c = 0; c < rp->r_nr_control; c++) {
104 if (strcmp(rp->r_control[c], progname) == 0)
105 control_allowed = 1;
109 if (rs_verbose) {
110 printf("RS: allowing %u control over %s via policy: %s\n",
111 endpoint, label, control_allowed ? "yes" : "no");
113 return control_allowed;
116 /*===========================================================================*
117 * copy_label *
118 *===========================================================================*/
119 PRIVATE int copy_label(src_e, src_label, dst_label, dst_len)
120 endpoint_t src_e;
121 struct rss_label *src_label;
122 char *dst_label;
123 size_t dst_len;
125 int s, len;
127 len = MIN(dst_len-1, src_label->l_len);
129 s = sys_datacopy(src_e, (vir_bytes) src_label->l_addr,
130 SELF, (vir_bytes) dst_label, len);
131 if (s != OK) return s;
133 dst_label[len] = 0;
135 return OK;
138 /*===========================================================================*
139 * do_up *
140 *===========================================================================*/
141 PUBLIC int do_up(m_ptr)
142 message *m_ptr; /* request message pointer */
144 /* A request was made to start a new system service.
146 register struct rproc *rp; /* system process table */
147 register struct rprocpub *rpub; /* public entry */
148 int slot_nr; /* local table entry */
149 int arg_count; /* number of arguments */
150 char *cmd_ptr; /* parse command string */
151 char *label; /* unique name of command */
152 enum dev_style dev_style; /* device style */
153 int s; /* status variable */
154 int len; /* length of string */
155 int i;
156 int r;
157 endpoint_t ep;
158 struct rproc *tmp_rp;
159 struct rprocpub *tmp_rpub;
160 struct rs_start rs_start;
162 /* This call requires special privileges. */
163 if (!caller_is_root(m_ptr->m_source)) return(EPERM);
165 /* See if there is a free entry in the table with system processes. */
166 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
167 rp = &rproc[slot_nr]; /* get pointer to slot */
168 if (!(rp->r_flags & RS_IN_USE)) /* check if available */
169 break;
171 if (slot_nr >= NR_SYS_PROCS)
173 printf("RS: do_up: system process table full\n");
174 return ENOMEM;
176 rpub = rp->r_pub;
178 /* Ok, there is space. Get the request structure. */
179 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
180 SELF, (vir_bytes) &rs_start, sizeof(rs_start));
181 if (s != OK) return(s);
183 /* Obtain command name and parameters. This is a space-separated string
184 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
186 if (rs_start.rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
187 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_cmd,
188 SELF, (vir_bytes) rp->r_cmd, rs_start.rss_cmdlen);
189 if (s != OK) return(s);
190 rp->r_cmd[rs_start.rss_cmdlen] = '\0'; /* ensure it is terminated */
191 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
193 /* Build argument vector to be passed to execute call. The format of the
194 * arguments vector is: path, arguments, NULL.
196 arg_count = 0; /* initialize arg count */
197 rp->r_argv[arg_count++] = rp->r_cmd; /* start with path */
198 cmd_ptr = rp->r_cmd; /* do some parsing */
199 while(*cmd_ptr != '\0') { /* stop at end of string */
200 if (*cmd_ptr == ' ') { /* next argument */
201 *cmd_ptr = '\0'; /* terminate previous */
202 while (*++cmd_ptr == ' ') ; /* skip spaces */
203 if (*cmd_ptr == '\0') break; /* no arg following */
204 if (arg_count>MAX_NR_ARGS+1) break; /* arg vector full */
205 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
207 cmd_ptr ++; /* continue parsing */
209 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
210 rp->r_argc = arg_count;
212 /* Process name for the service. */
213 cmd_ptr = strrchr(rp->r_argv[0], '/');
214 if (cmd_ptr)
215 cmd_ptr++;
216 else
217 cmd_ptr= rp->r_argv[0];
218 len= strlen(cmd_ptr);
219 if (len > RS_MAX_LABEL_LEN-1)
220 len= RS_MAX_LABEL_LEN-1; /* truncate name */
221 memcpy(rpub->proc_name, cmd_ptr, len);
222 rpub->proc_name[len]= '\0';
223 if(rs_verbose)
224 printf("RS: do_up: using proc_name (from binary %s) '%s'\n",
225 rp->r_argv[0], rpub->proc_name);
227 if(rs_start.rss_label.l_len > 0) {
228 /* RS_UP caller has supplied a custom label for this service. */
229 int s = copy_label(m_ptr->m_source, &rs_start.rss_label,
230 rpub->label, sizeof(rpub->label));
231 if(s != OK)
232 return s;
233 if(rs_verbose)
234 printf("RS: do_up: using label (custom) '%s'\n", rpub->label);
235 } else {
236 /* Default label for the service. */
237 label = rpub->proc_name;
238 len= strlen(label);
239 memcpy(rpub->label, label, len);
240 rpub->label[len]= '\0';
241 if(rs_verbose)
242 printf("RS: do_up: using label (from proc_name) '%s'\n",
243 rpub->label);
246 if(rs_start.rss_nr_control > 0) {
247 int i, s;
248 if (rs_start.rss_nr_control > RS_NR_CONTROL)
250 printf("RS: do_up: too many control labels\n");
251 return EINVAL;
253 for (i=0; i<rs_start.rss_nr_control; i++) {
254 s = copy_label(m_ptr->m_source, &rs_start.rss_control[i],
255 rp->r_control[i], sizeof(rp->r_control[i]));
256 if(s != OK)
257 return s;
259 rp->r_nr_control = rs_start.rss_nr_control;
261 if (rs_verbose) {
262 printf("RS: do_up: control labels:");
263 for (i=0; i<rp->r_nr_control; i++)
264 printf(" %s", rp->r_control[i]);
265 printf("\n");
269 /* Check for duplicates */
270 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
271 tmp_rp = &rproc[slot_nr]; /* get pointer to slot */
272 if (!(tmp_rp->r_flags & RS_IN_USE)) /* check if available */
273 continue;
274 if (tmp_rp == rp)
275 continue; /* Our slot */
276 tmp_rpub = tmp_rp->r_pub;
277 if (strcmp(tmp_rpub->label, rpub->label) == 0)
279 printf("RS: found duplicate label '%s': slot %d\n",
280 rpub->label, slot_nr);
281 return EBUSY;
285 rp->r_script[0]= '\0';
286 if (rs_start.rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
287 if (rs_start.rss_script != NULL)
289 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_script,
290 SELF, (vir_bytes) rp->r_script, rs_start.rss_scriptlen);
291 if (s != OK) return(s);
292 rp->r_script[rs_start.rss_scriptlen] = '\0';
294 rp->r_uid= rs_start.rss_uid;
295 rp->r_nice= rs_start.rss_nice;
297 if (rs_start.rss_flags & RSS_IPC_VALID)
299 if (rs_start.rss_ipclen+1 > sizeof(rp->r_ipc_list))
301 printf("rs: ipc list too long for '%s'\n", rpub->label);
302 return EINVAL;
304 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_ipc,
305 SELF, (vir_bytes) rp->r_ipc_list, rs_start.rss_ipclen);
306 if (s != OK) return(s);
307 rp->r_ipc_list[rs_start.rss_ipclen]= '\0';
309 else
310 rp->r_ipc_list[0]= '\0';
312 rpub->sys_flags = DSRV_SF;
313 rp->r_exec= NULL;
314 if (rs_start.rss_flags & RSS_COPY) {
315 int exst_cpy;
316 struct rproc *rp2;
317 struct rprocpub *rpub2;
318 exst_cpy = 0;
320 if(rs_start.rss_flags & RSS_REUSE) {
321 int i;
323 for(i = 0; i < NR_SYS_PROCS; i++) {
324 rp2 = &rproc[i];
325 rpub2 = rproc[i].r_pub;
326 if(strcmp(rpub->proc_name, rpub2->proc_name) == 0 &&
327 (rpub2->sys_flags & SF_USE_COPY)) {
328 /* We have found the same binary that's
329 * already been copied */
330 exst_cpy = 1;
331 break;
336 if(!exst_cpy)
337 s = read_exec(rp);
338 else
339 s = share_exec(rp, rp2);
341 if (s != OK)
342 return s;
344 rpub->sys_flags |= SF_USE_COPY;
347 /* All dynamically created services get the same privilege flags, and
348 * allowed traps. Other privilege settings can be specified at runtime.
349 * The privilege id is dynamically allocated by the kernel.
351 rp->r_priv.s_flags = DSRV_F; /* privilege flags */
352 rp->r_priv.s_trap_mask = DSRV_T; /* allowed traps */
354 /* Copy granted resources */
355 if (rs_start.rss_nr_irq > NR_IRQ)
357 printf("RS: do_up: too many IRQs requested\n");
358 return EINVAL;
360 rp->r_priv.s_nr_irq= rs_start.rss_nr_irq;
361 for (i= 0; i<rp->r_priv.s_nr_irq; i++)
363 rp->r_priv.s_irq_tab[i]= rs_start.rss_irq[i];
364 if(rs_verbose)
365 printf("RS: do_up: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
368 if (rs_start.rss_nr_io > NR_IO_RANGE)
370 printf("RS: do_up: too many I/O ranges requested\n");
371 return EINVAL;
373 rp->r_priv.s_nr_io_range= rs_start.rss_nr_io;
374 for (i= 0; i<rp->r_priv.s_nr_io_range; i++)
376 rp->r_priv.s_io_tab[i].ior_base= rs_start.rss_io[i].base;
377 rp->r_priv.s_io_tab[i].ior_limit=
378 rs_start.rss_io[i].base+rs_start.rss_io[i].len-1;
379 if(rs_verbose)
380 printf("RS: do_up: I/O [%x..%x]\n",
381 rp->r_priv.s_io_tab[i].ior_base,
382 rp->r_priv.s_io_tab[i].ior_limit);
385 if (rs_start.rss_nr_pci_id > RS_NR_PCI_DEVICE)
387 printf("RS: do_up: too many PCI device IDs\n");
388 return EINVAL;
390 rpub->pci_acl.rsp_nr_device = rs_start.rss_nr_pci_id;
391 for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++)
393 rpub->pci_acl.rsp_device[i].vid= rs_start.rss_pci_id[i].vid;
394 rpub->pci_acl.rsp_device[i].did= rs_start.rss_pci_id[i].did;
395 if(rs_verbose)
396 printf("RS: do_up: PCI %04x/%04x\n",
397 rpub->pci_acl.rsp_device[i].vid,
398 rpub->pci_acl.rsp_device[i].did);
400 if (rs_start.rss_nr_pci_class > RS_NR_PCI_CLASS)
402 printf("RS: do_up: too many PCI class IDs\n");
403 return EINVAL;
405 rpub->pci_acl.rsp_nr_class= rs_start.rss_nr_pci_class;
406 for (i= 0; i<rpub->pci_acl.rsp_nr_class; i++)
408 rpub->pci_acl.rsp_class[i].class= rs_start.rss_pci_class[i].class;
409 rpub->pci_acl.rsp_class[i].mask= rs_start.rss_pci_class[i].mask;
410 if(rs_verbose)
411 printf("RS: do_up: PCI class %06x mask %06x\n",
412 rpub->pci_acl.rsp_class[i].class,
413 rpub->pci_acl.rsp_class[i].mask);
416 /* Copy 'system' call number bits */
417 if (sizeof(rs_start.rss_system[0]) == sizeof(rp->r_call_mask[0]) &&
418 sizeof(rs_start.rss_system) == sizeof(rp->r_call_mask))
420 for (i= 0; i<RS_SYS_CALL_MASK_SIZE; i++)
421 rp->r_call_mask[i]= rs_start.rss_system[i];
423 else
425 printf(
426 "RS: do_up: internal inconsistency: bad size of r_call_mask\n");
427 memset(rp->r_call_mask, '\0', sizeof(rp->r_call_mask));
430 /* Initialize some fields. */
431 rpub->period = rs_start.rss_period;
432 rpub->dev_nr = rs_start.rss_major;
433 rpub->dev_style = STYLE_DEV;
434 rp->r_restarts = -1; /* will be incremented */
435 rp->r_set_resources= 1; /* set resources */
437 if (sizeof(rpub->vm_call_mask) == sizeof(rs_start.rss_vm) &&
438 sizeof(rpub->vm_call_mask[0]) == sizeof(rs_start.rss_vm[0]))
440 int basic_vmc[] = { VM_BASIC_CALLS, SYS_NULL_C };
441 memcpy(rpub->vm_call_mask, rs_start.rss_vm,
442 sizeof(rpub->vm_call_mask));
443 fill_call_mask(basic_vmc, NR_VM_CALLS,
444 rpub->vm_call_mask, VM_RQ_BASE, FALSE);
446 else
448 printf("RS: internal inconsistency: bad size of vm_call_mask\n");
449 memset(rpub->vm_call_mask, '\0', sizeof(rpub->vm_call_mask));
452 /* All information was gathered. Now try to start the system service. */
453 r = start_service(rp, 0, &ep);
454 m_ptr->RS_ENDPOINT = ep;
455 return r;
459 /*===========================================================================*
460 * do_down *
461 *===========================================================================*/
462 PUBLIC int do_down(message *m_ptr)
464 register struct rproc *rp;
465 register struct rprocpub *rpub;
466 size_t len;
467 int s, proc;
468 char label[RS_MAX_LABEL_LEN];
470 /* This call requires special privileges. */
471 if (!caller_is_root(m_ptr->m_source)) return(EPERM);
473 len= m_ptr->RS_CMD_LEN;
474 if (len >= sizeof(label))
475 return EINVAL; /* Too long */
477 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
478 SELF, (vir_bytes) label, len);
479 if (s != OK) return(s);
480 label[len]= '\0';
482 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
483 rpub = rp->r_pub;
484 if (rp->r_flags & RS_IN_USE && strcmp(rpub->label, label) == 0) {
485 /* Core system services should never go down. */
486 if (rpub->sys_flags & SF_CORE_SRV) return(EPERM);
488 if(rs_verbose)
489 printf("RS: stopping '%s' (%d)\n", label, rp->r_pid);
490 stop_service(rp,RS_EXITING);
491 if (rp->r_pid == -1)
493 /* Process is already gone, release slot. */
494 free_slot(rp);
495 return(OK);
498 /* Late reply - send a reply when process dies. */
499 rp->r_flags |= RS_LATEREPLY;
500 rp->r_caller = m_ptr->m_source;
501 return EDONTREPLY;
504 if(rs_verbose) printf("RS: do_down: '%s' not found\n", label);
505 return(ESRCH);
509 /*===========================================================================*
510 * do_restart *
511 *===========================================================================*/
512 PUBLIC int do_restart(message *m_ptr)
514 register struct rproc *rp;
515 register struct rprocpub *rpub;
516 size_t len;
517 int s, proc, r;
518 char label[RS_MAX_LABEL_LEN];
519 endpoint_t ep;
521 len= m_ptr->RS_CMD_LEN;
522 if (len >= sizeof(label))
523 return EINVAL; /* Too long */
525 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
526 SELF, (vir_bytes) label, len);
527 if (s != OK) return(s);
528 label[len]= '\0';
530 /* This call requires special privileges. */
531 if (! (caller_can_control(m_ptr->m_source, label) ||
532 caller_is_root(m_ptr->m_source))) {
533 return(EPERM);
536 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
537 rpub = rp->r_pub;
538 if ((rp->r_flags & RS_IN_USE) && strcmp(rpub->label, label) == 0) {
539 if(rs_verbose) printf("RS: restarting '%s' (%d)\n", label, rp->r_pid);
540 if (rp->r_pid >= 0)
542 if(rs_verbose)
543 printf("RS: do_restart: '%s' is (still) running, pid = %d\n",
544 rp->r_pid);
545 return EBUSY;
547 rp->r_flags &= ~(RS_REFRESHING|RS_NOPINGREPLY);
548 r = start_service(rp, 0, &ep);
549 if (r != OK) printf("do_restart: start_service failed: %d\n", r);
550 m_ptr->RS_ENDPOINT = ep;
551 return(r);
554 if(rs_verbose) {
555 printf("RS: do_restart: '%s' not found\n", label);
558 return(ESRCH);
562 /*===========================================================================*
563 * do_refresh *
564 *===========================================================================*/
565 PUBLIC int do_refresh(message *m_ptr)
567 register struct rproc *rp;
568 register struct rprocpub *rpub;
569 size_t len;
570 int s;
571 char label[RS_MAX_LABEL_LEN];
573 len= m_ptr->RS_CMD_LEN;
574 if (len >= sizeof(label))
575 return EINVAL; /* Too long */
577 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
578 SELF, (vir_bytes) label, len);
579 if (s != OK) return(s);
580 label[len]= '\0';
582 /* This call requires special privileges. */
583 if (! (caller_can_control(m_ptr->m_source, label) ||
584 caller_is_root(m_ptr->m_source))) {
585 return(EPERM);
588 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
589 rpub = rp->r_pub;
590 if (rp->r_flags & RS_IN_USE && strcmp(rpub->label, label) == 0) {
591 /* Only system processes not including RS can refresh. */
592 if(!(rp->r_priv.s_flags & SYS_PROC) || rpub->endpoint == RS_PROC_NR) {
593 return EPERM;
596 if(rs_verbose) {
597 printf("RS: refreshing %s (%d)\n", rpub->label, rp->r_pid);
599 stop_service(rp,RS_REFRESHING);
600 return(OK);
603 if(rs_verbose) {
604 printf("RS: do_refresh: '%s' not found\n", label);
607 return(ESRCH);
610 /*===========================================================================*
611 * do_shutdown *
612 *===========================================================================*/
613 PUBLIC int do_shutdown(message *m_ptr)
615 /* This call requires special privileges. */
616 if (m_ptr != NULL && !caller_is_root(m_ptr->m_source)) return(EPERM);
618 /* Set flag so that RS server knows services shouldn't be restarted. */
619 shutting_down = TRUE;
620 return(OK);
624 /*===========================================================================*
625 * do_init_ready *
626 *===========================================================================*/
627 PUBLIC int do_init_ready(message *m_ptr)
629 int who_p;
630 struct rproc *rp;
631 struct rprocpub *rpub;
632 int result;
634 who_p = _ENDPOINT_P(m_ptr->m_source);
635 rp = rproc_ptr[who_p];
636 rpub = rp->r_pub;
637 result = m_ptr->RS_INIT_RESULT;
639 /* Make sure the originating service was requested to initialize. */
640 if(! (rp->r_flags & RS_INITIALIZING) ) {
641 if(rs_verbose) {
642 printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
643 m_ptr->m_source);
645 return(EINVAL);
648 /* Mark the slot as no longer initializing. */
649 rp->r_flags &= ~RS_INITIALIZING;
650 rp->r_check_tm = 0;
651 getuptime(&rp->r_alive_tm);
653 /* Check if something went wrong and the service failed to init.
654 * In that case, kill it and make sure it won't be restarted.
656 if(result != OK) {
657 if(rs_verbose)
658 printf("RS: initialization failed for service %d: %d\n",
659 rpub->endpoint, result);
660 rp->r_flags |= RS_EXITING;
661 kill(rp->r_pid, SIGKILL);
663 else {
664 if(rs_verbose)
665 printf("RS: initialization succeeded for service %d\n",
666 rpub->endpoint);
669 return(EDONTREPLY);
672 /*===========================================================================*
673 * do_update *
674 *===========================================================================*/
675 PUBLIC int do_update(message *m_ptr)
677 register struct rproc *rp;
678 register struct rprocpub *rpub;
679 size_t len;
680 int s;
681 char label[RS_MAX_LABEL_LEN];
682 int lu_state;
683 int prepare_maxtime;
685 /* Retrieve label. */
686 len= m_ptr->RS_CMD_LEN;
687 if (len >= sizeof(label))
688 return EINVAL; /* Too long */
689 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
690 SELF, (vir_bytes) label, len);
691 if (s != OK) return(s);
692 label[len]= '\0';
694 /* This call requires special privileges. */
695 if (! (caller_can_control(m_ptr->m_source, label) ||
696 caller_is_root(m_ptr->m_source))) {
697 return(EPERM);
700 /* Retrieve live update state. */
701 lu_state = m_ptr->RS_LU_STATE;
702 if(lu_state == SEF_LU_STATE_NULL) {
703 return(EINVAL);
706 /* Retrieve prepare max time. */
707 prepare_maxtime = m_ptr->RS_LU_PREPARE_MAXTIME;
708 if(prepare_maxtime) {
709 if(prepare_maxtime < 0 || prepare_maxtime > RS_MAX_PREPARE_MAXTIME) {
710 return(EINVAL);
713 else {
714 prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME;
717 /* Make sure we are not already updating. */
718 if(rupdate.flags & RS_UPDATING) {
719 if(rs_verbose) {
720 printf("RS: do_update: an update is already in progress");
722 return(EBUSY);
725 /* Try to start the update process. */
726 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
727 rpub = rp->r_pub;
728 if (rp->r_flags & RS_IN_USE && strcmp(rpub->label, label) == 0) {
729 /* Only system processes not including RS can update. */
730 if(!(rp->r_priv.s_flags & SYS_PROC) || rpub->endpoint == RS_PROC_NR) {
731 return EPERM;
734 if(rs_verbose) {
735 printf("RS: updating %s (%d)\n", rpub->label, rp->r_pid);
738 rp->r_flags |= RS_UPDATING;
739 rupdate.flags |= RS_UPDATING;
740 getuptime(&rupdate.prepare_tm);
741 rupdate.prepare_maxtime = prepare_maxtime;
742 rupdate.rp = rp;
744 m_ptr->m_type = RS_LU_PREPARE;
745 asynsend(rpub->endpoint, m_ptr); /* request to update */
747 return(OK);
750 if(rs_verbose) {
751 printf("RS: do_update: '%s' not found\n", label);
754 return(ESRCH);
757 /*===========================================================================*
758 * do_upd_ready *
759 *===========================================================================*/
760 PUBLIC int do_upd_ready(message *m_ptr)
762 register struct rproc *rp;
763 int who_p;
764 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
765 int result;
767 who_p = _ENDPOINT_P(m_ptr->m_source);
768 rp = rproc_ptr[who_p];
769 result = m_ptr->RS_LU_RESULT;
771 /* Make sure the originating service was requested to prepare for update. */
772 if(! (rp->r_flags & RS_UPDATING) ) {
773 if(rs_verbose) {
774 printf("RS: do_upd_ready: got unexpected update ready msg from %d\n",
775 m_ptr->m_source);
777 return(EINVAL);
780 /* Check if something went wrong and the service failed to prepare
781 * for the update. In that case, end the update process.
783 if(result != OK) {
784 end_update(now);
785 switch(result) {
786 case EACCES:
787 printf("RS: update failed: %s\n",
788 "service does not support live update");
789 break;
791 case EINVAL:
792 printf("RS: update failed: %s\n",
793 "service does not support the required state");
794 break;
796 case EBUSY:
797 printf("RS: update failed: %s\n",
798 "service is not able to prepare for the update now");
799 break;
801 case EGENERIC:
802 printf("RS: update failed: %s\n",
803 "a generic error occurred while preparing for the update");
804 break;
806 default:
807 printf("RS: update failed: %s (%d)\n",
808 "an unknown error occurred while preparing for the update\n",
809 result);
810 break;
813 return(OK);
816 /* Kill the process now and mark it for refresh, the new version will
817 * be automatically restarted.
819 rp->r_flags &= ~RS_EXITING;
820 rp->r_flags |= RS_REFRESHING;
821 kill(rp->r_pid, SIGKILL);
823 return(EDONTREPLY);
826 /*===========================================================================*
827 * update_period *
828 *===========================================================================*/
829 PRIVATE void update_period(message *m_ptr)
831 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
832 short has_update_timed_out;
833 message m;
834 struct rprocpub *rpub;
836 rpub = rupdate.rp->r_pub;
838 /* See if a timeout has occurred. */
839 has_update_timed_out = (now - rupdate.prepare_tm > rupdate.prepare_maxtime);
841 /* If an update timed out, end the update process and notify the service. */
842 if(has_update_timed_out) {
843 end_update(now);
844 printf("RS: update failed: maximum prepare time reached\n");
846 /* Prepare cancel request. */
847 m.m_type = RS_LU_PREPARE;
848 m.RS_LU_STATE = SEF_LU_STATE_NULL;
849 asynsend(rpub->endpoint, &m);
853 /*===========================================================================*
854 * end_update *
855 *===========================================================================*/
856 PRIVATE void end_update(clock_t now)
858 /* End the update process and mark the affected service as no longer under
859 * update. Eventual late ready to update message (if any) will simply be
860 * ignored and the service can continue executing.
861 * We reset the check timestamp, so that if the service has a period a status
862 * request will be forced in the next period.
864 rupdate.flags &= ~RS_UPDATING;
865 rupdate.rp->r_flags &= ~RS_UPDATING;
866 rupdate.rp->r_check_tm = 0;
869 /*===========================================================================*
870 * do_exit *
871 *===========================================================================*/
872 PUBLIC void do_exit(message *m_ptr)
874 register struct rproc *rp;
875 register struct rprocpub *rpub;
876 pid_t exit_pid;
877 int exit_status, r, slot_nr;
878 endpoint_t ep;
879 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
881 if(rs_verbose)
882 printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");
884 /* See which child exited and what the exit status is. This is done in a
885 * loop because multiple children may have exited, all reported by one
886 * SIGCHLD signal. The WNOHANG options is used to prevent blocking if,
887 * somehow, no exited child can be found.
889 while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
891 if(rs_verbose) {
892 #if 0
893 printf("RS: pid %d, ", exit_pid);
894 #endif
895 if (WIFSIGNALED(exit_status)) {
896 #if 0
897 printf("killed, signal number %d\n", WTERMSIG(exit_status));
898 #endif
900 else if (WIFEXITED(exit_status)) {
901 #if 0
902 printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
903 #endif
907 /* Read from the exec pipe */
908 for (;;)
910 r= read(exec_pipe[0], &slot_nr, sizeof(slot_nr));
911 if (r == -1)
913 break; /* No data */
915 if (r != sizeof(slot_nr))
917 panic("do_exit: unaligned read from exec pipe: %d", r);
919 printf("do_exit: got slot %d\n", slot_nr);
920 if (slot_nr < 0 || slot_nr >= NR_SYS_PROCS)
922 panic("do_exit: bad slot number from exec pipe: %d", slot_nr);
924 rp= &rproc[slot_nr];
925 rp->r_flags |= RS_EXITING;
928 /* Search the system process table to see who exited.
929 * This should always succeed.
931 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
932 rpub = rp->r_pub;
933 if ((rp->r_flags & RS_IN_USE) && rp->r_pid == exit_pid) {
934 int proc;
935 proc = _ENDPOINT_P(rpub->endpoint);
937 rproc_ptr[proc] = NULL; /* invalidate */
938 rp->r_pid= -1;
940 /* If PCI properties are set, inform the PCI driver. */
941 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
942 pci_del_acl(rpub->endpoint);
945 if ((rp->r_flags & RS_EXITING) || shutting_down) {
946 /* No reply sent to RS_DOWN yet. */
947 if(rp->r_flags & RS_LATEREPLY) {
948 message rsm;
949 rsm.m_type = OK;
950 send(rp->r_caller, &rsm);
953 /* Release slot. */
954 free_slot(rp);
956 else if(rp->r_flags & RS_REFRESHING) {
957 short is_updating = rp->r_flags & RS_UPDATING;
959 /* Refresh */
960 if (rp->r_script[0] != '\0')
961 run_script(rp);
962 else {
963 start_service(rp, 0, &ep); /* direct restart */
964 if(m_ptr)
965 m_ptr->RS_ENDPOINT = ep;
968 /* If updating, end the update process. */
969 if(is_updating) {
970 end_update(now);
971 printf("RS: update succeeded\n");
974 else {
975 /* Determine what to do. If this is the first unexpected
976 * exit, immediately restart this service. Otherwise use
977 * a binary exponential backoff.
979 #if 0
980 rp->r_restarts= 0;
981 #endif
982 if (WIFSIGNALED(exit_status)) {
983 switch(WTERMSIG(exit_status))
985 case SIGKILL: rp->r_flags |= RS_KILLED; break;
986 default: rp->r_flags |= RS_SIGNALED; break;
989 else
990 rp->r_flags |= RS_CRASHED;
992 if (rp->r_script[0] != '\0') {
993 if(rs_verbose)
994 printf("RS: running restart script for %s\n",
995 rp->r_cmd);
996 run_script(rp);
997 } else if (rp->r_restarts > 0) {
998 printf("RS: restarting %s, restarts %d\n",
999 rp->r_cmd, rp->r_backoff);
1000 rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
1001 rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
1002 if ((rpub->sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
1003 rp->r_backoff= 1;
1005 else {
1006 printf("RS: restarting %s\n", rp->r_cmd);
1007 start_service(rp, 0, &ep); /* direct restart */
1008 if(m_ptr)
1009 m_ptr->RS_ENDPOINT = ep;
1010 /* Do this even if no I/O happens with the ioctl, in
1011 * order to disambiguate requests with DEV_IOCTL_S.
1015 break;
1021 /*===========================================================================*
1022 * do_period *
1023 *===========================================================================*/
1024 PUBLIC void do_period(m_ptr)
1025 message *m_ptr;
1027 register struct rproc *rp;
1028 register struct rprocpub *rpub;
1029 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
1030 int s;
1031 endpoint_t ep;
1032 long period;
1034 /* If an update is in progress, check its status. */
1035 if(rupdate.flags & RS_UPDATING) {
1036 update_period(m_ptr);
1039 /* Search system services table. Only check slots that are in use and not
1040 * updating.
1042 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
1043 rpub = rp->r_pub;
1044 if ((rp->r_flags & RS_IN_USE) && !(rp->r_flags & RS_UPDATING)) {
1046 /* Compute period. */
1047 period = rpub->period;
1048 if(rp->r_flags & RS_INITIALIZING) {
1049 period = RS_INIT_T;
1052 /* If the service is to be revived (because it repeatedly exited,
1053 * and was not directly restarted), the binary backoff field is
1054 * greater than zero.
1056 if (rp->r_backoff > 0) {
1057 rp->r_backoff -= 1;
1058 if (rp->r_backoff == 0) {
1059 start_service(rp, 0, &ep);
1060 m_ptr->RS_ENDPOINT = ep;
1064 /* If the service was signaled with a SIGTERM and fails to respond,
1065 * kill the system service with a SIGKILL signal.
1067 else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
1068 && rp->r_pid > 0) {
1069 kill(rp->r_pid, SIGKILL); /* terminate */
1072 /* There seems to be no special conditions. If the service has a
1073 * period assigned check its status.
1075 else if (period > 0) {
1077 /* Check if an answer to a status request is still pending. If
1078 * the service didn't respond within time, kill it to simulate
1079 * a crash. The failure will be detected and the service will
1080 * be restarted automatically.
1082 if (rp->r_alive_tm < rp->r_check_tm) {
1083 if (now - rp->r_alive_tm > 2*period &&
1084 rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) {
1085 if(rs_verbose)
1086 printf("RS: service %d reported late\n",
1087 rpub->endpoint);
1088 rp->r_flags |= RS_NOPINGREPLY;
1089 if(rp->r_flags & RS_INITIALIZING) {
1090 rp->r_flags |= RS_EXITING; /* don't restart */
1092 kill(rp->r_pid, SIGKILL); /* simulate crash */
1096 /* No answer pending. Check if a period expired since the last
1097 * check and, if so request the system service's status.
1099 else if (now - rp->r_check_tm > rpub->period) {
1100 #if 0
1101 if(rs_verbose)
1102 printf("RS: status request sent to %d\n", rpub->endpoint);
1103 #endif
1104 notify(rpub->endpoint); /* request status */
1105 rp->r_check_tm = now; /* mark time */
1111 /* Reschedule a synchronous alarm for the next period. */
1112 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
1113 panic("couldn't set alarm: %d", s);
1117 /*===========================================================================*
1118 * start_service *
1119 *===========================================================================*/
1120 PRIVATE int start_service(rp, flags, endpoint)
1121 struct rproc *rp;
1122 int flags;
1123 endpoint_t *endpoint;
1125 /* Try to execute the given system service. Fork a new process. The child
1126 * process will be inhibited from running by the NO_PRIV flag. Only let the
1127 * child run once its privileges have been set by the parent.
1129 int child_proc_nr_e, child_proc_nr_n; /* child process slot */
1130 pid_t child_pid; /* child's process id */
1131 char *file_only;
1132 int s, use_copy, slot_nr, init_type;
1133 bitchunk_t *vm_mask;
1134 message m;
1135 char * null_env = NULL;
1136 struct rprocpub *rpub;
1138 rpub = rp->r_pub;
1139 use_copy= (rpub->sys_flags & SF_USE_COPY);
1141 /* See if we are not using a copy but we do need one to start the service. */
1142 if(!use_copy && (rpub->sys_flags & SF_NEED_COPY)) {
1143 printf("RS: unable to start service %s without an in-memory copy\n",
1144 rpub->label);
1145 free_slot(rp);
1146 return(EPERM);
1149 /* Now fork and branch for parent and child process (and check for error). */
1150 if (use_copy) {
1151 if(rs_verbose) printf("RS: fork_nb..\n");
1152 child_pid= fork_nb();
1153 } else {
1154 if(rs_verbose) printf("RS: fork regular..\n");
1155 child_pid = fork();
1158 switch(child_pid) { /* see fork(2) */
1159 case -1: /* fork failed */
1160 printf("RS: warning, fork() failed: %d\n", errno); /* shouldn't happen */
1161 return(errno); /* return error */
1163 case 0: /* child process */
1164 /* Try to execute the binary that has an absolute path. If this fails,
1165 * e.g., because the root file system cannot be read, try to strip off
1166 * the path, and see if the command is in RS' current working dir.
1168 nice(rp->r_nice); /* Nice before setuid, to allow negative
1169 * nice values.
1171 setuid(rp->r_uid);
1172 cpf_reload(); /* Tell kernel about grant table */
1173 if (!use_copy)
1175 execve(rp->r_argv[0], rp->r_argv, &null_env); /* POSIX execute */
1176 file_only = strrchr(rp->r_argv[0], '/') + 1;
1177 execve(file_only, rp->r_argv, &null_env); /* POSIX execute */
1179 printf("RS: exec failed for %s: %d\n", rp->r_argv[0], errno);
1180 slot_nr= rp-rproc;
1181 s= write(exec_pipe[1], &slot_nr, sizeof(slot_nr));
1182 if (s != sizeof(slot_nr))
1183 printf("RS: write to exec pipe failed: %d/%d\n", s, errno);
1184 exit(1); /* terminate child */
1186 default: /* parent process */
1187 #if 0
1188 if(rs_verbose) printf("RS: parent forked, pid %d..\n", child_pid);
1189 #endif
1190 child_proc_nr_e = getnprocnr(child_pid); /* get child slot */
1191 #if 0
1192 if(rs_verbose) printf("RS: forked into %d..\n", child_proc_nr_e);
1193 #endif
1194 break; /* continue below */
1197 /* Regardless of any following failures, there is now a child process.
1198 * Update the system process table that is maintained by the RS server.
1200 child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
1201 rp->r_flags = RS_IN_USE | flags; /* mark slot in use */
1202 rp->r_restarts += 1; /* raise nr of restarts */
1203 rpub->endpoint = child_proc_nr_e; /* set child details */
1204 rp->r_pid = child_pid;
1205 rp->r_check_tm = 0; /* not checked yet */
1206 getuptime(&rp->r_alive_tm); /* currently alive */
1207 rp->r_stop_tm = 0; /* not exiting yet */
1208 rp->r_backoff = 0; /* not to be restarted */
1209 rproc_ptr[child_proc_nr_n] = rp; /* mapping for fast access */
1210 rpub->in_use = TRUE; /* public entry is now in use */
1212 /* If any of the calls below fail, the RS_EXITING flag is set. This implies
1213 * that the process will be removed from RS's process table once it has
1214 * terminated. The assumption is that it is not useful to try to restart the
1215 * process later in these failure cases.
1218 if (use_copy)
1220 extern char **environ;
1222 /* Copy the executable image into the child process. If this call
1223 * fails, the child process may or may not be killed already. If it is
1224 * not killed, it's blocked because of NO_PRIV. Kill it now either way.
1226 s = dev_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
1227 environ);
1228 if (s != OK) {
1229 printf("RS: dev_execve call failed: %d\n", s);
1230 kill(child_pid, SIGKILL);
1231 rp->r_flags |= RS_EXITING; /* don't try again */
1232 return(s);
1236 /* Set resources when asked to. */
1237 if (rp->r_set_resources)
1239 /* Initialize privilege structure. */
1240 init_privs(rp, &rp->r_priv);
1242 /* Tell VM about allowed calls. */
1243 vm_mask = &rpub->vm_call_mask[0];
1244 if ((s = vm_set_priv(child_proc_nr_e, vm_mask)) < 0) {
1245 printf("RS: vm_set_priv call failed: %d\n", s);
1246 kill(child_pid, SIGKILL);
1247 rp->r_flags |= RS_EXITING;
1248 return (s);
1252 /* Set and synch the privilege structure for the new service. */
1253 if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_SET_SYS, &rp->r_priv)) != OK
1254 || (s = sys_getpriv(&rp->r_priv, child_proc_nr_e)) != OK) {
1255 printf("RS: unable to set privileges: %d\n", s);
1256 kill(child_pid, SIGKILL); /* kill the service */
1257 rp->r_flags |= RS_EXITING; /* expect exit */
1258 return(s); /* return error */
1261 /* If PCI properties are set, inform the PCI driver about the new service. */
1262 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
1263 init_pci(rp, child_proc_nr_e);
1266 /* Publish the new system service. */
1267 s = publish_service(rp);
1268 if (s != OK) {
1269 printf("RS: warning: publish_service failed: %d\n", s);
1272 /* Allow the service to run.
1273 * XXX: We should let the service run/init only after publishing information
1274 * about the new system service, but this is not currently possible due to
1275 * the blocking nature of mapdriver() that expects the service to be running.
1276 * The current solution is not race-free. This hack can go once service
1277 * publishing is made fully asynchronous in RS.
1279 if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_ALLOW, NULL)) != OK) {
1280 printf("RS: unable to allow the service to run: %d\n", s);
1281 kill(child_pid, SIGKILL); /* kill the service */
1282 rp->r_flags |= RS_EXITING; /* expect exit */
1283 return(s); /* return error */
1286 /* Initialize service. */
1287 init_type = rp->r_restarts > 0 ? SEF_INIT_RESTART : SEF_INIT_FRESH;
1288 if((s = init_service(rp, init_type)) != OK) {
1289 panic("unable to initialize service: %d", s);
1292 /* The purpose of non-blocking forks is to avoid involving VFS in the forking
1293 * process, because VFS may be blocked on a sendrec() to a MFS that is
1294 * waiting for a endpoint update for a dead driver. We have just published
1295 * that update, but VFS may still be blocked. As a result, VFS may not yet
1296 * have received PM's fork message. Hence, if we call mapdriver()
1297 * immediately, VFS may not know about the process and thus refuse to add the
1298 * driver entry. The following temporary hack works around this by forcing
1299 * blocking communication from PM to VFS. Once VFS has been made non-blocking
1300 * towards MFS instances, this hack and the entire fork_nb() call can go.
1302 if (use_copy)
1303 setuid(0);
1305 /* Map the new service. */
1306 if (rpub->dev_nr > 0) { /* set driver map */
1307 if ((s=mapdriver(rpub->label,
1308 rpub->dev_nr, rpub->dev_style, !!use_copy /* force */)) < 0) {
1309 printf("RS: couldn't map driver (continuing): %d\n", errno);
1313 if(rs_verbose)
1314 printf("RS: started '%s', major %d, pid %d, endpoint %d, proc %d\n",
1315 rp->r_cmd, rpub->dev_nr, child_pid,
1316 child_proc_nr_e, child_proc_nr_n);
1318 /* The system service now has been successfully started. The only thing
1319 * that can go wrong now, is that execution fails at the child. If that's
1320 * the case, the child will exit.
1322 if(endpoint) *endpoint = child_proc_nr_e; /* send back child endpoint */
1324 return(OK);
1327 /*===========================================================================*
1328 * stop_service *
1329 *===========================================================================*/
1330 PRIVATE void stop_service(struct rproc *rp,int how)
1332 /* Try to stop the system service. First send a SIGTERM signal to ask the
1333 * system service to terminate. If the service didn't install a signal
1334 * handler, it will be killed. If it did and ignores the signal, we'll
1335 * find out because we record the time here and send a SIGKILL.
1337 if(rs_verbose) printf("RS tries to stop %s (pid %d)\n", rp->r_cmd, rp->r_pid);
1339 rp->r_flags |= how; /* what to on exit? */
1340 if(rp->r_pid > 0) kill(rp->r_pid, SIGTERM); /* first try friendly */
1341 else if(rs_verbose) printf("RS: no process to kill\n");
1342 getuptime(&rp->r_stop_tm); /* record current time */
1346 /*===========================================================================*
1347 * do_getsysinfo *
1348 *===========================================================================*/
1349 PUBLIC int do_getsysinfo(m_ptr)
1350 message *m_ptr;
1352 vir_bytes src_addr, dst_addr;
1353 int dst_proc;
1354 size_t len;
1355 int s;
1357 /* This call requires special privileges. */
1358 if (!caller_is_root(m_ptr->m_source)) return(EPERM);
1360 switch(m_ptr->m1_i1) {
1361 case SI_PROC_TAB:
1362 src_addr = (vir_bytes) rproc;
1363 len = sizeof(struct rproc) * NR_SYS_PROCS;
1364 break;
1365 case SI_PROCPUB_TAB:
1366 src_addr = (vir_bytes) rprocpub;
1367 len = sizeof(struct rprocpub) * NR_SYS_PROCS;
1368 break;
1369 default:
1370 return(EINVAL);
1373 dst_proc = m_ptr->m_source;
1374 dst_addr = (vir_bytes) m_ptr->m1_p1;
1375 if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
1376 return(s);
1377 return(OK);
1380 /*===========================================================================*
1381 * fork_nb *
1382 *===========================================================================*/
1383 PRIVATE pid_t fork_nb()
1385 message m;
1387 return(_syscall(PM_PROC_NR, FORK_NB, &m));
1390 /*===========================================================================*
1391 * share_exec *
1392 *===========================================================================*/
1393 PRIVATE int share_exec(rp_dst, rp_src)
1394 struct rproc *rp_dst, *rp_src;
1396 struct rprocpub *rpub_src;
1397 struct rprocpub *rpub_dst;
1399 rpub_src = rp_src->r_pub;
1400 rpub_dst = rp_dst->r_pub;
1402 if(rs_verbose) {
1403 printf("RS: share_exec: sharing exec image from %s to %s\n",
1404 rpub_src->label, rpub_dst->label);
1407 /* Share exec image from rp_src to rp_dst. */
1408 rp_dst->r_exec_len = rp_src->r_exec_len;
1409 rp_dst->r_exec = rp_src->r_exec;
1411 return OK;
1414 /*===========================================================================*
1415 * read_exec *
1416 *===========================================================================*/
1417 PRIVATE int read_exec(rp)
1418 struct rproc *rp;
1420 int e, r, fd;
1421 char *e_name;
1422 struct stat sb;
1424 e_name= rp->r_argv[0];
1425 if(rs_verbose) {
1426 printf("RS: read_exec: copying exec image from: %s\n", e_name);
1429 r= stat(e_name, &sb);
1430 if (r != 0)
1431 return -errno;
1433 fd= open(e_name, O_RDONLY);
1434 if (fd == -1)
1435 return -errno;
1437 rp->r_exec_len= sb.st_size;
1438 rp->r_exec= malloc(rp->r_exec_len);
1439 if (rp->r_exec == NULL)
1441 printf("RS: read_exec: unable to allocate %d bytes\n",
1442 rp->r_exec_len);
1443 close(fd);
1444 return ENOMEM;
1447 r= read(fd, rp->r_exec, rp->r_exec_len);
1448 e= errno;
1449 close(fd);
1450 if (r == rp->r_exec_len)
1451 return OK;
1453 printf("RS: read_exec: read failed %d, errno %d\n", r, e);
1455 free(rp->r_exec);
1456 rp->r_exec= NULL;
1458 if (r >= 0)
1459 return EIO;
1460 else
1461 return -e;
1464 /*===========================================================================*
1465 * free_slot *
1466 *===========================================================================*/
1467 PRIVATE void free_slot(rp)
1468 struct rproc *rp;
1470 int slot_nr, has_shared_exec;
1471 struct rprocpub *rpub;
1472 struct rproc *other_rp;
1474 rpub = rp->r_pub;
1476 /* Free memory if necessary. */
1477 if(rpub->sys_flags & SF_USE_COPY) {
1478 /* Search for some other slot sharing the same exec image. */
1479 has_shared_exec = FALSE;
1480 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1481 other_rp = &rproc[slot_nr]; /* get pointer to slot */
1482 if (other_rp->r_flags & RS_IN_USE && other_rp != rp
1483 && other_rp->r_exec == rp->r_exec) { /* found! */
1484 has_shared_exec = TRUE;
1488 /* If nobody uses our copy of the exec image, we can get rid of it. */
1489 if(!has_shared_exec) {
1490 if(rs_verbose) {
1491 printf("RS: free_slot: free exec image from %s\n",
1492 rpub->label);
1494 free(rp->r_exec);
1495 rp->r_exec = NULL;
1496 rp->r_exec_len = 0;
1500 /* Mark slot as no longer in use.. */
1501 rp->r_flags = 0;
1502 rpub->in_use = FALSE;
1503 rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
1506 /*===========================================================================*
1507 * run_script *
1508 *===========================================================================*/
1509 PRIVATE void run_script(rp)
1510 struct rproc *rp;
1512 int r, endpoint;
1513 pid_t pid;
1514 char *reason;
1515 char incarnation_str[20]; /* Enough for a counter? */
1516 char *envp[1] = { NULL };
1517 struct rprocpub *rpub;
1519 rpub = rp->r_pub;
1520 if (rp->r_flags & RS_REFRESHING)
1521 reason= "restart";
1522 else if (rp->r_flags & RS_NOPINGREPLY)
1523 reason= "no-heartbeat";
1524 else if (rp->r_flags & RS_KILLED)
1525 reason= "killed";
1526 else if (rp->r_flags & RS_CRASHED)
1527 reason= "crashed";
1528 else if (rp->r_flags & RS_SIGNALED)
1529 reason= "signaled";
1530 else
1532 printf(
1533 "RS: run_script: can't find reason for termination of '%s'\n",
1534 rpub->label);
1535 return;
1537 sprintf(incarnation_str, "%d", rp->r_restarts);
1539 if(rs_verbose) {
1540 printf("RS: calling script '%s'\n", rp->r_script);
1541 printf("RS: sevice name: '%s'\n", rpub->label);
1542 printf("RS: reason: '%s'\n", reason);
1543 printf("RS: incarnation: '%s'\n", incarnation_str);
1546 pid= fork();
1547 switch(pid)
1549 case -1:
1550 printf("RS: run_script: fork failed: %s\n", strerror(errno));
1551 break;
1552 case 0:
1553 execle(rp->r_script, rp->r_script, rpub->label, reason,
1554 incarnation_str, NULL, envp);
1555 printf("RS: run_script: execl '%s' failed: %s\n",
1556 rp->r_script, strerror(errno));
1557 exit(1);
1558 default:
1559 /* Set the privilege structure for the child process. */
1560 endpoint = getnprocnr(pid);
1561 if ((r = sys_privctl(endpoint, SYS_PRIV_SET_USER, NULL))
1562 != OK) {
1563 printf("RS: run_script: can't set privileges: %d\n",r);
1565 /* Allow the service to run. */
1566 if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
1567 printf("RS: run_script: process can't run: %d\n",r);
1569 /* Do not wait for the child */
1570 break;
1575 /*===========================================================================*
1576 * get_next_label *
1577 *===========================================================================*/
1578 PRIVATE char *get_next_label(ptr, label, caller_label)
1579 char *ptr;
1580 char *label;
1581 char *caller_label;
1583 /* Get the next label from the list of (IPC) labels.
1585 char *p, *q;
1586 size_t len;
1588 for (p= ptr; p[0] != '\0'; p= q)
1590 /* Skip leading space */
1591 while (p[0] != '\0' && isspace((unsigned char)p[0]))
1592 p++;
1594 /* Find start of next word */
1595 q= p;
1596 while (q[0] != '\0' && !isspace((unsigned char)q[0]))
1597 q++;
1598 if (q == p)
1599 continue;
1600 len= q-p;
1601 if (len > RS_MAX_LABEL_LEN)
1603 printf(
1604 "rs:get_next_label: bad ipc list entry '.*s' for %s: too long\n",
1605 len, p, caller_label);
1606 continue;
1608 memcpy(label, p, len);
1609 label[len]= '\0';
1611 return q; /* found another */
1614 return NULL; /* done */
1617 /*===========================================================================*
1618 * add_forward_ipc *
1619 *===========================================================================*/
1620 PRIVATE void add_forward_ipc(rp, privp)
1621 struct rproc *rp;
1622 struct priv *privp;
1624 /* Add IPC send permissions to a process based on that process's IPC
1625 * list.
1627 char label[RS_MAX_LABEL_LEN+1], *p;
1628 struct rproc *tmp_rp;
1629 struct rprocpub *tmp_rpub;
1630 endpoint_t endpoint;
1631 int r;
1632 int slot_nr, priv_id;
1633 struct priv priv;
1634 struct rprocpub *rpub;
1636 rpub = rp->r_pub;
1637 p = rp->r_ipc_list;
1639 while ((p = get_next_label(p, label, rpub->label)) != NULL) {
1641 if (strcmp(label, "SYSTEM") == 0)
1642 endpoint= SYSTEM;
1643 else if (strcmp(label, "USER") == 0)
1644 endpoint= INIT_PROC_NR; /* all user procs */
1645 else if (strcmp(label, "PM") == 0)
1646 endpoint= PM_PROC_NR;
1647 else if (strcmp(label, "VFS") == 0)
1648 endpoint= FS_PROC_NR;
1649 else if (strcmp(label, "RS") == 0)
1650 endpoint= RS_PROC_NR;
1651 else if (strcmp(label, "LOG") == 0)
1652 endpoint= LOG_PROC_NR;
1653 else if (strcmp(label, "TTY") == 0)
1654 endpoint= TTY_PROC_NR;
1655 else if (strcmp(label, "DS") == 0)
1656 endpoint= DS_PROC_NR;
1657 else if (strcmp(label, "VM") == 0)
1658 endpoint= VM_PROC_NR;
1659 else
1661 /* Try to find process */
1662 for (slot_nr = 0; slot_nr < NR_SYS_PROCS;
1663 slot_nr++)
1665 tmp_rp = &rproc[slot_nr];
1666 if (!(tmp_rp->r_flags & RS_IN_USE))
1667 continue;
1668 tmp_rpub = tmp_rp->r_pub;
1669 if (strcmp(tmp_rpub->label, label) == 0)
1670 break;
1672 if (slot_nr >= NR_SYS_PROCS)
1674 if (rs_verbose)
1675 printf(
1676 "add_forward_ipc: unable to find '%s'\n", label);
1677 continue;
1679 endpoint= tmp_rpub->endpoint;
1682 if ((r = sys_getpriv(&priv, endpoint)) < 0)
1684 printf(
1685 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1686 label, r);
1687 continue;
1689 priv_id= priv.s_id;
1690 set_sys_bit(privp->s_ipc_to, priv_id);
1695 /*===========================================================================*
1696 * add_backward_ipc *
1697 *===========================================================================*/
1698 PRIVATE void add_backward_ipc(rp, privp)
1699 struct rproc *rp;
1700 struct priv *privp;
1702 /* Add IPC send permissions to a process based on other processes' IPC
1703 * lists. This is enough to allow each such two processes to talk to
1704 * each other, as the kernel guarantees send mask symmetry. We need to
1705 * add these permissions now because the current process may not yet
1706 * have existed at the time that the other process was initialized.
1708 char label[RS_MAX_LABEL_LEN+1], *p;
1709 struct rproc *rrp;
1710 struct rprocpub *rrpub;
1711 int priv_id, found;
1713 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
1714 if (!(rrp->r_flags & RS_IN_USE))
1715 continue;
1717 /* If an IPC target list was provided for the process being
1718 * checked here, make sure that the label of the new process
1719 * is in that process's list.
1721 if (rrp->r_ipc_list[0]) {
1722 found = 0;
1724 rrpub = rrp->r_pub;
1725 p = rrp->r_ipc_list;
1727 while ((p = get_next_label(p, label,
1728 rrpub->label)) != NULL) {
1729 if (!strcmp(rrpub->label, label)) {
1730 found = 1;
1731 break;
1735 if (!found)
1736 continue;
1739 priv_id= rrp->r_priv.s_id;
1741 set_sys_bit(privp->s_ipc_to, priv_id);
1746 /*===========================================================================*
1747 * init_privs *
1748 *===========================================================================*/
1749 PRIVATE void init_privs(rp, privp)
1750 struct rproc *rp;
1751 struct priv *privp;
1753 int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
1754 src_bit, call_nr;
1755 unsigned long mask;
1757 /* Clear s_k_call_mask */
1758 memset(privp->s_k_call_mask, '\0', sizeof(privp->s_k_call_mask));
1760 src_bits_per_word= 8*sizeof(rp->r_call_mask[0]);
1761 dst_bits_per_word= 8*sizeof(privp->s_k_call_mask[0]);
1762 for (src_word= 0; src_word < RS_SYS_CALL_MASK_SIZE; src_word++)
1764 for (src_bit= 0; src_bit < src_bits_per_word; src_bit++)
1766 mask= (1UL << src_bit);
1767 if (!(rp->r_call_mask[src_word] & mask))
1768 continue;
1769 call_nr= src_word*src_bits_per_word+src_bit;
1770 #if 0
1771 if(rs_verbose)
1772 printf("RS: init_privs: system call %d\n", call_nr);
1773 #endif
1774 dst_word= call_nr / dst_bits_per_word;
1775 mask= (1UL << (call_nr % dst_bits_per_word));
1776 if (dst_word >= SYS_CALL_MASK_SIZE)
1778 printf(
1779 "RS: init_privs: call number %d doesn't fit\n",
1780 call_nr);
1782 privp->s_k_call_mask[dst_word] |= mask;
1786 /* Clear s_ipc_to */
1787 memset(&privp->s_ipc_to, '\0', sizeof(privp->s_ipc_to));
1789 if (strlen(rp->r_ipc_list) != 0)
1791 add_forward_ipc(rp, privp);
1792 add_backward_ipc(rp, privp);
1795 else
1797 for (i= 0; i<NR_SYS_PROCS; i++)
1799 if (i != USER_PRIV_ID)
1800 set_sys_bit(privp->s_ipc_to, i);
1805 /*===========================================================================*
1806 * init_pci *
1807 *===========================================================================*/
1808 PRIVATE void init_pci(rp, endpoint)
1809 struct rproc *rp;
1810 int endpoint;
1812 /* Inform the PCI driver about the new service. */
1813 size_t len;
1814 int i, r;
1815 struct rs_pci rs_pci;
1816 struct rprocpub *rpub;
1818 rpub = rp->r_pub;
1819 rs_pci = rpub->pci_acl;
1820 strcpy(rs_pci.rsp_label, rpub->label);
1821 rs_pci.rsp_endpoint= endpoint;
1823 if(rs_verbose)
1824 printf("RS: init_pci: calling pci_set_acl\n");
1826 r= pci_set_acl(&rs_pci);
1828 if(rs_verbose)
1829 printf("RS: init_pci: after pci_set_acl\n");
1831 if (r != OK)
1833 printf("RS: init_pci: pci_set_acl failed: %s\n",
1834 strerror(errno));
1835 return;
1839 /*===========================================================================*
1840 * do_lookup *
1841 *===========================================================================*/
1842 PUBLIC int do_lookup(m_ptr)
1843 message *m_ptr;
1845 static char namebuf[100];
1846 int len, r;
1847 struct rproc *rrp;
1848 struct rprocpub *rrpub;
1850 len = m_ptr->RS_NAME_LEN;
1852 if(len < 2 || len >= sizeof(namebuf)) {
1853 printf("RS: len too weird (%d)\n", len);
1854 return EINVAL;
1857 if((r=sys_vircopy(m_ptr->m_source, D, (vir_bytes) m_ptr->RS_NAME,
1858 SELF, D, (vir_bytes) namebuf, len)) != OK) {
1859 printf("RS: name copy failed\n");
1860 return r;
1864 namebuf[len] = '\0';
1866 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
1867 if (!(rrp->r_flags & RS_IN_USE))
1868 continue;
1869 rrpub = rrp->r_pub;
1870 if (!strcmp(rrpub->label, namebuf)) {
1871 m_ptr->RS_ENDPOINT = rrpub->endpoint;
1872 return OK;
1876 return ESRCH;