- Fixed a bug when running out of priv structures.
[minix.git] / servers / rs / manager.c
blobc20bc3bbc23291de1cdd240b06885fe02af823ef
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 cleanup_service(rp);
465 return ENOMEM;
468 /* Copy the executable image into the child process. If this call
469 * fails, the child process may or may not be killed already. If it is
470 * not killed, it's blocked because of NO_PRIV. Kill it now either way.
471 * If no copy exists, allocate one and free it right after exec completes.
473 if(use_copy) {
474 if(rs_verbose)
475 printf("RS: %s uses an in-memory copy\n",
476 srv_to_string(rp));
478 else {
479 if ((s = read_exec(rp)) != OK) {
480 printf("read_exec failed: %d\n", s);
481 cleanup_service(rp);
482 return s;
485 if(rs_verbose)
486 printf("RS: execing child with srv_execve()...\n");
487 s = srv_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
488 environ);
490 if (s != OK) {
491 printf("srv_execve failed: %d\n", s);
492 cleanup_service(rp);
493 return s;
495 if(!use_copy) {
496 free_exec(rp);
499 /* The purpose of non-blocking forks is to avoid involving VFS in the forking
500 * process, because VFS may be blocked on a sendrec() to a MFS that is
501 * waiting for a endpoint update for a dead driver. We have just published
502 * that update, but VFS may still be blocked. As a result, VFS may not yet
503 * have received PM's fork message. Hence, if we call mapdriver()
504 * immediately, VFS may not know about the process and thus refuse to add the
505 * driver entry. The following temporary hack works around this by forcing
506 * blocking communication from PM to VFS. Once VFS has been made non-blocking
507 * towards MFS instances, this hack and the big part of srv_fork() can go.
509 setuid(0);
511 if(rs_verbose)
512 printf("RS: %s created\n", srv_to_string(rp));
514 return OK;
517 /*===========================================================================*
518 * clone_service *
519 *===========================================================================*/
520 PUBLIC int clone_service(rp)
521 struct rproc *rp;
523 /* Clone the given system service instance. */
524 struct rproc *replica_rp;
525 struct rprocpub *replica_rpub;
526 int r;
528 if(rs_verbose)
529 printf("RS: creating a replica for %s\n", srv_to_string(rp));
531 /* Clone slot. */
532 if((r = clone_slot(rp, &replica_rp)) != OK) {
533 return r;
536 /* Link the two slots. */
537 rp->r_next_rp = replica_rp;
538 replica_rp->r_prev_rp = rp;
540 /* Create a new replica of the service. */
541 r = create_service(replica_rp);
542 if(r != OK) {
543 rp->r_next_rp = NULL;
544 return r;
547 /* Tell VM about allowed calls, if any. */
548 replica_rpub = replica_rp->r_pub;
549 if(replica_rpub->vm_call_mask[0]) {
550 r = vm_set_priv(replica_rpub->endpoint, &replica_rpub->vm_call_mask[0]);
551 if (r != OK) {
552 rp->r_next_rp = NULL;
553 return kill_service(replica_rp, "vm_set_priv call failed", r);
557 return OK;
560 /*===========================================================================*
561 * publish_service *
562 *===========================================================================*/
563 PUBLIC int publish_service(rp)
564 struct rproc *rp; /* pointer to service slot */
566 /* Publish a service. */
567 int r;
568 struct rprocpub *rpub;
569 struct rs_pci pci_acl;
571 rpub = rp->r_pub;
573 /* Register label with DS. */
574 r = ds_publish_label(rpub->label, rpub->endpoint, DSF_OVERWRITE);
575 if (r != OK) {
576 return kill_service(rp, "ds_publish_label call failed", r);
579 /* If the service is a driver, map it. */
580 if (rpub->dev_nr > 0) {
581 if (mapdriver(rpub->label, rpub->dev_nr, rpub->dev_style,
582 rpub->dev_flags) != OK) {
583 return kill_service(rp, "couldn't map driver", errno);
587 /* Tell VM about allowed calls, if any. */
588 if(rpub->vm_call_mask[0]) {
589 r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0]);
590 if (r != OK) {
591 return kill_service(rp, "vm_set_priv call failed", r);
595 /* If PCI properties are set, inform the PCI driver about the new service. */
596 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
597 pci_acl = rpub->pci_acl;
598 strcpy(pci_acl.rsp_label, rpub->label);
599 pci_acl.rsp_endpoint= rpub->endpoint;
601 r = pci_set_acl(&pci_acl);
602 if (r != OK) {
603 return kill_service(rp, "pci_set_acl call failed", r);
607 if(rs_verbose)
608 printf("RS: %s published\n", srv_to_string(rp));
610 return OK;
613 /*===========================================================================*
614 * unpublish_service *
615 *===========================================================================*/
616 PUBLIC int unpublish_service(rp)
617 struct rproc *rp; /* pointer to service slot */
619 /* Unpublish a service. */
620 struct rprocpub *rpub;
621 int r, result;
623 rpub = rp->r_pub;
624 result = OK;
626 /* Unregister label with DS. */
627 r = ds_delete_label(rpub->label);
628 if (r != OK && !shutting_down) {
629 printf("RS: ds_delete_label call failed (error %d)\n", r);
630 result = r;
633 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
635 /* If PCI properties are set, inform the PCI driver. */
636 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
637 r = pci_del_acl(rpub->endpoint);
638 if (r != OK && !shutting_down) {
639 printf("RS: pci_del_acl call failed (error %d)\n", r);
640 result = r;
644 if(rs_verbose)
645 printf("RS: %s unpublished\n", srv_to_string(rp));
647 return result;
650 /*===========================================================================*
651 * run_service *
652 *===========================================================================*/
653 PUBLIC int run_service(rp, init_type)
654 struct rproc *rp;
655 int init_type;
657 /* Let a newly created service run. */
658 int s, use_copy;
659 struct rprocpub *rpub;
661 rpub = rp->r_pub;
662 use_copy= (rpub->sys_flags & SF_USE_COPY);
664 /* Allow the service to run. */
665 if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
666 return kill_service(rp, "unable to allow the service to run",s);
669 /* Initialize service. */
670 if((s = init_service(rp, init_type)) != OK) {
671 return kill_service(rp, "unable to initialize service", s);
674 if(rs_verbose)
675 printf("RS: %s allowed to run\n", srv_to_string(rp));
677 return OK;
680 /*===========================================================================*
681 * start_service *
682 *===========================================================================*/
683 PUBLIC int start_service(rp)
684 struct rproc *rp;
686 /* Start a system service. */
687 int r, init_type;
688 struct rprocpub *rpub;
690 rpub = rp->r_pub;
692 /* Create and make active. */
693 r = create_service(rp);
694 if(r != OK) {
695 return r;
697 activate_service(rp, NULL);
699 /* Publish service properties. */
700 r = publish_service(rp);
701 if (r != OK) {
702 return r;
705 /* Run. */
706 init_type = SEF_INIT_FRESH;
707 r = run_service(rp, init_type);
708 if(r != OK) {
709 return r;
712 if(rs_verbose)
713 printf("RS: %s started with major %d\n", srv_to_string(rp),
714 rpub->dev_nr);
716 return OK;
719 /*===========================================================================*
720 * stop_service *
721 *===========================================================================*/
722 PUBLIC void stop_service(struct rproc *rp,int how)
724 struct rprocpub *rpub;
726 rpub = rp->r_pub;
728 /* Try to stop the system service. First send a SIGTERM signal to ask the
729 * system service to terminate. If the service didn't install a signal
730 * handler, it will be killed. If it did and ignores the signal, we'll
731 * find out because we record the time here and send a SIGKILL.
733 if(rs_verbose)
734 printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp));
736 rp->r_flags |= how; /* what to on exit? */
737 sys_kill(rpub->endpoint, SIGTERM); /* first try friendly */
738 getuptime(&rp->r_stop_tm); /* record current time */
741 /*===========================================================================*
742 * update_service *
743 *===========================================================================*/
744 PUBLIC int update_service(src_rpp, dst_rpp)
745 struct rproc **src_rpp;
746 struct rproc **dst_rpp;
748 /* Update an existing service. */
749 int r;
750 struct rproc *src_rp;
751 struct rproc *dst_rp;
752 struct rprocpub *src_rpub;
753 struct rprocpub *dst_rpub;
754 int pid;
755 endpoint_t endpoint;
757 src_rp = *src_rpp;
758 dst_rp = *dst_rpp;
759 src_rpub = src_rp->r_pub;
760 dst_rpub = dst_rp->r_pub;
762 if(rs_verbose)
763 printf("RS: %s updating into %s\n",
764 srv_to_string(src_rp), srv_to_string(dst_rp));
766 /* Swap the slots of the two processes. */
767 r = srv_update(src_rpub->endpoint, dst_rpub->endpoint);
768 if(r != OK) {
769 return r;
772 /* Swap slots here as well. */
773 pid = src_rp->r_pid;
774 endpoint = src_rpub->endpoint;
775 swap_slot(&src_rp, &dst_rp);
777 /* Reassign pids and endpoints. */
778 src_rp->r_pid = dst_rp->r_pid;
779 src_rp->r_pub->endpoint = dst_rp->r_pub->endpoint;
780 rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)] = src_rp;
781 dst_rp->r_pid = pid;
782 dst_rp->r_pub->endpoint = endpoint;
783 rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)] = dst_rp;
785 /* Adjust input pointers. */
786 *src_rpp = src_rp;
787 *dst_rpp = dst_rp;
789 /* Make the new version active. */
790 activate_service(dst_rp, src_rp);
792 if(rs_verbose)
793 printf("RS: %s updated into %s\n",
794 srv_to_string(src_rp), srv_to_string(dst_rp));
796 return OK;
799 /*===========================================================================*
800 * activate_service *
801 *===========================================================================*/
802 PUBLIC void activate_service(struct rproc *rp, struct rproc *ex_rp)
804 /* Activate a service instance and deactivate another one if requested. */
806 if(ex_rp && (ex_rp->r_flags & RS_ACTIVE) ) {
807 ex_rp->r_flags &= ~RS_ACTIVE;
808 if(rs_verbose)
809 printf("RS: %s becomes inactive\n", srv_to_string(ex_rp));
812 if(! (rp->r_flags & RS_ACTIVE) ) {
813 rp->r_flags |= RS_ACTIVE;
814 if(rs_verbose)
815 printf("RS: %s becomes active\n", srv_to_string(rp));
819 /*===========================================================================*
820 * terminate_service *
821 *===========================================================================*/
822 PUBLIC void terminate_service(struct rproc *rp)
824 /* Handle a termination event for a system service. */
825 struct rproc **rps;
826 struct rprocpub *rpub;
827 int nr_rps;
828 int i, r;
830 rpub = rp->r_pub;
832 if(rs_verbose)
833 printf("RS: %s terminated\n", srv_to_string(rp));
835 /* Deal with failures during initialization. */
836 if(rp->r_flags & RS_INITIALIZING) {
837 printf("RS: service '%s' exited during initialization\n", rpub->label);
838 rp->r_flags |= RS_EXITING; /* don't restart. */
839 sys_sysctl_stacktrace(rp->r_pub->endpoint);
841 /* If updating, rollback. */
842 if(rp->r_flags & RS_UPDATING) {
843 message m;
844 struct rproc *old_rp, *new_rp;
845 printf("RS: update failed: state transfer failed. Rolling back...\n");
846 new_rp = rp;
847 old_rp = new_rp->r_old_rp;
848 new_rp->r_flags &= ~RS_INITIALIZING;
849 update_service(&new_rp, &old_rp); /* can't fail */
850 m.m_type = ERESTART;
851 reply(old_rp->r_pub->endpoint, &m);
852 end_update(ERESTART);
853 return;
857 if (rp->r_flags & RS_EXITING) {
858 /* If a core system service is exiting, we are in trouble. */
859 if (rp->r_pub->sys_flags & SF_CORE_SRV && !shutting_down) {
860 panic("core system service died: %s", srv_to_string(rp));
863 /* See if a late reply has to be sent. */
864 r = (rp->r_caller_request == RS_DOWN ? OK : EDEADSRCDST);
865 late_reply(rp, r);
867 /* Unpublish the service. */
868 unpublish_service(rp);
870 /* Cleanup all the instances of the service. */
871 get_service_instances(rp, &rps, &nr_rps);
872 for(i=0;i<nr_rps;i++) {
873 cleanup_service(rps[i]);
876 else if(rp->r_flags & RS_REFRESHING) {
877 /* Restart service. */
878 restart_service(rp);
880 else {
881 /* If an update is in progress, end it. The old version
882 * that just exited will continue executing.
884 if(rp->r_flags & RS_UPDATING) {
885 end_update(ERESTART);
888 /* Determine what to do. If this is the first unexpected
889 * exit, immediately restart this service. Otherwise use
890 * a binary exponential backoff.
892 if (rp->r_restarts > 0) {
893 rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
894 rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
895 if ((rpub->sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
896 rp->r_backoff= 1;
897 return;
900 /* Restart service. */
901 restart_service(rp);
905 /*===========================================================================*
906 * run_script *
907 *===========================================================================*/
908 PRIVATE int run_script(struct rproc *rp)
910 int r, endpoint;
911 pid_t pid;
912 char *reason;
913 char incarnation_str[20]; /* Enough for a counter? */
914 char *envp[1] = { NULL };
915 struct rprocpub *rpub;
917 rpub = rp->r_pub;
918 if (rp->r_flags & RS_REFRESHING)
919 reason= "restart";
920 else if (rp->r_flags & RS_NOPINGREPLY)
921 reason= "no-heartbeat";
922 else reason= "terminated";
923 sprintf(incarnation_str, "%d", rp->r_restarts);
925 if(rs_verbose) {
926 printf("RS: %s:\n", srv_to_string(rp));
927 printf("RS: calling script '%s'\n", rp->r_script);
928 printf("RS: reason: '%s'\n", reason);
929 printf("RS: incarnation: '%s'\n", incarnation_str);
932 pid= fork();
933 switch(pid)
935 case -1:
936 return kill_service(rp, "unable to fork script", errno);
937 case 0:
938 execle(rp->r_script, rp->r_script, rpub->label, reason,
939 incarnation_str, (char*) NULL, envp);
940 printf("RS: run_script: execl '%s' failed: %s\n",
941 rp->r_script, strerror(errno));
942 exit(1);
943 default:
944 /* Set the privilege structure for the child process. */
945 endpoint = getnprocnr(pid);
946 if ((r = sys_privctl(endpoint, SYS_PRIV_SET_USER, NULL))
947 != OK) {
948 return kill_service(rp,"can't set script privileges",r);
950 /* Allow the script to run. */
951 if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
952 return kill_service(rp,"can't let the script run",r);
955 return OK;
958 /*===========================================================================*
959 * restart_service *
960 *===========================================================================*/
961 PUBLIC void restart_service(struct rproc *rp)
963 /* Restart service via a recovery script or directly. */
964 struct rproc *replica_rp;
965 int r;
967 /* See if a late reply has to be sent. */
968 late_reply(rp, OK);
970 /* Run a recovery script if available. */
971 if (rp->r_script[0] != '\0') {
972 run_script(rp);
973 return;
976 /* Restart directly. We need a replica if not already available. */
977 if(rp->r_next_rp == NULL) {
978 /* Create the replica. */
979 r = clone_service(rp);
980 if(r != OK) {
981 kill_service(rp, "unable to clone service", r);
982 return;
985 replica_rp = rp->r_next_rp;
987 /* Update the service into the replica. */
988 r = update_service(&rp, &replica_rp);
989 if(r != OK) {
990 kill_service(rp, "unable to update into new replica", r);
991 return;
994 /* Let the new replica run. */
995 r = run_service(replica_rp, SEF_INIT_RESTART);
996 if(r != OK) {
997 kill_service(rp, "unable to let the replica run", r);
998 return;
1001 /* Increase the number of restarts. */
1002 replica_rp->r_restarts += 1;
1004 if(rs_verbose)
1005 printf("RS: %s restarted into %s\n",
1006 srv_to_string(rp), srv_to_string(replica_rp));
1009 /*===========================================================================*
1010 * inherit_service_defaults *
1011 *===========================================================================*/
1012 PUBLIC void inherit_service_defaults(def_rp, rp)
1013 struct rproc *def_rp;
1014 struct rproc *rp;
1016 struct rprocpub *def_rpub;
1017 struct rprocpub *rpub;
1019 def_rpub = def_rp->r_pub;
1020 rpub = rp->r_pub;
1022 /* Device settings. These properties cannot change. */
1023 rpub->dev_flags = def_rpub->dev_flags;
1024 rpub->dev_nr = def_rpub->dev_nr;
1025 rpub->dev_style = def_rpub->dev_style;
1026 rpub->dev_style2 = def_rpub->dev_style2;
1028 /* Period. */
1029 if(!rpub->period && def_rpub->period) {
1030 rpub->period = def_rpub->period;
1034 /*===========================================================================*
1035 * get_service_instances *
1036 *===========================================================================*/
1037 PUBLIC void get_service_instances(rp, rps, length)
1038 struct rproc *rp;
1039 struct rproc ***rps;
1040 int *length;
1042 /* Retrieve all the service instances of a give service. */
1043 static struct rproc *instances[5];
1044 int nr_instances;
1046 nr_instances = 0;
1047 instances[nr_instances++] = rp;
1048 if(rp->r_prev_rp) instances[nr_instances++] = rp->r_prev_rp;
1049 if(rp->r_next_rp) instances[nr_instances++] = rp->r_next_rp;
1050 if(rp->r_old_rp) instances[nr_instances++] = rp->r_old_rp;
1051 if(rp->r_new_rp) instances[nr_instances++] = rp->r_new_rp;
1053 *rps = instances;
1054 *length = nr_instances;
1057 /*===========================================================================*
1058 * share_exec *
1059 *===========================================================================*/
1060 PUBLIC void share_exec(rp_dst, rp_src)
1061 struct rproc *rp_dst, *rp_src;
1063 struct rprocpub *rpub_src;
1064 struct rprocpub *rpub_dst;
1066 rpub_src = rp_src->r_pub;
1067 rpub_dst = rp_dst->r_pub;
1069 if(rs_verbose)
1070 printf("RS: %s shares exec image with %s\n",
1071 srv_to_string(rp_dst), srv_to_string(rp_src));
1073 /* Share exec image from rp_src to rp_dst. */
1074 rp_dst->r_exec_len = rp_src->r_exec_len;
1075 rp_dst->r_exec = rp_src->r_exec;
1078 /*===========================================================================*
1079 * read_exec *
1080 *===========================================================================*/
1081 PUBLIC int read_exec(rp)
1082 struct rproc *rp;
1084 int e, r, fd;
1085 char *e_name;
1086 struct stat sb;
1088 e_name= rp->r_argv[0];
1089 if(rs_verbose)
1090 printf("RS: service '%s' reads exec image from: %s\n", rp->r_pub->label,
1091 e_name);
1093 r= stat(e_name, &sb);
1094 if (r != 0)
1095 return -errno;
1097 fd= open(e_name, O_RDONLY);
1098 if (fd == -1)
1099 return -errno;
1101 rp->r_exec_len= sb.st_size;
1102 rp->r_exec= malloc(rp->r_exec_len);
1103 if (rp->r_exec == NULL)
1105 printf("RS: read_exec: unable to allocate %d bytes\n",
1106 rp->r_exec_len);
1107 close(fd);
1108 return ENOMEM;
1111 r= read(fd, rp->r_exec, rp->r_exec_len);
1112 e= errno;
1113 close(fd);
1114 if (r == rp->r_exec_len)
1115 return OK;
1117 printf("RS: read_exec: read failed %d, errno %d\n", r, e);
1119 free_exec(rp);
1121 if (r >= 0)
1122 return EIO;
1123 else
1124 return -e;
1127 /*===========================================================================*
1128 * free_exec *
1129 *===========================================================================*/
1130 PUBLIC void free_exec(rp)
1131 struct rproc *rp;
1133 /* Free an exec image. */
1134 int slot_nr, has_shared_exec, is_boot_image_mem;
1135 struct rproc *other_rp;
1137 /* Search for some other slot sharing the same exec image. */
1138 has_shared_exec = FALSE;
1139 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1140 other_rp = &rproc[slot_nr]; /* get pointer to slot */
1141 if (other_rp->r_flags & RS_IN_USE && other_rp != rp
1142 && other_rp->r_exec == rp->r_exec) { /* found! */
1143 has_shared_exec = TRUE;
1144 break;
1148 /* If nobody uses our copy of the exec image, we can try to get rid of it. */
1149 if(!has_shared_exec) {
1150 is_boot_image_mem = (rp->r_exec >= boot_image_buffer
1151 && rp->r_exec < boot_image_buffer + boot_image_buffer_size);
1153 /* Free memory only if not part of the boot image buffer. */
1154 if(is_boot_image_mem) {
1155 if(rs_verbose)
1156 printf("RS: %s has exec image in the boot image buffer\n",
1157 srv_to_string(rp));
1159 else {
1160 if(rs_verbose)
1161 printf("RS: %s frees exec image\n", srv_to_string(rp));
1162 free(rp->r_exec);
1165 else {
1166 if(rs_verbose)
1167 printf("RS: %s no longer sharing exec image with %s\n",
1168 srv_to_string(rp), srv_to_string(other_rp));
1170 rp->r_exec = NULL;
1171 rp->r_exec_len = 0;
1174 /*===========================================================================*
1175 * init_slot *
1176 *===========================================================================*/
1177 PUBLIC int init_slot(rp, rs_start, source)
1178 struct rproc *rp;
1179 struct rs_start *rs_start;
1180 endpoint_t source;
1182 /* Initialize a slot as requested by the client. */
1183 struct rprocpub *rpub;
1184 char *label; /* unique name of command */
1185 int len; /* length of string */
1186 int i;
1187 int s;
1188 int basic_kc[] = { SYS_BASIC_CALLS, SYS_NULL_C };
1189 int basic_vmc[] = { VM_BASIC_CALLS, SYS_NULL_C };
1191 rpub = rp->r_pub;
1193 /* Obtain command name and parameters. This is a space-separated string
1194 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
1196 if (rs_start->rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
1197 s=sys_datacopy(source, (vir_bytes) rs_start->rss_cmd,
1198 SELF, (vir_bytes) rp->r_cmd, rs_start->rss_cmdlen);
1199 if (s != OK) return(s);
1200 rp->r_cmd[rs_start->rss_cmdlen] = '\0'; /* ensure it is terminated */
1201 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
1203 /* Build cmd dependencies: argv and program name. */
1204 build_cmd_dep(rp);
1206 if(rs_start->rss_label.l_len > 0) {
1207 /* RS_UP caller has supplied a custom label for this service. */
1208 int s = copy_label(source, rs_start->rss_label.l_addr,
1209 rs_start->rss_label.l_len, rpub->label, sizeof(rpub->label));
1210 if(s != OK)
1211 return s;
1212 if(rs_verbose)
1213 printf("RS: init_slot: using label (custom) '%s'\n", rpub->label);
1214 } else {
1215 /* Default label for the service. */
1216 label = rpub->proc_name;
1217 len= strlen(label);
1218 memcpy(rpub->label, label, len);
1219 rpub->label[len]= '\0';
1220 if(rs_verbose)
1221 printf("RS: init_slot: using label (from proc_name) '%s'\n",
1222 rpub->label);
1225 if(rs_start->rss_nr_control > 0) {
1226 int i, s;
1227 if (rs_start->rss_nr_control > RS_NR_CONTROL)
1229 printf("RS: init_slot: too many control labels\n");
1230 return EINVAL;
1232 for (i=0; i<rs_start->rss_nr_control; i++) {
1233 s = copy_label(source, rs_start->rss_control[i].l_addr,
1234 rs_start->rss_control[i].l_len, rp->r_control[i],
1235 sizeof(rp->r_control[i]));
1236 if(s != OK)
1237 return s;
1239 rp->r_nr_control = rs_start->rss_nr_control;
1241 if (rs_verbose) {
1242 printf("RS: init_slot: control labels:");
1243 for (i=0; i<rp->r_nr_control; i++)
1244 printf(" %s", rp->r_control[i]);
1245 printf("\n");
1249 rp->r_script[0]= '\0';
1250 if (rs_start->rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
1251 if (rs_start->rss_script != NULL)
1253 s=sys_datacopy(source, (vir_bytes) rs_start->rss_script,
1254 SELF, (vir_bytes) rp->r_script, rs_start->rss_scriptlen);
1255 if (s != OK) return(s);
1256 rp->r_script[rs_start->rss_scriptlen] = '\0';
1258 rp->r_uid= rs_start->rss_uid;
1259 rp->r_nice= rs_start->rss_nice;
1261 if (rs_start->rss_flags & RSS_IPC_VALID)
1263 if (rs_start->rss_ipclen+1 > sizeof(rp->r_ipc_list))
1265 printf("RS: ipc list too long for '%s'\n", rpub->label);
1266 return EINVAL;
1268 s=sys_datacopy(source, (vir_bytes) rs_start->rss_ipc,
1269 SELF, (vir_bytes) rp->r_ipc_list, rs_start->rss_ipclen);
1270 if (s != OK) return(s);
1271 rp->r_ipc_list[rs_start->rss_ipclen]= '\0';
1273 else
1274 rp->r_ipc_list[0]= '\0';
1276 /* Set system flags. */
1277 rpub->sys_flags = DSRV_SF;
1278 rp->r_exec= NULL;
1279 if (rs_start->rss_flags & RSS_COPY) {
1280 int exst_cpy;
1281 struct rproc *rp2;
1282 struct rprocpub *rpub2;
1283 exst_cpy = 0;
1285 if(rs_start->rss_flags & RSS_REUSE) {
1286 int i;
1288 for(i = 0; i < NR_SYS_PROCS; i++) {
1289 rp2 = &rproc[i];
1290 rpub2 = rproc[i].r_pub;
1291 if(strcmp(rpub->proc_name, rpub2->proc_name) == 0 &&
1292 (rpub2->sys_flags & SF_USE_COPY)) {
1293 /* We have found the same binary that's
1294 * already been copied */
1295 exst_cpy = 1;
1296 break;
1301 s = OK;
1302 if(!exst_cpy)
1303 s = read_exec(rp);
1304 else
1305 share_exec(rp, rp2);
1307 if (s != OK)
1308 return s;
1310 rpub->sys_flags |= SF_USE_COPY;
1312 if (rs_start->rss_flags & RSS_REPLICA) {
1313 rpub->sys_flags |= SF_USE_REPL;
1316 /* All dynamically created services get the same privilege flags, and
1317 * allowed traps, and signal manager. Other privilege settings can be
1318 * specified at runtime. The privilege id is dynamically allocated by
1319 * the kernel.
1321 rp->r_priv.s_flags = DSRV_F; /* privilege flags */
1322 rp->r_priv.s_trap_mask = DSRV_T; /* allowed traps */
1323 rp->r_priv.s_sig_mgr = DSRV_SM; /* signal manager */
1325 /* Copy granted resources */
1326 if (rs_start->rss_nr_irq > NR_IRQ)
1328 printf("RS: init_slot: too many IRQs requested\n");
1329 return EINVAL;
1331 rp->r_priv.s_nr_irq= rs_start->rss_nr_irq;
1332 for (i= 0; i<rp->r_priv.s_nr_irq; i++)
1334 rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i];
1335 if(rs_verbose)
1336 printf("RS: init_slot: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
1339 if (rs_start->rss_nr_io > NR_IO_RANGE)
1341 printf("RS: init_slot: too many I/O ranges requested\n");
1342 return EINVAL;
1344 rp->r_priv.s_nr_io_range= rs_start->rss_nr_io;
1345 for (i= 0; i<rp->r_priv.s_nr_io_range; i++)
1347 rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base;
1348 rp->r_priv.s_io_tab[i].ior_limit=
1349 rs_start->rss_io[i].base+rs_start->rss_io[i].len-1;
1350 if(rs_verbose)
1351 printf("RS: init_slot: I/O [%x..%x]\n",
1352 rp->r_priv.s_io_tab[i].ior_base,
1353 rp->r_priv.s_io_tab[i].ior_limit);
1356 if (rs_start->rss_nr_pci_id > RS_NR_PCI_DEVICE)
1358 printf("RS: init_slot: too many PCI device IDs\n");
1359 return EINVAL;
1361 rpub->pci_acl.rsp_nr_device = rs_start->rss_nr_pci_id;
1362 for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++)
1364 rpub->pci_acl.rsp_device[i].vid= rs_start->rss_pci_id[i].vid;
1365 rpub->pci_acl.rsp_device[i].did= rs_start->rss_pci_id[i].did;
1366 if(rs_verbose)
1367 printf("RS: init_slot: PCI %04x/%04x\n",
1368 rpub->pci_acl.rsp_device[i].vid,
1369 rpub->pci_acl.rsp_device[i].did);
1371 if (rs_start->rss_nr_pci_class > RS_NR_PCI_CLASS)
1373 printf("RS: init_slot: too many PCI class IDs\n");
1374 return EINVAL;
1376 rpub->pci_acl.rsp_nr_class= rs_start->rss_nr_pci_class;
1377 for (i= 0; i<rpub->pci_acl.rsp_nr_class; i++)
1379 rpub->pci_acl.rsp_class[i].class= rs_start->rss_pci_class[i].class;
1380 rpub->pci_acl.rsp_class[i].mask= rs_start->rss_pci_class[i].mask;
1381 if(rs_verbose)
1382 printf("RS: init_slot: PCI class %06x mask %06x\n",
1383 (unsigned int) rpub->pci_acl.rsp_class[i].class,
1384 (unsigned int) rpub->pci_acl.rsp_class[i].mask);
1387 /* Copy kernel call mask. Inherit basic kernel calls. */
1388 memcpy(rp->r_priv.s_k_call_mask, rs_start->rss_system,
1389 sizeof(rp->r_priv.s_k_call_mask));
1390 fill_call_mask(basic_kc, NR_SYS_CALLS,
1391 rp->r_priv.s_k_call_mask, KERNEL_CALL, FALSE);
1393 /* Device driver properties. */
1394 rpub->dev_flags = DSRV_DF;
1395 rpub->dev_nr = rs_start->rss_major;
1396 rpub->dev_style = rs_start->rss_dev_style;
1397 if(rpub->dev_nr && !IS_DEV_STYLE(rs_start->rss_dev_style)) {
1398 printf("RS: init_slot: bad device style\n");
1399 return EINVAL;
1401 rpub->dev_style2 = STYLE_NDEV;
1403 /* Initialize some fields. */
1404 rpub->period = rs_start->rss_period;
1405 rp->r_restarts = 0; /* no restarts yet */
1406 rp->r_set_resources= 1; /* set resources */
1407 rp->r_old_rp = NULL; /* no old version yet */
1408 rp->r_new_rp = NULL; /* no new version yet */
1409 rp->r_prev_rp = NULL; /* no prev replica yet */
1410 rp->r_next_rp = NULL; /* no next replica yet */
1412 /* Copy VM call mask. Inherit basic VM calls. */
1413 memcpy(rpub->vm_call_mask, rs_start->rss_vm,
1414 sizeof(rpub->vm_call_mask));
1415 fill_call_mask(basic_vmc, NR_VM_CALLS,
1416 rpub->vm_call_mask, VM_RQ_BASE, FALSE);
1418 return OK;
1421 /*===========================================================================*
1422 * clone_slot *
1423 *===========================================================================*/
1424 PUBLIC int clone_slot(rp, clone_rpp)
1425 struct rproc *rp;
1426 struct rproc **clone_rpp;
1428 int r;
1429 struct rproc *clone_rp;
1430 struct rprocpub *rpub, *clone_rpub;
1432 /* Allocate a system service slot for the clone. */
1433 r = alloc_slot(&clone_rp);
1434 if(r != OK) {
1435 printf("RS: clone_slot: unable to allocate a new slot: %d\n", r);
1436 return r;
1439 rpub = rp->r_pub;
1440 clone_rpub = clone_rp->r_pub;
1442 /* Shallow copy. */
1443 *clone_rp = *rp;
1444 *clone_rpub = *rpub;
1446 /* Deep copy. */
1447 clone_rp->r_flags &= ~RS_ACTIVE; /* the clone is not active yet */
1448 clone_rp->r_pid = -1; /* no pid yet */
1449 clone_rpub->endpoint = -1; /* no endpoint yet */
1450 clone_rp->r_pub = clone_rpub; /* restore pointer to public entry */
1451 build_cmd_dep(clone_rp); /* rebuild cmd dependencies */
1452 if(clone_rpub->sys_flags & SF_USE_COPY) {
1453 share_exec(clone_rp, rp); /* share exec image */
1456 /* Force dynamic privilege id. */
1457 clone_rp->r_priv.s_flags |= DYN_PRIV_ID;
1459 *clone_rpp = clone_rp;
1460 return OK;
1463 /*===========================================================================*
1464 * swap_slot_pointer *
1465 *===========================================================================*/
1466 PRIVATE void swap_slot_pointer(struct rproc **rpp, struct rproc *src_rp,
1467 struct rproc *dst_rp)
1469 if(*rpp == src_rp) {
1470 *rpp = dst_rp;
1472 else if(*rpp == dst_rp) {
1473 *rpp = src_rp;
1477 /*===========================================================================*
1478 * swap_slot *
1479 *===========================================================================*/
1480 PUBLIC void swap_slot(src_rpp, dst_rpp)
1481 struct rproc **src_rpp;
1482 struct rproc **dst_rpp;
1484 /* Swap two service slots. */
1485 struct rproc *src_rp;
1486 struct rproc *dst_rp;
1487 struct rprocpub *src_rpub;
1488 struct rprocpub *dst_rpub;
1489 struct rproc orig_src_rproc, orig_dst_rproc;
1490 struct rprocpub orig_src_rprocpub, orig_dst_rprocpub;
1492 src_rp = *src_rpp;
1493 dst_rp = *dst_rpp;
1494 src_rpub = src_rp->r_pub;
1495 dst_rpub = dst_rp->r_pub;
1497 /* Save existing data first. */
1498 orig_src_rproc = *src_rp;
1499 orig_src_rprocpub = *src_rpub;
1500 orig_dst_rproc = *dst_rp;
1501 orig_dst_rprocpub = *dst_rpub;
1503 /* Swap slots. */
1504 *src_rp = orig_dst_rproc;
1505 *src_rpub = orig_dst_rprocpub;
1506 *dst_rp = orig_src_rproc;
1507 *dst_rpub = orig_src_rprocpub;
1509 /* Restore public entries. */
1510 src_rp->r_pub = orig_src_rproc.r_pub;
1511 dst_rp->r_pub = orig_dst_rproc.r_pub;
1513 /* Rebuild command dependencies. */
1514 build_cmd_dep(src_rp);
1515 build_cmd_dep(dst_rp);
1517 /* Swap local slot pointers. */
1518 swap_slot_pointer(&src_rp->r_prev_rp, src_rp, dst_rp);
1519 swap_slot_pointer(&src_rp->r_next_rp, src_rp, dst_rp);
1520 swap_slot_pointer(&src_rp->r_old_rp, src_rp, dst_rp);
1521 swap_slot_pointer(&src_rp->r_new_rp, src_rp, dst_rp);
1522 swap_slot_pointer(&dst_rp->r_prev_rp, src_rp, dst_rp);
1523 swap_slot_pointer(&dst_rp->r_next_rp, src_rp, dst_rp);
1524 swap_slot_pointer(&dst_rp->r_old_rp, src_rp, dst_rp);
1525 swap_slot_pointer(&dst_rp->r_new_rp, src_rp, dst_rp);
1527 /* Swap global slot pointers. */
1528 swap_slot_pointer(&rupdate.rp, src_rp, dst_rp);
1529 swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)],
1530 src_rp, dst_rp);
1531 swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)],
1532 src_rp, dst_rp);
1534 /* Adjust input pointers. */
1535 *src_rpp = dst_rp;
1536 *dst_rpp = src_rp;
1539 /*===========================================================================*
1540 * lookup_slot_by_label *
1541 *===========================================================================*/
1542 PUBLIC struct rproc* lookup_slot_by_label(char *label)
1544 /* Lookup a service slot matching the given label. */
1545 int slot_nr;
1546 struct rproc *rp;
1547 struct rprocpub *rpub;
1549 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1550 rp = &rproc[slot_nr];
1551 if (!(rp->r_flags & RS_ACTIVE)) {
1552 continue;
1554 rpub = rp->r_pub;
1555 if (strcmp(rpub->label, label) == 0) {
1556 return rp;
1560 return NULL;
1563 /*===========================================================================*
1564 * lookup_slot_by_pid *
1565 *===========================================================================*/
1566 PUBLIC struct rproc* lookup_slot_by_pid(pid_t pid)
1568 /* Lookup a service slot matching the given pid. */
1569 int slot_nr;
1570 struct rproc *rp;
1572 if(pid < 0) {
1573 return NULL;
1576 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1577 rp = &rproc[slot_nr];
1578 if (!(rp->r_flags & RS_IN_USE)) {
1579 continue;
1581 if (rp->r_pid == pid) {
1582 return rp;
1586 return NULL;
1589 /*===========================================================================*
1590 * lookup_slot_by_dev_nr *
1591 *===========================================================================*/
1592 PUBLIC struct rproc* lookup_slot_by_dev_nr(dev_t dev_nr)
1594 /* Lookup a service slot matching the given device number. */
1595 int slot_nr;
1596 struct rproc *rp;
1597 struct rprocpub *rpub;
1599 if(dev_nr <= 0) {
1600 return NULL;
1603 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1604 rp = &rproc[slot_nr];
1605 rpub = rp->r_pub;
1606 if (!(rp->r_flags & RS_IN_USE)) {
1607 continue;
1609 if (rpub->dev_nr == dev_nr) {
1610 return rp;
1614 return NULL;
1617 /*===========================================================================*
1618 * alloc_slot *
1619 *===========================================================================*/
1620 PUBLIC int alloc_slot(rpp)
1621 struct rproc **rpp;
1623 /* Alloc a new system service slot. */
1624 int slot_nr;
1626 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1627 *rpp = &rproc[slot_nr]; /* get pointer to slot */
1628 if (!((*rpp)->r_flags & RS_IN_USE)) /* check if available */
1629 break;
1631 if (slot_nr >= NR_SYS_PROCS) {
1632 return ENOMEM;
1635 return OK;
1638 /*===========================================================================*
1639 * free_slot *
1640 *===========================================================================*/
1641 PUBLIC void free_slot(rp)
1642 struct rproc *rp;
1644 /* Free a system service slot. */
1645 struct rprocpub *rpub;
1647 rpub = rp->r_pub;
1649 /* Send a late reply if there is any pending. */
1650 late_reply(rp, OK);
1652 /* Free memory if necessary. */
1653 if(rpub->sys_flags & SF_USE_COPY) {
1654 free_exec(rp);
1657 /* Mark slot as no longer in use.. */
1658 rp->r_flags = 0;
1659 rp->r_pid = -1;
1660 rpub->in_use = FALSE;
1661 rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
1665 /*===========================================================================*
1666 * get_next_label *
1667 *===========================================================================*/
1668 PUBLIC char *get_next_label(ptr, label, caller_label)
1669 char *ptr;
1670 char *label;
1671 char *caller_label;
1673 /* Get the next label from the list of (IPC) labels.
1675 char *p, *q;
1676 size_t len;
1678 for (p= ptr; p[0] != '\0'; p= q)
1680 /* Skip leading space */
1681 while (p[0] != '\0' && isspace((unsigned char)p[0]))
1682 p++;
1684 /* Find start of next word */
1685 q= p;
1686 while (q[0] != '\0' && !isspace((unsigned char)q[0]))
1687 q++;
1688 if (q == p)
1689 continue;
1690 len= q-p;
1691 if (len > RS_MAX_LABEL_LEN)
1693 printf(
1694 "rs:get_next_label: bad ipc list entry '%.*s' for %s: too long\n",
1695 len, p, caller_label);
1696 continue;
1698 memcpy(label, p, len);
1699 label[len]= '\0';
1701 return q; /* found another */
1704 return NULL; /* done */
1707 /*===========================================================================*
1708 * add_forward_ipc *
1709 *===========================================================================*/
1710 PUBLIC void add_forward_ipc(rp, privp)
1711 struct rproc *rp;
1712 struct priv *privp;
1714 /* Add IPC send permissions to a process based on that process's IPC
1715 * list.
1717 char label[RS_MAX_LABEL_LEN+1], *p;
1718 struct rproc *tmp_rp;
1719 struct rprocpub *tmp_rpub;
1720 endpoint_t endpoint;
1721 int r;
1722 int priv_id;
1723 struct priv priv;
1724 struct rprocpub *rpub;
1726 rpub = rp->r_pub;
1727 p = rp->r_ipc_list;
1729 while ((p = get_next_label(p, label, rpub->label)) != NULL) {
1731 if (strcmp(label, "SYSTEM") == 0)
1732 endpoint= SYSTEM;
1733 else if (strcmp(label, "USER") == 0)
1734 endpoint= INIT_PROC_NR; /* all user procs */
1735 else if (strcmp(label, "PM") == 0)
1736 endpoint= PM_PROC_NR;
1737 else if (strcmp(label, "VFS") == 0)
1738 endpoint= FS_PROC_NR;
1739 else if (strcmp(label, "RS") == 0)
1740 endpoint= RS_PROC_NR;
1741 else if (strcmp(label, "LOG") == 0)
1742 endpoint= LOG_PROC_NR;
1743 else if (strcmp(label, "TTY") == 0)
1744 endpoint= TTY_PROC_NR;
1745 else if (strcmp(label, "DS") == 0)
1746 endpoint= DS_PROC_NR;
1747 else if (strcmp(label, "VM") == 0)
1748 endpoint= VM_PROC_NR;
1749 else
1751 /* Try to find process */
1752 tmp_rp = lookup_slot_by_label(label);
1753 if (!tmp_rp)
1754 continue;
1755 tmp_rpub = tmp_rp->r_pub;
1756 endpoint= tmp_rpub->endpoint;
1759 if ((r = sys_getpriv(&priv, endpoint)) < 0)
1761 printf(
1762 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1763 label, r);
1764 continue;
1766 priv_id= priv.s_id;
1767 set_sys_bit(privp->s_ipc_to, priv_id);
1772 /*===========================================================================*
1773 * add_backward_ipc *
1774 *===========================================================================*/
1775 PUBLIC void add_backward_ipc(rp, privp)
1776 struct rproc *rp;
1777 struct priv *privp;
1779 /* Add IPC send permissions to a process based on other processes' IPC
1780 * lists. This is enough to allow each such two processes to talk to
1781 * each other, as the kernel guarantees send mask symmetry. We need to
1782 * add these permissions now because the current process may not yet
1783 * have existed at the time that the other process was initialized.
1785 char label[RS_MAX_LABEL_LEN+1], *p;
1786 struct rproc *rrp;
1787 struct rprocpub *rrpub;
1788 int priv_id, found;
1790 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
1791 if (!(rrp->r_flags & RS_IN_USE))
1792 continue;
1794 /* If an IPC target list was provided for the process being
1795 * checked here, make sure that the label of the new process
1796 * is in that process's list.
1798 if (rrp->r_ipc_list[0]) {
1799 found = 0;
1801 rrpub = rrp->r_pub;
1802 p = rrp->r_ipc_list;
1804 while ((p = get_next_label(p, label,
1805 rrpub->label)) != NULL) {
1806 if (!strcmp(rrpub->label, label)) {
1807 found = 1;
1808 break;
1812 if (!found)
1813 continue;
1816 priv_id= rrp->r_priv.s_id;
1818 set_sys_bit(privp->s_ipc_to, priv_id);
1823 /*===========================================================================*
1824 * init_privs *
1825 *===========================================================================*/
1826 PUBLIC void init_privs(rp, privp)
1827 struct rproc *rp;
1828 struct priv *privp;
1830 int i;
1832 /* Clear s_ipc_to */
1833 memset(&privp->s_ipc_to, '\0', sizeof(privp->s_ipc_to));
1835 if (strlen(rp->r_ipc_list) != 0)
1837 add_forward_ipc(rp, privp);
1838 add_backward_ipc(rp, privp);
1841 else
1843 for (i= 0; i<NR_SYS_PROCS; i++)
1845 if (i != USER_PRIV_ID)
1846 set_sys_bit(privp->s_ipc_to, i);