rs: stacktrace if system process exits early.
[minix.git] / servers / rs / manager.c
blobb585b40bf004a96e03f59c7a9332fcc1f7f41791
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"
10 /*===========================================================================*
11 * caller_is_root *
12 *===========================================================================*/
13 PUBLIC int caller_is_root(endpoint)
14 endpoint_t endpoint; /* caller endpoint */
16 uid_t euid;
18 /* Check if caller has root user ID. */
19 euid = getnuid(endpoint);
20 if (rs_verbose && euid != 0)
22 printf("RS: got unauthorized request from endpoint %d\n", endpoint);
25 return euid == 0;
28 /*===========================================================================*
29 * caller_can_control *
30 *===========================================================================*/
31 PUBLIC int caller_can_control(endpoint, label)
32 endpoint_t endpoint;
33 char *label;
35 int control_allowed = 0;
36 register struct rproc *rp;
37 register struct rprocpub *rpub;
38 int c;
39 char *progname;
41 /* Find name of binary for given label. */
42 rp = lookup_slot_by_label(label);
43 if (!rp) return 0;
44 progname = strrchr(rp->r_argv[0], '/');
45 if (progname != NULL)
46 progname++;
47 else
48 progname = rp->r_argv[0];
50 /* Check if label is listed in caller's isolation policy. */
51 for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) {
52 rpub = rp->r_pub;
53 if (rpub->endpoint == endpoint) {
54 break;
57 if (rp == END_RPROC_ADDR) return 0;
58 if (rp->r_nr_control > 0) {
59 for (c = 0; c < rp->r_nr_control; c++) {
60 if (strcmp(rp->r_control[c], progname) == 0)
61 control_allowed = 1;
65 if (rs_verbose)
66 printf("RS: allowing %u control over %s via policy: %s\n",
67 endpoint, label, control_allowed ? "yes" : "no");
69 return control_allowed;
72 /*===========================================================================*
73 * check_call_permission *
74 *===========================================================================*/
75 PUBLIC int check_call_permission(caller, call, rp)
76 endpoint_t caller;
77 int call;
78 struct rproc *rp;
80 /* Check if the caller has permission to execute a particular call. */
81 struct rprocpub *rpub;
82 int call_allowed;
84 /* Caller should be either root or have control privileges. */
85 call_allowed = caller_is_root(caller);
86 if(rp) {
87 call_allowed |= caller_can_control(caller, rp->r_pub->label);
89 if(!call_allowed) {
90 return EPERM;
93 if(rp) {
94 rpub = rp->r_pub;
96 /* Disallow the call if the target is RS or a user process. */
97 if(!(rp->r_priv.s_flags & SYS_PROC) || rpub->endpoint == RS_PROC_NR) {
98 return EPERM;
101 /* Disallow the call if another call is in progress for the service. */
102 if(rp->r_flags & RS_LATEREPLY || rp->r_flags & RS_INITIALIZING) {
103 return EBUSY;
106 /* Only allow RS_DOWN and RS_RESTART if the service has terminated. */
107 if(rp->r_flags & RS_TERMINATED) {
108 if(call != RS_DOWN && call != RS_RESTART) return EPERM;
111 /* Disallow RS_DOWN for core system services. */
112 if (rpub->sys_flags & SF_CORE_SRV) {
113 if(call == RS_DOWN) return EPERM;
117 return OK;
120 /*===========================================================================*
121 * copy_rs_start *
122 *===========================================================================*/
123 PUBLIC int copy_rs_start(src_e, src_rs_start, dst_rs_start)
124 endpoint_t src_e;
125 char *src_rs_start;
126 struct rs_start *dst_rs_start;
128 int r;
130 r = sys_datacopy(src_e, (vir_bytes) src_rs_start,
131 SELF, (vir_bytes) dst_rs_start, sizeof(struct rs_start));
133 return r;
136 /*===========================================================================*
137 * copy_label *
138 *===========================================================================*/
139 PUBLIC int copy_label(src_e, src_label, src_len, dst_label, dst_len)
140 endpoint_t src_e;
141 char *src_label;
142 size_t src_len;
143 char *dst_label;
144 size_t dst_len;
146 int s, len;
148 len = MIN(dst_len-1, src_len);
150 s = sys_datacopy(src_e, (vir_bytes) src_label,
151 SELF, (vir_bytes) dst_label, len);
152 if (s != OK) return s;
154 dst_label[len] = 0;
156 return OK;
159 /*===========================================================================*
160 * build_cmd_dep *
161 *===========================================================================*/
162 PUBLIC void build_cmd_dep(struct rproc *rp)
164 struct rprocpub *rpub;
165 int arg_count;
166 int len;
167 char *cmd_ptr;
169 rpub = rp->r_pub;
171 /* Build argument vector to be passed to execute call. The format of the
172 * arguments vector is: path, arguments, NULL.
174 strcpy(rp->r_args, rp->r_cmd); /* copy raw command */
175 arg_count = 0; /* initialize arg count */
176 rp->r_argv[arg_count++] = rp->r_args; /* start with path */
177 cmd_ptr = rp->r_args; /* do some parsing */
178 while(*cmd_ptr != '\0') { /* stop at end of string */
179 if (*cmd_ptr == ' ') { /* next argument */
180 *cmd_ptr = '\0'; /* terminate previous */
181 while (*++cmd_ptr == ' ') ; /* skip spaces */
182 if (*cmd_ptr == '\0') break; /* no arg following */
183 if (arg_count>MAX_NR_ARGS+1) break; /* arg vector full */
184 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
186 cmd_ptr ++; /* continue parsing */
188 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
189 rp->r_argc = arg_count;
191 /* Build process name. */
192 cmd_ptr = strrchr(rp->r_argv[0], '/');
193 if (cmd_ptr)
194 cmd_ptr++;
195 else
196 cmd_ptr= rp->r_argv[0];
197 len= strlen(cmd_ptr);
198 if (len > RS_MAX_LABEL_LEN-1)
199 len= RS_MAX_LABEL_LEN-1; /* truncate name */
200 memcpy(rpub->proc_name, cmd_ptr, len);
201 rpub->proc_name[len]= '\0';
204 /*===========================================================================*
205 * srv_fork *
206 *===========================================================================*/
207 PUBLIC pid_t srv_fork()
209 message m;
211 return(_syscall(PM_PROC_NR, SRV_FORK, &m));
214 /*===========================================================================*
215 * srv_kill *
216 *===========================================================================*/
217 PUBLIC int srv_kill(pid_t pid, int sig)
219 message m;
221 m.m1_i1 = pid;
222 m.m1_i2 = sig;
223 return(_syscall(PM_PROC_NR, SRV_KILL, &m));
226 /*===========================================================================*
227 * srv_update *
228 *===========================================================================*/
229 PUBLIC int srv_update(endpoint_t src_e, endpoint_t dst_e)
231 int r;
233 /* Ask VM to swap the slots of the two processes and tell the kernel to
234 * do the same. If VM is the service being updated, only perform the kernel
235 * part of the call. The new instance of VM will do the rest at
236 * initialization time.
238 if(src_e != VM_PROC_NR) {
239 r = vm_update(src_e, dst_e);
241 else {
242 r = sys_update(src_e, dst_e);
245 return r;
248 /*===========================================================================*
249 * update_period *
250 *===========================================================================*/
251 PUBLIC void update_period(message *m_ptr)
253 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
254 short has_update_timed_out;
255 message m;
256 struct rprocpub *rpub;
258 rpub = rupdate.rp->r_pub;
260 /* See if a timeout has occurred. */
261 has_update_timed_out = (now - rupdate.prepare_tm > rupdate.prepare_maxtime);
263 /* If an update timed out, end the update process and notify
264 * the old version that the update has been canceled. From now on, the old
265 * version will continue executing.
267 if(has_update_timed_out) {
268 printf("RS: update failed: maximum prepare time reached\n");
269 end_update(EINTR);
271 /* Prepare cancel request. */
272 m.m_type = RS_LU_PREPARE;
273 m.RS_LU_STATE = SEF_LU_STATE_NULL;
274 asynsend(rpub->endpoint, &m);
278 /*===========================================================================*
279 * end_update *
280 *===========================================================================*/
281 PUBLIC void end_update(int result)
283 /* End the update process. There are two possibilities:
284 * 1) the update succeeded. In that case, cleanup the old version and mark the
285 * new version as no longer under update.
286 * 2) the update failed. In that case, cleanup the new version and mark the old
287 * version as no longer under update. Eventual late ready to update
288 * messages (if any) will simply be ignored and the service can
289 * continue executing. In addition, reset the check timestamp, so that if the
290 * service has a period, a status request will be forced in the next period.
292 struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp;
294 old_rp = rupdate.rp;
295 new_rp = old_rp->r_new_rp;
297 if(rs_verbose)
298 printf("RS: ending update from %s to %s with result: %d\n",
299 srv_to_string(old_rp), srv_to_string(new_rp), result);
301 /* Decide which version has to die out and which version has to survive. */
302 surviving_rp = (result == OK ? new_rp : old_rp);
303 exiting_rp = (result == OK ? old_rp : new_rp);
305 /* End update. */
306 rupdate.flags &= ~RS_UPDATING;
307 rupdate.rp = NULL;
308 old_rp->r_new_rp = NULL;
309 new_rp->r_old_rp = NULL;
310 old_rp->r_check_tm = 0;
312 /* Send a late reply if necessary. */
313 late_reply(old_rp, result);
315 /* Unpublish and cleanup the version that has to die out and mark the other
316 * version as no longer updating.
318 surviving_rp->r_flags &= ~RS_UPDATING;
319 cleanup_service(exiting_rp);
321 if(rs_verbose)
322 printf("RS: service %s ended the update\n", srv_to_string(surviving_rp));
325 /*===========================================================================*
326 * kill_service_debug *
327 *===========================================================================*/
328 PUBLIC int kill_service_debug(file, line, rp, errstr, err)
329 char *file;
330 int line;
331 struct rproc *rp;
332 char *errstr;
333 int err;
335 /* Crash a system service and don't let it restart. */
336 if(errstr && !shutting_down) {
337 printf("RS: %s (error %d)\n", errstr, err);
339 rp->r_flags |= RS_EXITING; /* expect exit */
340 crash_service_debug(file, line, rp); /* simulate crash */
342 return err;
345 /*===========================================================================*
346 * crash_service_debug *
347 *===========================================================================*/
348 PUBLIC int crash_service_debug(file, line, rp)
349 char *file;
350 int line;
351 struct rproc *rp;
353 /* Simluate a crash in a system service. */
354 struct rprocpub *rpub;
356 rpub = rp->r_pub;
358 if(rs_verbose)
359 printf("RS: %s %skilled at %s:%d\n", srv_to_string(rp),
360 rp->r_flags & RS_EXITING ? "lethally " : "", file, line);
362 return sys_kill(rpub->endpoint, SIGKILL);
365 /*===========================================================================*
366 * cleanup_service_debug *
367 *===========================================================================*/
368 PUBLIC void cleanup_service_debug(file, line, rp)
369 char *file;
370 int line;
371 struct rproc *rp;
373 /* Ask PM to exit the service and free slot. */
374 struct rprocpub *rpub;
376 rpub = rp->r_pub;
378 if(rs_verbose)
379 printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp),
380 file, line);
382 if(rp->r_pid == -1) {
383 printf("RS: warning: attempt to kill pid -1!\n");
385 else {
386 srv_kill(rp->r_pid, SIGKILL);
389 free_slot(rp);
392 /*===========================================================================*
393 * create_service *
394 *===========================================================================*/
395 PUBLIC int create_service(rp)
396 struct rproc *rp;
398 /* Create the given system service. */
399 int child_proc_nr_e, child_proc_nr_n; /* child process slot */
400 pid_t child_pid; /* child's process id */
401 int s, use_copy, has_replica;
402 extern char **environ;
403 struct rprocpub *rpub;
405 rpub = rp->r_pub;
406 use_copy= (rpub->sys_flags & SF_USE_COPY);
407 has_replica= (rp->r_prev_rp && !(rp->r_prev_rp->r_flags & RS_TERMINATED));
409 /* Do we need an existing replica to create the service? */
410 if(!has_replica && (rpub->sys_flags & SF_NEED_REPL)) {
411 printf("RS: unable to create service '%s' without a replica\n",
412 rpub->label);
413 free_slot(rp);
414 return(EPERM);
417 /* Do we need an in-memory copy to create the service? */
418 if(!use_copy && (rpub->sys_flags & SF_NEED_COPY)) {
419 printf("RS: unable to create service '%s' without an in-memory copy\n",
420 rpub->label);
421 free_slot(rp);
422 return(EPERM);
425 /* Now fork and branch for parent and child process (and check for error). */
426 if(rs_verbose)
427 printf("RS: forking child with srv_fork()...\n");
428 child_pid= srv_fork();
429 if(child_pid == -1) {
430 printf("RS: srv_fork() failed (error %d)\n", errno);
431 free_slot(rp);
432 return(errno);
435 /* Get endpoint of the child. */
436 child_proc_nr_e = getnprocnr(child_pid);
438 /* There is now a child process. Update the system process table. */
439 child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
440 rp->r_flags = RS_IN_USE; /* mark slot in use */
441 rpub->endpoint = child_proc_nr_e; /* set child endpoint */
442 rp->r_pid = child_pid; /* set child pid */
443 rp->r_check_tm = 0; /* not checked yet */
444 getuptime(&rp->r_alive_tm); /* currently alive */
445 rp->r_stop_tm = 0; /* not exiting yet */
446 rp->r_backoff = 0; /* not to be restarted */
447 rproc_ptr[child_proc_nr_n] = rp; /* mapping for fast access */
448 rpub->in_use = TRUE; /* public entry is now in use */
450 /* Set resources when asked to. */
451 if (rp->r_set_resources) {
452 /* Initialize privilege structure. */
453 init_privs(rp, &rp->r_priv);
456 /* Set and synch the privilege structure for the new service.
457 * In case the following fails, we can't kill the process as no signal
458 * manager has been assigned yet. The solution is to directly call
459 * terminate_service() without sending any signal to the process.
461 if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_SET_SYS, &rp->r_priv)) != OK
462 || (s = sys_getpriv(&rp->r_priv, child_proc_nr_e)) != OK) {
463 printf("unable to set privilege structure: %d\n", s);
464 rp->r_flags |= RS_EXITING;
465 terminate_service(rp);
466 return ENOMEM;
469 /* Copy the executable image into the child process. If this call
470 * fails, the child process may or may not be killed already. If it is
471 * not killed, it's blocked because of NO_PRIV. Kill it now either way.
472 * If no copy exists, allocate one and free it right after exec completes.
474 if(use_copy) {
475 if(rs_verbose)
476 printf("RS: %s uses an in-memory copy\n",
477 srv_to_string(rp));
479 else {
480 if ((s = read_exec(rp)) != OK) {
481 return kill_service(rp, "read_exec failed", s);
484 if(rs_verbose)
485 printf("RS: execing child with srv_execve()...\n");
486 s = srv_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
487 environ);
489 if (s != OK) {
490 return kill_service(rp, "srv_execve failed", s);
492 if(!use_copy) {
493 free_exec(rp);
496 /* The purpose of non-blocking forks is to avoid involving VFS in the forking
497 * process, because VFS may be blocked on a sendrec() to a MFS that is
498 * waiting for a endpoint update for a dead driver. We have just published
499 * that update, but VFS may still be blocked. As a result, VFS may not yet
500 * have received PM's fork message. Hence, if we call mapdriver()
501 * immediately, VFS may not know about the process and thus refuse to add the
502 * driver entry. The following temporary hack works around this by forcing
503 * blocking communication from PM to VFS. Once VFS has been made non-blocking
504 * towards MFS instances, this hack and the big part of srv_fork() can go.
506 setuid(0);
508 if(rs_verbose)
509 printf("RS: %s created\n", srv_to_string(rp));
511 return OK;
514 /*===========================================================================*
515 * clone_service *
516 *===========================================================================*/
517 PUBLIC int clone_service(rp)
518 struct rproc *rp;
520 /* Clone the given system service instance. */
521 struct rproc *replica_rp;
522 int r;
524 if(rs_verbose)
525 printf("RS: creating a replica for %s\n", srv_to_string(rp));
527 /* Clone slot. */
528 if((r = clone_slot(rp, &replica_rp)) != OK) {
529 return r;
532 /* Link the two slots. */
533 rp->r_next_rp = replica_rp;
534 replica_rp->r_prev_rp = rp;
536 /* Create a new replica of the service. */
537 r = create_service(replica_rp);
538 if(r != OK) {
539 rp->r_next_rp = NULL;
540 return r;
543 return OK;
546 /*===========================================================================*
547 * publish_service *
548 *===========================================================================*/
549 PUBLIC int publish_service(rp)
550 struct rproc *rp; /* pointer to service slot */
552 /* Publish a service. */
553 int r;
554 struct rprocpub *rpub;
555 struct rs_pci pci_acl;
557 rpub = rp->r_pub;
559 /* Register label with DS. */
560 r = ds_publish_label(rpub->label, rpub->endpoint, DSF_OVERWRITE);
561 if (r != OK) {
562 return kill_service(rp, "ds_publish_label call failed", r);
565 /* If the service is a driver, map it. */
566 if (rpub->dev_nr > 0) {
567 if (mapdriver(rpub->label, rpub->dev_nr, rpub->dev_style,
568 rpub->dev_flags) != OK) {
569 return kill_service(rp, "couldn't map driver", errno);
573 /* Tell VM about allowed calls, if any. */
574 if(rpub->vm_call_mask[0]) {
575 r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0]);
576 if (r != OK) {
577 return kill_service(rp, "vm_set_priv call failed", r);
581 /* If PCI properties are set, inform the PCI driver about the new service. */
582 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
583 pci_acl = rpub->pci_acl;
584 strcpy(pci_acl.rsp_label, rpub->label);
585 pci_acl.rsp_endpoint= rpub->endpoint;
587 r = pci_set_acl(&pci_acl);
588 if (r != OK) {
589 return kill_service(rp, "pci_set_acl call failed", r);
593 if(rs_verbose)
594 printf("RS: %s published\n", srv_to_string(rp));
596 return OK;
599 /*===========================================================================*
600 * unpublish_service *
601 *===========================================================================*/
602 PUBLIC int unpublish_service(rp)
603 struct rproc *rp; /* pointer to service slot */
605 /* Unpublish a service. */
606 struct rprocpub *rpub;
607 int r, result;
609 rpub = rp->r_pub;
610 result = OK;
612 /* Unregister label with DS. */
613 r = ds_delete_label(rpub->label);
614 if (r != OK && !shutting_down) {
615 printf("RS: ds_delete_label call failed (error %d)\n", r);
616 result = r;
619 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
621 /* If PCI properties are set, inform the PCI driver. */
622 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
623 r = pci_del_acl(rpub->endpoint);
624 if (r != OK && !shutting_down) {
625 printf("RS: pci_del_acl call failed (error %d)\n", r);
626 result = r;
630 if(rs_verbose)
631 printf("RS: %s unpublished\n", srv_to_string(rp));
633 return result;
636 /*===========================================================================*
637 * run_service *
638 *===========================================================================*/
639 PUBLIC int run_service(rp, init_type)
640 struct rproc *rp;
641 int init_type;
643 /* Let a newly created service run. */
644 int s, use_copy;
645 struct rprocpub *rpub;
647 rpub = rp->r_pub;
648 use_copy= (rpub->sys_flags & SF_USE_COPY);
650 /* Allow the service to run. */
651 if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
652 return kill_service(rp, "unable to allow the service to run",s);
655 /* Initialize service. */
656 if((s = init_service(rp, init_type)) != OK) {
657 return kill_service(rp, "unable to initialize service", s);
660 if(rs_verbose)
661 printf("RS: %s allowed to run\n", srv_to_string(rp));
663 return OK;
666 /*===========================================================================*
667 * start_service *
668 *===========================================================================*/
669 PUBLIC int start_service(rp)
670 struct rproc *rp;
672 /* Start a system service. */
673 int r, init_type;
674 struct rprocpub *rpub;
676 rpub = rp->r_pub;
678 /* Create and make active. */
679 r = create_service(rp);
680 activate_service(rp, NULL);
681 if(r != OK) {
682 return r;
685 /* Publish service properties. */
686 r = publish_service(rp);
687 if (r != OK) {
688 return r;
691 /* Run. */
692 init_type = SEF_INIT_FRESH;
693 r = run_service(rp, init_type);
694 if(r != OK) {
695 return r;
698 if(rs_verbose)
699 printf("RS: %s started with major %d\n", srv_to_string(rp),
700 rpub->dev_nr);
702 return OK;
705 /*===========================================================================*
706 * stop_service *
707 *===========================================================================*/
708 PUBLIC void stop_service(struct rproc *rp,int how)
710 struct rprocpub *rpub;
712 rpub = rp->r_pub;
714 /* Try to stop the system service. First send a SIGTERM signal to ask the
715 * system service to terminate. If the service didn't install a signal
716 * handler, it will be killed. If it did and ignores the signal, we'll
717 * find out because we record the time here and send a SIGKILL.
719 if(rs_verbose)
720 printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp));
722 rp->r_flags |= how; /* what to on exit? */
723 sys_kill(rpub->endpoint, SIGTERM); /* first try friendly */
724 getuptime(&rp->r_stop_tm); /* record current time */
727 /*===========================================================================*
728 * update_service *
729 *===========================================================================*/
730 PUBLIC int update_service(src_rpp, dst_rpp)
731 struct rproc **src_rpp;
732 struct rproc **dst_rpp;
734 /* Update an existing service. */
735 int r;
736 struct rproc *src_rp;
737 struct rproc *dst_rp;
738 struct rprocpub *src_rpub;
739 struct rprocpub *dst_rpub;
740 int pid;
741 endpoint_t endpoint;
743 src_rp = *src_rpp;
744 dst_rp = *dst_rpp;
745 src_rpub = src_rp->r_pub;
746 dst_rpub = dst_rp->r_pub;
748 if(rs_verbose)
749 printf("RS: %s updating into %s\n",
750 srv_to_string(src_rp), srv_to_string(dst_rp));
752 /* Swap the slots of the two processes. */
753 r = srv_update(src_rpub->endpoint, dst_rpub->endpoint);
754 if(r != OK) {
755 return r;
758 /* Swap slots here as well. */
759 pid = src_rp->r_pid;
760 endpoint = src_rpub->endpoint;
761 swap_slot(&src_rp, &dst_rp);
763 /* Reassign pids and endpoints. */
764 src_rp->r_pid = dst_rp->r_pid;
765 src_rp->r_pub->endpoint = dst_rp->r_pub->endpoint;
766 rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)] = src_rp;
767 dst_rp->r_pid = pid;
768 dst_rp->r_pub->endpoint = endpoint;
769 rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)] = dst_rp;
771 /* Adjust input pointers. */
772 *src_rpp = src_rp;
773 *dst_rpp = dst_rp;
775 /* Make the new version active. */
776 activate_service(dst_rp, src_rp);
778 if(rs_verbose)
779 printf("RS: %s updated into %s\n",
780 srv_to_string(src_rp), srv_to_string(dst_rp));
782 return OK;
785 /*===========================================================================*
786 * activate_service *
787 *===========================================================================*/
788 PUBLIC void activate_service(struct rproc *rp, struct rproc *ex_rp)
790 /* Activate a service instance and deactivate another one if requested. */
792 if(ex_rp && (ex_rp->r_flags & RS_ACTIVE) ) {
793 ex_rp->r_flags &= ~RS_ACTIVE;
794 if(rs_verbose)
795 printf("RS: %s becomes inactive\n", srv_to_string(ex_rp));
798 if(! (rp->r_flags & RS_ACTIVE) ) {
799 rp->r_flags |= RS_ACTIVE;
800 if(rs_verbose)
801 printf("RS: %s becomes active\n", srv_to_string(rp));
805 /*===========================================================================*
806 * terminate_service *
807 *===========================================================================*/
808 PUBLIC void terminate_service(struct rproc *rp)
810 /* Handle a termination event for a system service. */
811 struct rproc **rps;
812 struct rprocpub *rpub;
813 int nr_rps;
814 int i, r;
816 rpub = rp->r_pub;
818 if(rs_verbose)
819 printf("RS: %s terminated\n", srv_to_string(rp));
821 /* Deal with failures during initialization. */
822 if(rp->r_flags & RS_INITIALIZING) {
823 printf("RS: service '%s' exited during initialization\n", rpub->label);
824 rp->r_flags |= RS_EXITING; /* don't restart. */
825 sys_sysctl_stacktrace(rp->r_pub->endpoint);
827 /* If updating, rollback. */
828 if(rp->r_flags & RS_UPDATING) {
829 message m;
830 struct rproc *old_rp, *new_rp;
831 printf("RS: update failed: state transfer failed. Rolling back...\n");
832 new_rp = rp;
833 old_rp = new_rp->r_old_rp;
834 new_rp->r_flags &= ~RS_INITIALIZING;
835 update_service(&new_rp, &old_rp); /* can't fail */
836 m.m_type = ERESTART;
837 reply(old_rp->r_pub->endpoint, &m);
838 end_update(ERESTART);
839 return;
843 if (rp->r_flags & RS_EXITING) {
844 /* If a core system service is exiting, we are in trouble. */
845 if (rp->r_pub->sys_flags & SF_CORE_SRV && !shutting_down) {
846 panic("core system service died: %s", srv_to_string(rp));
849 /* See if a late reply has to be sent. */
850 r = (rp->r_caller_request == RS_DOWN ? OK : EDEADSRCDST);
851 late_reply(rp, r);
853 /* Unpublish the service. */
854 unpublish_service(rp);
856 /* Cleanup all the instances of the service. */
857 get_service_instances(rp, &rps, &nr_rps);
858 for(i=0;i<nr_rps;i++) {
859 cleanup_service(rps[i]);
862 else if(rp->r_flags & RS_REFRESHING) {
863 /* Restart service. */
864 restart_service(rp);
866 else {
867 /* If an update is in progress, end it. The old version
868 * that just exited will continue executing.
870 if(rp->r_flags & RS_UPDATING) {
871 end_update(ERESTART);
874 /* Determine what to do. If this is the first unexpected
875 * exit, immediately restart this service. Otherwise use
876 * a binary exponential backoff.
878 if (rp->r_restarts > 0) {
879 rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
880 rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
881 if ((rpub->sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
882 rp->r_backoff= 1;
883 return;
886 /* Restart service. */
887 restart_service(rp);
891 /*===========================================================================*
892 * run_script *
893 *===========================================================================*/
894 PRIVATE int run_script(struct rproc *rp)
896 int r, endpoint;
897 pid_t pid;
898 char *reason;
899 char incarnation_str[20]; /* Enough for a counter? */
900 char *envp[1] = { NULL };
901 struct rprocpub *rpub;
903 rpub = rp->r_pub;
904 if (rp->r_flags & RS_REFRESHING)
905 reason= "restart";
906 else if (rp->r_flags & RS_NOPINGREPLY)
907 reason= "no-heartbeat";
908 else reason= "terminated";
909 sprintf(incarnation_str, "%d", rp->r_restarts);
911 if(rs_verbose) {
912 printf("RS: %s:\n", srv_to_string(rp));
913 printf("RS: calling script '%s'\n", rp->r_script);
914 printf("RS: reason: '%s'\n", reason);
915 printf("RS: incarnation: '%s'\n", incarnation_str);
918 pid= fork();
919 switch(pid)
921 case -1:
922 return kill_service(rp, "unable to fork script", errno);
923 case 0:
924 execle(rp->r_script, rp->r_script, rpub->label, reason,
925 incarnation_str, (char*) NULL, envp);
926 printf("RS: run_script: execl '%s' failed: %s\n",
927 rp->r_script, strerror(errno));
928 exit(1);
929 default:
930 /* Set the privilege structure for the child process. */
931 endpoint = getnprocnr(pid);
932 if ((r = sys_privctl(endpoint, SYS_PRIV_SET_USER, NULL))
933 != OK) {
934 return kill_service(rp,"can't set script privileges",r);
936 /* Allow the script to run. */
937 if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
938 return kill_service(rp,"can't let the script run",r);
941 return OK;
944 /*===========================================================================*
945 * restart_service *
946 *===========================================================================*/
947 PUBLIC void restart_service(struct rproc *rp)
949 /* Restart service via a recovery script or directly. */
950 struct rproc *replica_rp;
951 int r;
953 /* See if a late reply has to be sent. */
954 late_reply(rp, OK);
956 /* Run a recovery script if available. */
957 if (rp->r_script[0] != '\0') {
958 run_script(rp);
959 return;
962 /* Restart directly. We need a replica if not already available. */
963 if(rp->r_next_rp == NULL) {
964 /* Create the replica. */
965 r = clone_service(rp);
966 if(r != OK) {
967 kill_service(rp, "unable to clone service", r);
968 return;
971 replica_rp = rp->r_next_rp;
973 /* Update the service into the replica. */
974 r = update_service(&rp, &replica_rp);
975 if(r != OK) {
976 kill_service(rp, "unable to update into new replica", r);
977 return;
980 /* Let the new replica run. */
981 r = run_service(replica_rp, SEF_INIT_RESTART);
982 if(r != OK) {
983 kill_service(rp, "unable to let the replica run", r);
984 return;
987 /* Increase the number of restarts. */
988 replica_rp->r_restarts += 1;
990 if(rs_verbose)
991 printf("RS: %s restarted into %s\n",
992 srv_to_string(rp), srv_to_string(replica_rp));
995 /*===========================================================================*
996 * inherit_service_defaults *
997 *===========================================================================*/
998 PUBLIC void inherit_service_defaults(def_rp, rp)
999 struct rproc *def_rp;
1000 struct rproc *rp;
1002 struct rprocpub *def_rpub;
1003 struct rprocpub *rpub;
1005 def_rpub = def_rp->r_pub;
1006 rpub = rp->r_pub;
1008 /* Device settings. These properties cannot change. */
1009 rpub->dev_flags = def_rpub->dev_flags;
1010 rpub->dev_nr = def_rpub->dev_nr;
1011 rpub->dev_style = def_rpub->dev_style;
1012 rpub->dev_style2 = def_rpub->dev_style2;
1014 /* Period. */
1015 if(!rpub->period && def_rpub->period) {
1016 rpub->period = def_rpub->period;
1020 /*===========================================================================*
1021 * get_service_instances *
1022 *===========================================================================*/
1023 PUBLIC void get_service_instances(rp, rps, length)
1024 struct rproc *rp;
1025 struct rproc ***rps;
1026 int *length;
1028 /* Retrieve all the service instances of a give service. */
1029 static struct rproc *instances[5];
1030 int nr_instances;
1032 nr_instances = 0;
1033 instances[nr_instances++] = rp;
1034 if(rp->r_prev_rp) instances[nr_instances++] = rp->r_prev_rp;
1035 if(rp->r_next_rp) instances[nr_instances++] = rp->r_next_rp;
1036 if(rp->r_old_rp) instances[nr_instances++] = rp->r_old_rp;
1037 if(rp->r_new_rp) instances[nr_instances++] = rp->r_new_rp;
1039 *rps = instances;
1040 *length = nr_instances;
1043 /*===========================================================================*
1044 * share_exec *
1045 *===========================================================================*/
1046 PUBLIC void share_exec(rp_dst, rp_src)
1047 struct rproc *rp_dst, *rp_src;
1049 struct rprocpub *rpub_src;
1050 struct rprocpub *rpub_dst;
1052 rpub_src = rp_src->r_pub;
1053 rpub_dst = rp_dst->r_pub;
1055 if(rs_verbose)
1056 printf("RS: %s shares exec image with %s\n",
1057 srv_to_string(rp_dst), srv_to_string(rp_src));
1059 /* Share exec image from rp_src to rp_dst. */
1060 rp_dst->r_exec_len = rp_src->r_exec_len;
1061 rp_dst->r_exec = rp_src->r_exec;
1064 /*===========================================================================*
1065 * read_exec *
1066 *===========================================================================*/
1067 PUBLIC int read_exec(rp)
1068 struct rproc *rp;
1070 int e, r, fd;
1071 char *e_name;
1072 struct stat sb;
1074 e_name= rp->r_argv[0];
1075 if(rs_verbose)
1076 printf("RS: service '%s' reads exec image from: %s\n", rp->r_pub->label,
1077 e_name);
1079 r= stat(e_name, &sb);
1080 if (r != 0)
1081 return -errno;
1083 fd= open(e_name, O_RDONLY);
1084 if (fd == -1)
1085 return -errno;
1087 rp->r_exec_len= sb.st_size;
1088 rp->r_exec= malloc(rp->r_exec_len);
1089 if (rp->r_exec == NULL)
1091 printf("RS: read_exec: unable to allocate %d bytes\n",
1092 rp->r_exec_len);
1093 close(fd);
1094 return ENOMEM;
1097 r= read(fd, rp->r_exec, rp->r_exec_len);
1098 e= errno;
1099 close(fd);
1100 if (r == rp->r_exec_len)
1101 return OK;
1103 printf("RS: read_exec: read failed %d, errno %d\n", r, e);
1105 free_exec(rp);
1107 if (r >= 0)
1108 return EIO;
1109 else
1110 return -e;
1113 /*===========================================================================*
1114 * free_exec *
1115 *===========================================================================*/
1116 PUBLIC void free_exec(rp)
1117 struct rproc *rp;
1119 /* Free an exec image. */
1120 int slot_nr, has_shared_exec, is_boot_image_mem;
1121 struct rproc *other_rp;
1123 /* Search for some other slot sharing the same exec image. */
1124 has_shared_exec = FALSE;
1125 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1126 other_rp = &rproc[slot_nr]; /* get pointer to slot */
1127 if (other_rp->r_flags & RS_IN_USE && other_rp != rp
1128 && other_rp->r_exec == rp->r_exec) { /* found! */
1129 has_shared_exec = TRUE;
1130 break;
1134 /* If nobody uses our copy of the exec image, we can try to get rid of it. */
1135 if(!has_shared_exec) {
1136 is_boot_image_mem = (rp->r_exec >= boot_image_buffer
1137 && rp->r_exec < boot_image_buffer + boot_image_buffer_size);
1139 /* Free memory only if not part of the boot image buffer. */
1140 if(is_boot_image_mem) {
1141 if(rs_verbose)
1142 printf("RS: %s has exec image in the boot image buffer\n",
1143 srv_to_string(rp));
1145 else {
1146 if(rs_verbose)
1147 printf("RS: %s frees exec image\n", srv_to_string(rp));
1148 free(rp->r_exec);
1151 else {
1152 if(rs_verbose)
1153 printf("RS: %s no longer sharing exec image with %s\n",
1154 srv_to_string(rp), srv_to_string(other_rp));
1156 rp->r_exec = NULL;
1157 rp->r_exec_len = 0;
1160 /*===========================================================================*
1161 * init_slot *
1162 *===========================================================================*/
1163 PUBLIC int init_slot(rp, rs_start, source)
1164 struct rproc *rp;
1165 struct rs_start *rs_start;
1166 endpoint_t source;
1168 /* Initialize a slot as requested by the client. */
1169 struct rprocpub *rpub;
1170 char *label; /* unique name of command */
1171 int len; /* length of string */
1172 int i;
1173 int s;
1174 int basic_kc[] = { SYS_BASIC_CALLS, SYS_NULL_C };
1175 int basic_vmc[] = { VM_BASIC_CALLS, SYS_NULL_C };
1177 rpub = rp->r_pub;
1179 /* Obtain command name and parameters. This is a space-separated string
1180 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
1182 if (rs_start->rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
1183 s=sys_datacopy(source, (vir_bytes) rs_start->rss_cmd,
1184 SELF, (vir_bytes) rp->r_cmd, rs_start->rss_cmdlen);
1185 if (s != OK) return(s);
1186 rp->r_cmd[rs_start->rss_cmdlen] = '\0'; /* ensure it is terminated */
1187 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
1189 /* Build cmd dependencies: argv and program name. */
1190 build_cmd_dep(rp);
1192 if(rs_start->rss_label.l_len > 0) {
1193 /* RS_UP caller has supplied a custom label for this service. */
1194 int s = copy_label(source, rs_start->rss_label.l_addr,
1195 rs_start->rss_label.l_len, rpub->label, sizeof(rpub->label));
1196 if(s != OK)
1197 return s;
1198 if(rs_verbose)
1199 printf("RS: init_slot: using label (custom) '%s'\n", rpub->label);
1200 } else {
1201 /* Default label for the service. */
1202 label = rpub->proc_name;
1203 len= strlen(label);
1204 memcpy(rpub->label, label, len);
1205 rpub->label[len]= '\0';
1206 if(rs_verbose)
1207 printf("RS: init_slot: using label (from proc_name) '%s'\n",
1208 rpub->label);
1211 if(rs_start->rss_nr_control > 0) {
1212 int i, s;
1213 if (rs_start->rss_nr_control > RS_NR_CONTROL)
1215 printf("RS: init_slot: too many control labels\n");
1216 return EINVAL;
1218 for (i=0; i<rs_start->rss_nr_control; i++) {
1219 s = copy_label(source, rs_start->rss_control[i].l_addr,
1220 rs_start->rss_control[i].l_len, rp->r_control[i],
1221 sizeof(rp->r_control[i]));
1222 if(s != OK)
1223 return s;
1225 rp->r_nr_control = rs_start->rss_nr_control;
1227 if (rs_verbose) {
1228 printf("RS: init_slot: control labels:");
1229 for (i=0; i<rp->r_nr_control; i++)
1230 printf(" %s", rp->r_control[i]);
1231 printf("\n");
1235 rp->r_script[0]= '\0';
1236 if (rs_start->rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
1237 if (rs_start->rss_script != NULL)
1239 s=sys_datacopy(source, (vir_bytes) rs_start->rss_script,
1240 SELF, (vir_bytes) rp->r_script, rs_start->rss_scriptlen);
1241 if (s != OK) return(s);
1242 rp->r_script[rs_start->rss_scriptlen] = '\0';
1244 rp->r_uid= rs_start->rss_uid;
1245 rp->r_nice= rs_start->rss_nice;
1247 if (rs_start->rss_flags & RSS_IPC_VALID)
1249 if (rs_start->rss_ipclen+1 > sizeof(rp->r_ipc_list))
1251 printf("RS: ipc list too long for '%s'\n", rpub->label);
1252 return EINVAL;
1254 s=sys_datacopy(source, (vir_bytes) rs_start->rss_ipc,
1255 SELF, (vir_bytes) rp->r_ipc_list, rs_start->rss_ipclen);
1256 if (s != OK) return(s);
1257 rp->r_ipc_list[rs_start->rss_ipclen]= '\0';
1259 else
1260 rp->r_ipc_list[0]= '\0';
1262 /* Set system flags. */
1263 rpub->sys_flags = DSRV_SF;
1264 rp->r_exec= NULL;
1265 if (rs_start->rss_flags & RSS_COPY) {
1266 int exst_cpy;
1267 struct rproc *rp2;
1268 struct rprocpub *rpub2;
1269 exst_cpy = 0;
1271 if(rs_start->rss_flags & RSS_REUSE) {
1272 int i;
1274 for(i = 0; i < NR_SYS_PROCS; i++) {
1275 rp2 = &rproc[i];
1276 rpub2 = rproc[i].r_pub;
1277 if(strcmp(rpub->proc_name, rpub2->proc_name) == 0 &&
1278 (rpub2->sys_flags & SF_USE_COPY)) {
1279 /* We have found the same binary that's
1280 * already been copied */
1281 exst_cpy = 1;
1282 break;
1287 s = OK;
1288 if(!exst_cpy)
1289 s = read_exec(rp);
1290 else
1291 share_exec(rp, rp2);
1293 if (s != OK)
1294 return s;
1296 rpub->sys_flags |= SF_USE_COPY;
1298 if (rs_start->rss_flags & RSS_REPLICA) {
1299 rpub->sys_flags |= SF_USE_REPL;
1302 /* All dynamically created services get the same privilege flags, and
1303 * allowed traps, and signal manager. Other privilege settings can be
1304 * specified at runtime. The privilege id is dynamically allocated by
1305 * the kernel.
1307 rp->r_priv.s_flags = DSRV_F; /* privilege flags */
1308 rp->r_priv.s_trap_mask = DSRV_T; /* allowed traps */
1309 rp->r_priv.s_sig_mgr = DSRV_SM; /* signal manager */
1311 /* Copy granted resources */
1312 if (rs_start->rss_nr_irq > NR_IRQ)
1314 printf("RS: init_slot: too many IRQs requested\n");
1315 return EINVAL;
1317 rp->r_priv.s_nr_irq= rs_start->rss_nr_irq;
1318 for (i= 0; i<rp->r_priv.s_nr_irq; i++)
1320 rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i];
1321 if(rs_verbose)
1322 printf("RS: init_slot: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
1325 if (rs_start->rss_nr_io > NR_IO_RANGE)
1327 printf("RS: init_slot: too many I/O ranges requested\n");
1328 return EINVAL;
1330 rp->r_priv.s_nr_io_range= rs_start->rss_nr_io;
1331 for (i= 0; i<rp->r_priv.s_nr_io_range; i++)
1333 rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base;
1334 rp->r_priv.s_io_tab[i].ior_limit=
1335 rs_start->rss_io[i].base+rs_start->rss_io[i].len-1;
1336 if(rs_verbose)
1337 printf("RS: init_slot: I/O [%x..%x]\n",
1338 rp->r_priv.s_io_tab[i].ior_base,
1339 rp->r_priv.s_io_tab[i].ior_limit);
1342 if (rs_start->rss_nr_pci_id > RS_NR_PCI_DEVICE)
1344 printf("RS: init_slot: too many PCI device IDs\n");
1345 return EINVAL;
1347 rpub->pci_acl.rsp_nr_device = rs_start->rss_nr_pci_id;
1348 for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++)
1350 rpub->pci_acl.rsp_device[i].vid= rs_start->rss_pci_id[i].vid;
1351 rpub->pci_acl.rsp_device[i].did= rs_start->rss_pci_id[i].did;
1352 if(rs_verbose)
1353 printf("RS: init_slot: PCI %04x/%04x\n",
1354 rpub->pci_acl.rsp_device[i].vid,
1355 rpub->pci_acl.rsp_device[i].did);
1357 if (rs_start->rss_nr_pci_class > RS_NR_PCI_CLASS)
1359 printf("RS: init_slot: too many PCI class IDs\n");
1360 return EINVAL;
1362 rpub->pci_acl.rsp_nr_class= rs_start->rss_nr_pci_class;
1363 for (i= 0; i<rpub->pci_acl.rsp_nr_class; i++)
1365 rpub->pci_acl.rsp_class[i].class= rs_start->rss_pci_class[i].class;
1366 rpub->pci_acl.rsp_class[i].mask= rs_start->rss_pci_class[i].mask;
1367 if(rs_verbose)
1368 printf("RS: init_slot: PCI class %06x mask %06x\n",
1369 (unsigned int) rpub->pci_acl.rsp_class[i].class,
1370 (unsigned int) rpub->pci_acl.rsp_class[i].mask);
1373 /* Copy kernel call mask. Inherit basic kernel calls. */
1374 memcpy(rp->r_priv.s_k_call_mask, rs_start->rss_system,
1375 sizeof(rp->r_priv.s_k_call_mask));
1376 fill_call_mask(basic_kc, NR_SYS_CALLS,
1377 rp->r_priv.s_k_call_mask, KERNEL_CALL, FALSE);
1379 /* Device driver properties. */
1380 rpub->dev_flags = DSRV_DF;
1381 rpub->dev_nr = rs_start->rss_major;
1382 rpub->dev_style = rs_start->rss_dev_style;
1383 if(rpub->dev_nr && !IS_DEV_STYLE(rs_start->rss_dev_style)) {
1384 printf("RS: init_slot: bad device style\n");
1385 return EINVAL;
1387 rpub->dev_style2 = STYLE_NDEV;
1389 /* Initialize some fields. */
1390 rpub->period = rs_start->rss_period;
1391 rp->r_restarts = 0; /* no restarts yet */
1392 rp->r_set_resources= 1; /* set resources */
1393 rp->r_old_rp = NULL; /* no old version yet */
1394 rp->r_new_rp = NULL; /* no new version yet */
1395 rp->r_prev_rp = NULL; /* no prev replica yet */
1396 rp->r_next_rp = NULL; /* no next replica yet */
1398 /* Copy VM call mask. Inherit basic VM calls. */
1399 memcpy(rpub->vm_call_mask, rs_start->rss_vm,
1400 sizeof(rpub->vm_call_mask));
1401 fill_call_mask(basic_vmc, NR_VM_CALLS,
1402 rpub->vm_call_mask, VM_RQ_BASE, FALSE);
1404 return OK;
1407 /*===========================================================================*
1408 * clone_slot *
1409 *===========================================================================*/
1410 PUBLIC int clone_slot(rp, clone_rpp)
1411 struct rproc *rp;
1412 struct rproc **clone_rpp;
1414 int r;
1415 struct rproc *clone_rp;
1416 struct rprocpub *rpub, *clone_rpub;
1418 /* Allocate a system service slot for the clone. */
1419 r = alloc_slot(&clone_rp);
1420 if(r != OK) {
1421 printf("RS: clone_slot: unable to allocate a new slot: %d\n", r);
1422 return r;
1425 rpub = rp->r_pub;
1426 clone_rpub = clone_rp->r_pub;
1428 /* Shallow copy. */
1429 *clone_rp = *rp;
1430 *clone_rpub = *rpub;
1432 /* Deep copy. */
1433 clone_rp->r_flags &= ~RS_ACTIVE; /* the clone is not active yet */
1434 clone_rp->r_pid = -1; /* no pid yet */
1435 clone_rpub->endpoint = -1; /* no endpoint yet */
1436 clone_rp->r_pub = clone_rpub; /* restore pointer to public entry */
1437 build_cmd_dep(clone_rp); /* rebuild cmd dependencies */
1438 if(clone_rpub->sys_flags & SF_USE_COPY) {
1439 share_exec(clone_rp, rp); /* share exec image */
1442 /* Force dynamic privilege id. */
1443 clone_rp->r_priv.s_flags |= DYN_PRIV_ID;
1445 *clone_rpp = clone_rp;
1446 return OK;
1449 /*===========================================================================*
1450 * swap_slot_pointer *
1451 *===========================================================================*/
1452 PRIVATE void swap_slot_pointer(struct rproc **rpp, struct rproc *src_rp,
1453 struct rproc *dst_rp)
1455 if(*rpp == src_rp) {
1456 *rpp = dst_rp;
1458 else if(*rpp == dst_rp) {
1459 *rpp = src_rp;
1463 /*===========================================================================*
1464 * swap_slot *
1465 *===========================================================================*/
1466 PUBLIC void swap_slot(src_rpp, dst_rpp)
1467 struct rproc **src_rpp;
1468 struct rproc **dst_rpp;
1470 /* Swap two service slots. */
1471 struct rproc *src_rp;
1472 struct rproc *dst_rp;
1473 struct rprocpub *src_rpub;
1474 struct rprocpub *dst_rpub;
1475 struct rproc orig_src_rproc, orig_dst_rproc;
1476 struct rprocpub orig_src_rprocpub, orig_dst_rprocpub;
1478 src_rp = *src_rpp;
1479 dst_rp = *dst_rpp;
1480 src_rpub = src_rp->r_pub;
1481 dst_rpub = dst_rp->r_pub;
1483 /* Save existing data first. */
1484 orig_src_rproc = *src_rp;
1485 orig_src_rprocpub = *src_rpub;
1486 orig_dst_rproc = *dst_rp;
1487 orig_dst_rprocpub = *dst_rpub;
1489 /* Swap slots. */
1490 *src_rp = orig_dst_rproc;
1491 *src_rpub = orig_dst_rprocpub;
1492 *dst_rp = orig_src_rproc;
1493 *dst_rpub = orig_src_rprocpub;
1495 /* Restore public entries. */
1496 src_rp->r_pub = orig_src_rproc.r_pub;
1497 dst_rp->r_pub = orig_dst_rproc.r_pub;
1499 /* Rebuild command dependencies. */
1500 build_cmd_dep(src_rp);
1501 build_cmd_dep(dst_rp);
1503 /* Swap local slot pointers. */
1504 swap_slot_pointer(&src_rp->r_prev_rp, src_rp, dst_rp);
1505 swap_slot_pointer(&src_rp->r_next_rp, src_rp, dst_rp);
1506 swap_slot_pointer(&src_rp->r_old_rp, src_rp, dst_rp);
1507 swap_slot_pointer(&src_rp->r_new_rp, src_rp, dst_rp);
1508 swap_slot_pointer(&dst_rp->r_prev_rp, src_rp, dst_rp);
1509 swap_slot_pointer(&dst_rp->r_next_rp, src_rp, dst_rp);
1510 swap_slot_pointer(&dst_rp->r_old_rp, src_rp, dst_rp);
1511 swap_slot_pointer(&dst_rp->r_new_rp, src_rp, dst_rp);
1513 /* Swap global slot pointers. */
1514 swap_slot_pointer(&rupdate.rp, src_rp, dst_rp);
1515 swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)],
1516 src_rp, dst_rp);
1517 swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)],
1518 src_rp, dst_rp);
1520 /* Adjust input pointers. */
1521 *src_rpp = dst_rp;
1522 *dst_rpp = src_rp;
1525 /*===========================================================================*
1526 * lookup_slot_by_label *
1527 *===========================================================================*/
1528 PUBLIC struct rproc* lookup_slot_by_label(char *label)
1530 /* Lookup a service slot matching the given label. */
1531 int slot_nr;
1532 struct rproc *rp;
1533 struct rprocpub *rpub;
1535 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1536 rp = &rproc[slot_nr];
1537 if (!(rp->r_flags & RS_ACTIVE)) {
1538 continue;
1540 rpub = rp->r_pub;
1541 if (strcmp(rpub->label, label) == 0) {
1542 return rp;
1546 return NULL;
1549 /*===========================================================================*
1550 * lookup_slot_by_pid *
1551 *===========================================================================*/
1552 PUBLIC struct rproc* lookup_slot_by_pid(pid_t pid)
1554 /* Lookup a service slot matching the given pid. */
1555 int slot_nr;
1556 struct rproc *rp;
1558 if(pid < 0) {
1559 return NULL;
1562 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1563 rp = &rproc[slot_nr];
1564 if (!(rp->r_flags & RS_IN_USE)) {
1565 continue;
1567 if (rp->r_pid == pid) {
1568 return rp;
1572 return NULL;
1575 /*===========================================================================*
1576 * lookup_slot_by_dev_nr *
1577 *===========================================================================*/
1578 PUBLIC struct rproc* lookup_slot_by_dev_nr(dev_t dev_nr)
1580 /* Lookup a service slot matching the given device number. */
1581 int slot_nr;
1582 struct rproc *rp;
1583 struct rprocpub *rpub;
1585 if(dev_nr <= 0) {
1586 return NULL;
1589 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1590 rp = &rproc[slot_nr];
1591 rpub = rp->r_pub;
1592 if (!(rp->r_flags & RS_IN_USE)) {
1593 continue;
1595 if (rpub->dev_nr == dev_nr) {
1596 return rp;
1600 return NULL;
1603 /*===========================================================================*
1604 * alloc_slot *
1605 *===========================================================================*/
1606 PUBLIC int alloc_slot(rpp)
1607 struct rproc **rpp;
1609 /* Alloc a new system service slot. */
1610 int slot_nr;
1612 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1613 *rpp = &rproc[slot_nr]; /* get pointer to slot */
1614 if (!((*rpp)->r_flags & RS_IN_USE)) /* check if available */
1615 break;
1617 if (slot_nr >= NR_SYS_PROCS) {
1618 return ENOMEM;
1621 return OK;
1624 /*===========================================================================*
1625 * free_slot *
1626 *===========================================================================*/
1627 PUBLIC void free_slot(rp)
1628 struct rproc *rp;
1630 /* Free a system service slot. */
1631 struct rprocpub *rpub;
1633 rpub = rp->r_pub;
1635 /* Send a late reply if there is any pending. */
1636 late_reply(rp, OK);
1638 /* Free memory if necessary. */
1639 if(rpub->sys_flags & SF_USE_COPY) {
1640 free_exec(rp);
1643 /* Mark slot as no longer in use.. */
1644 rp->r_flags = 0;
1645 rp->r_pid = -1;
1646 rpub->in_use = FALSE;
1647 rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
1651 /*===========================================================================*
1652 * get_next_label *
1653 *===========================================================================*/
1654 PUBLIC char *get_next_label(ptr, label, caller_label)
1655 char *ptr;
1656 char *label;
1657 char *caller_label;
1659 /* Get the next label from the list of (IPC) labels.
1661 char *p, *q;
1662 size_t len;
1664 for (p= ptr; p[0] != '\0'; p= q)
1666 /* Skip leading space */
1667 while (p[0] != '\0' && isspace((unsigned char)p[0]))
1668 p++;
1670 /* Find start of next word */
1671 q= p;
1672 while (q[0] != '\0' && !isspace((unsigned char)q[0]))
1673 q++;
1674 if (q == p)
1675 continue;
1676 len= q-p;
1677 if (len > RS_MAX_LABEL_LEN)
1679 printf(
1680 "rs:get_next_label: bad ipc list entry '%.*s' for %s: too long\n",
1681 len, p, caller_label);
1682 continue;
1684 memcpy(label, p, len);
1685 label[len]= '\0';
1687 return q; /* found another */
1690 return NULL; /* done */
1693 /*===========================================================================*
1694 * add_forward_ipc *
1695 *===========================================================================*/
1696 PUBLIC void add_forward_ipc(rp, privp)
1697 struct rproc *rp;
1698 struct priv *privp;
1700 /* Add IPC send permissions to a process based on that process's IPC
1701 * list.
1703 char label[RS_MAX_LABEL_LEN+1], *p;
1704 struct rproc *tmp_rp;
1705 struct rprocpub *tmp_rpub;
1706 endpoint_t endpoint;
1707 int r;
1708 int priv_id;
1709 struct priv priv;
1710 struct rprocpub *rpub;
1712 rpub = rp->r_pub;
1713 p = rp->r_ipc_list;
1715 while ((p = get_next_label(p, label, rpub->label)) != NULL) {
1717 if (strcmp(label, "SYSTEM") == 0)
1718 endpoint= SYSTEM;
1719 else if (strcmp(label, "USER") == 0)
1720 endpoint= INIT_PROC_NR; /* all user procs */
1721 else if (strcmp(label, "PM") == 0)
1722 endpoint= PM_PROC_NR;
1723 else if (strcmp(label, "VFS") == 0)
1724 endpoint= FS_PROC_NR;
1725 else if (strcmp(label, "RS") == 0)
1726 endpoint= RS_PROC_NR;
1727 else if (strcmp(label, "LOG") == 0)
1728 endpoint= LOG_PROC_NR;
1729 else if (strcmp(label, "TTY") == 0)
1730 endpoint= TTY_PROC_NR;
1731 else if (strcmp(label, "DS") == 0)
1732 endpoint= DS_PROC_NR;
1733 else if (strcmp(label, "VM") == 0)
1734 endpoint= VM_PROC_NR;
1735 else
1737 /* Try to find process */
1738 tmp_rp = lookup_slot_by_label(label);
1739 if (!tmp_rp)
1740 continue;
1741 tmp_rpub = tmp_rp->r_pub;
1742 endpoint= tmp_rpub->endpoint;
1745 if ((r = sys_getpriv(&priv, endpoint)) < 0)
1747 printf(
1748 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1749 label, r);
1750 continue;
1752 priv_id= priv.s_id;
1753 set_sys_bit(privp->s_ipc_to, priv_id);
1758 /*===========================================================================*
1759 * add_backward_ipc *
1760 *===========================================================================*/
1761 PUBLIC void add_backward_ipc(rp, privp)
1762 struct rproc *rp;
1763 struct priv *privp;
1765 /* Add IPC send permissions to a process based on other processes' IPC
1766 * lists. This is enough to allow each such two processes to talk to
1767 * each other, as the kernel guarantees send mask symmetry. We need to
1768 * add these permissions now because the current process may not yet
1769 * have existed at the time that the other process was initialized.
1771 char label[RS_MAX_LABEL_LEN+1], *p;
1772 struct rproc *rrp;
1773 struct rprocpub *rrpub;
1774 int priv_id, found;
1776 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
1777 if (!(rrp->r_flags & RS_IN_USE))
1778 continue;
1780 /* If an IPC target list was provided for the process being
1781 * checked here, make sure that the label of the new process
1782 * is in that process's list.
1784 if (rrp->r_ipc_list[0]) {
1785 found = 0;
1787 rrpub = rrp->r_pub;
1788 p = rrp->r_ipc_list;
1790 while ((p = get_next_label(p, label,
1791 rrpub->label)) != NULL) {
1792 if (!strcmp(rrpub->label, label)) {
1793 found = 1;
1794 break;
1798 if (!found)
1799 continue;
1802 priv_id= rrp->r_priv.s_id;
1804 set_sys_bit(privp->s_ipc_to, priv_id);
1809 /*===========================================================================*
1810 * init_privs *
1811 *===========================================================================*/
1812 PUBLIC void init_privs(rp, privp)
1813 struct rproc *rp;
1814 struct priv *privp;
1816 int i;
1818 /* Clear s_ipc_to */
1819 memset(&privp->s_ipc_to, '\0', sizeof(privp->s_ipc_to));
1821 if (strlen(rp->r_ipc_list) != 0)
1823 add_forward_ipc(rp, privp);
1824 add_backward_ipc(rp, privp);
1827 else
1829 for (i= 0; i<NR_SYS_PROCS; i++)
1831 if (i != USER_PRIV_ID)
1832 set_sys_bit(privp->s_ipc_to, i);