tools/llvm: Do not build with symbols
[minix3.git] / minix / servers / rs / manager.c
blob9adf386c35877248508dafd6582f710070973eac
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 <paths.h>
10 #include <sys/exec_elf.h>
12 #include "inc.h"
14 #include "kernel/proc.h"
16 /*===========================================================================*
17 * caller_is_root *
18 *===========================================================================*/
19 static int caller_is_root(endpoint)
20 endpoint_t endpoint; /* caller endpoint */
22 uid_t euid;
24 /* Check if caller has root user ID. */
25 euid = getnuid(endpoint);
26 if (rs_verbose && euid != 0)
28 printf("RS: got unauthorized request from endpoint %d\n", endpoint);
31 return euid == 0;
34 /*===========================================================================*
35 * caller_can_control *
36 *===========================================================================*/
37 static int caller_can_control(endpoint, target_rp)
38 endpoint_t endpoint;
39 struct rproc *target_rp;
41 int control_allowed = 0;
42 register struct rproc *rp;
43 register struct rprocpub *rpub;
44 char *proc_name;
45 int c;
47 proc_name = target_rp->r_pub->proc_name;
49 /* Check if label is listed in caller's isolation policy. */
50 for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) {
51 if (!(rp->r_flags & RS_IN_USE))
52 continue;
54 rpub = rp->r_pub;
55 if (rpub->endpoint == endpoint) {
56 break;
59 if (rp == END_RPROC_ADDR) return 0;
61 for (c = 0; c < rp->r_nr_control; c++) {
62 if (strcmp(rp->r_control[c], proc_name) == 0) {
63 control_allowed = 1;
64 break;
68 if (rs_verbose)
69 printf("RS: allowing %u control over %s via policy: %s\n",
70 endpoint, target_rp->r_pub->label,
71 control_allowed ? "yes" : "no");
73 return control_allowed;
76 /*===========================================================================*
77 * check_call_permission *
78 *===========================================================================*/
79 int check_call_permission(caller, call, rp)
80 endpoint_t caller;
81 int call;
82 struct rproc *rp;
84 /* Check if the caller has permission to execute a particular call. */
85 struct rprocpub *rpub;
86 int call_allowed;
88 /* Caller should be either root or have control privileges. */
89 call_allowed = caller_is_root(caller);
90 if(rp) {
91 call_allowed |= caller_can_control(caller, rp);
93 if(!call_allowed) {
94 return EPERM;
97 if(rp) {
98 rpub = rp->r_pub;
100 /* Only allow RS_EDIT if the target is a user process. */
101 if(!(rp->r_priv.s_flags & SYS_PROC)) {
102 if(call != RS_EDIT) return EPERM;
105 /* Disallow the call if another call is in progress for the service. */
106 if((rp->r_flags & RS_LATEREPLY)
107 || (rp->r_flags & RS_INITIALIZING) || (rp->r_flags & RS_UPDATING)) {
108 return EBUSY;
111 /* Only allow RS_DOWN and RS_RESTART if the service has terminated. */
112 if(rp->r_flags & RS_TERMINATED) {
113 if(call != RS_DOWN && call != RS_RESTART) return EPERM;
116 /* Disallow RS_DOWN for core system services. */
117 if (rpub->sys_flags & SF_CORE_SRV) {
118 if(call == RS_DOWN) return EPERM;
122 return OK;
125 /*===========================================================================*
126 * copy_rs_start *
127 *===========================================================================*/
128 int copy_rs_start(src_e, src_rs_start, dst_rs_start)
129 endpoint_t src_e;
130 char *src_rs_start;
131 struct rs_start *dst_rs_start;
133 int r;
135 r = sys_datacopy(src_e, (vir_bytes) src_rs_start,
136 SELF, (vir_bytes) dst_rs_start, sizeof(struct rs_start));
138 return r;
141 /*===========================================================================*
142 * copy_label *
143 *===========================================================================*/
144 int copy_label(src_e, src_label, src_len, dst_label, dst_len)
145 endpoint_t src_e;
146 char *src_label;
147 size_t src_len;
148 char *dst_label;
149 size_t dst_len;
151 int s, len;
153 len = MIN(dst_len-1, src_len);
155 s = sys_datacopy(src_e, (vir_bytes) src_label,
156 SELF, (vir_bytes) dst_label, len);
157 if (s != OK) return s;
159 dst_label[len] = 0;
161 return OK;
164 /*===========================================================================*
165 * build_cmd_dep *
166 *===========================================================================*/
167 void build_cmd_dep(struct rproc *rp)
169 struct rprocpub *rpub;
170 int arg_count;
171 int len;
172 char *cmd_ptr;
174 rpub = rp->r_pub;
176 /* Build argument vector to be passed to execute call. The format of the
177 * arguments vector is: path, arguments, NULL.
179 strcpy(rp->r_args, rp->r_cmd); /* copy raw command */
180 arg_count = 0; /* initialize arg count */
181 rp->r_argv[arg_count++] = rp->r_args; /* start with path */
182 cmd_ptr = rp->r_args; /* do some parsing */
183 while(*cmd_ptr != '\0') { /* stop at end of string */
184 if (*cmd_ptr == ' ') { /* next argument */
185 *cmd_ptr = '\0'; /* terminate previous */
186 while (*++cmd_ptr == ' ') ; /* skip spaces */
187 if (*cmd_ptr == '\0') break; /* no arg following */
188 /* There are ARGV_ELEMENTS elements; must leave one for null */
189 if (arg_count>=ARGV_ELEMENTS-1) { /* arg vector full */
190 printf("RS: build_cmd_dep: too many args\n");
191 break;
193 assert(arg_count < ARGV_ELEMENTS);
194 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
196 cmd_ptr ++; /* continue parsing */
198 assert(arg_count < ARGV_ELEMENTS);
199 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
200 rp->r_argc = arg_count;
202 /* Build process name. */
203 cmd_ptr = strrchr(rp->r_argv[0], '/');
204 if (cmd_ptr)
205 cmd_ptr++;
206 else
207 cmd_ptr= rp->r_argv[0];
208 len= strlen(cmd_ptr);
209 if (len > RS_MAX_LABEL_LEN-1)
210 len= RS_MAX_LABEL_LEN-1; /* truncate name */
211 memcpy(rpub->proc_name, cmd_ptr, len);
212 rpub->proc_name[len]= '\0';
215 /*===========================================================================*
216 * srv_update *
217 *===========================================================================*/
218 int srv_update(endpoint_t src_e, endpoint_t dst_e)
220 int r;
222 /* Ask VM to swap the slots of the two processes and tell the kernel to
223 * do the same. If VM is the service being updated, only perform the kernel
224 * part of the call. The new instance of VM will do the rest at
225 * initialization time.
227 if(src_e != VM_PROC_NR) {
228 r = vm_update(src_e, dst_e);
230 else {
231 r = sys_update(src_e, dst_e);
234 return r;
237 /*===========================================================================*
238 * update_period *
239 *===========================================================================*/
240 void update_period(message *m_ptr)
242 clock_t now = m_ptr->m_notify.timestamp;
243 short has_update_timed_out;
244 message m;
245 struct rprocpub *rpub;
247 rpub = rupdate.rp->r_pub;
249 /* See if a timeout has occurred. */
250 has_update_timed_out = (now - rupdate.prepare_tm > rupdate.prepare_maxtime);
252 /* If an update timed out, end the update process and notify
253 * the old version that the update has been canceled. From now on, the old
254 * version will continue executing.
256 if(has_update_timed_out) {
257 printf("RS: update failed: maximum prepare time reached\n");
258 end_update(EINTR, RS_DONTREPLY);
260 /* Prepare cancel request. */
261 m.m_type = RS_LU_PREPARE;
262 m.m_rs_update.state = SEF_LU_STATE_NULL;
263 if(rpub->endpoint == RS_PROC_NR) {
264 /* RS can process the request directly. */
265 do_sef_lu_request(&m);
267 else {
268 /* Send request message to the system service. */
269 asynsend(rpub->endpoint, &m);
274 /*===========================================================================*
275 * end_update *
276 *===========================================================================*/
277 void end_update(int result, int reply_flag)
279 /* End the update process. There are two possibilities:
280 * 1) the update succeeded. In that case, cleanup the old version and mark the
281 * new version as no longer under update.
282 * 2) the update failed. In that case, cleanup the new version and mark the old
283 * version as no longer under update. Eventual late ready to update
284 * messages (if any) will simply be ignored and the service can
285 * continue executing. In addition, reset the check timestamp, so that if the
286 * service has a period, a status request will be forced in the next period.
288 struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp;
289 struct rproc **rps;
290 int nr_rps, i;
292 old_rp = rupdate.rp;
293 new_rp = old_rp->r_new_rp;
295 if(rs_verbose)
296 printf("RS: ending update from %s to %s with result: %d\n",
297 srv_to_string(old_rp), srv_to_string(new_rp), result);
299 /* Decide which version has to die out and which version has to survive. */
300 surviving_rp = (result == OK ? new_rp : old_rp);
301 exiting_rp = (result == OK ? old_rp : new_rp);
303 /* End update. */
304 rupdate.flags &= ~RS_UPDATING;
305 rupdate.rp = NULL;
306 old_rp->r_new_rp = NULL;
307 new_rp->r_old_rp = NULL;
308 old_rp->r_check_tm = 0;
310 /* Send a late reply if necessary. */
311 late_reply(old_rp, result);
313 /* Mark the version that has to survive as no longer updating and
314 * reply when asked to.
316 surviving_rp->r_flags &= ~RS_UPDATING;
317 if(reply_flag == RS_REPLY) {
318 message m;
319 m.m_type = result;
320 reply(surviving_rp->r_pub->endpoint, surviving_rp, &m);
323 /* Cleanup the version that has to die out. */
324 get_service_instances(exiting_rp, &rps, &nr_rps);
325 for(i=0;i<nr_rps;i++) {
326 cleanup_service(rps[i]);
329 if(rs_verbose)
330 printf("RS: %s ended the update\n", srv_to_string(surviving_rp));
333 /*===========================================================================*
334 * kill_service_debug *
335 *===========================================================================*/
336 int kill_service_debug(file, line, rp, errstr, err)
337 char *file;
338 int line;
339 struct rproc *rp;
340 char *errstr;
341 int err;
343 /* Crash a system service and don't let it restart. */
344 if(errstr && !shutting_down) {
345 printf("RS: %s (error %d)\n", errstr, err);
347 rp->r_flags |= RS_EXITING; /* expect exit */
348 crash_service_debug(file, line, rp); /* simulate crash */
350 return err;
353 /*===========================================================================*
354 * crash_service_debug *
355 *===========================================================================*/
356 int crash_service_debug(file, line, rp)
357 char *file;
358 int line;
359 struct rproc *rp;
361 /* Simluate a crash in a system service. */
362 struct rprocpub *rpub;
364 rpub = rp->r_pub;
366 if(rs_verbose)
367 printf("RS: %s %skilled at %s:%d\n", srv_to_string(rp),
368 rp->r_flags & RS_EXITING ? "lethally " : "", file, line);
370 /* RS should simply exit() directly. */
371 if(rpub->endpoint == RS_PROC_NR) {
372 exit(1);
375 return sys_kill(rpub->endpoint, SIGKILL);
378 /*===========================================================================*
379 * cleanup_service_debug *
380 *===========================================================================*/
381 void cleanup_service_debug(file, line, rp)
382 char *file;
383 int line;
384 struct rproc *rp;
386 struct rprocpub *rpub;
387 int s;
389 rpub = rp->r_pub;
391 if(rs_verbose)
392 printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp),
393 file, line);
395 /* Tell scheduler this process is finished */
396 if ((s = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) {
397 printf("RS: warning: scheduler won't give up process: %d\n", s);
400 /* Ask PM to exit the service */
401 if(rp->r_pid == -1) {
402 printf("RS: warning: attempt to kill pid -1!\n");
404 else {
405 srv_kill(rp->r_pid, SIGKILL);
408 /* Free slot, unless we're about to reuse it */
409 if (!(rp->r_flags & RS_REINCARNATE))
410 free_slot(rp);
413 /*===========================================================================*
414 * create_service *
415 *===========================================================================*/
416 int create_service(rp)
417 struct rproc *rp;
419 /* Create the given system service. */
420 int child_proc_nr_e, child_proc_nr_n; /* child process slot */
421 pid_t child_pid; /* child's process id */
422 int s, use_copy, has_replica;
423 extern char **environ;
424 struct rprocpub *rpub;
426 rpub = rp->r_pub;
427 use_copy= (rpub->sys_flags & SF_USE_COPY);
428 has_replica= (rp->r_old_rp
429 || (rp->r_prev_rp && !(rp->r_prev_rp->r_flags & RS_TERMINATED)));
431 /* Do we need an existing replica to create the service? */
432 if(!has_replica && (rpub->sys_flags & SF_NEED_REPL)) {
433 printf("RS: unable to create service '%s' without a replica\n",
434 rpub->label);
435 free_slot(rp);
436 return(EPERM);
439 /* Do we need an in-memory copy to create the service? */
440 if(!use_copy && (rpub->sys_flags & SF_NEED_COPY)) {
441 printf("RS: unable to create service '%s' without an in-memory copy\n",
442 rpub->label);
443 free_slot(rp);
444 return(EPERM);
447 /* Do we have a copy or a command to create the service? */
448 if(!use_copy && !strcmp(rp->r_cmd, "")) {
449 printf("RS: unable to create service '%s' without a copy or command\n",
450 rpub->label);
451 free_slot(rp);
452 return(EPERM);
455 /* Now fork and branch for parent and child process (and check for error).
456 * After fork()ing, we need to pin RS memory again or pagefaults will occur
457 * on future writes.
459 if(rs_verbose)
460 printf("RS: forking child with srv_fork()...\n");
461 child_pid= srv_fork(rp->r_uid, 0); /* Force group to operator for now */
462 if(child_pid < 0) {
463 printf("RS: srv_fork() failed (error %d)\n", child_pid);
464 free_slot(rp);
465 return(child_pid);
468 /* Get endpoint of the child. */
469 if ((s = getprocnr(child_pid, &child_proc_nr_e)) != 0)
470 panic("unable to get child endpoint: %d", s);
472 /* There is now a child process. Update the system process table. */
473 child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
474 rp->r_flags = RS_IN_USE; /* mark slot in use */
475 rpub->endpoint = child_proc_nr_e; /* set child endpoint */
476 rp->r_pid = child_pid; /* set child pid */
477 rp->r_check_tm = 0; /* not checked yet */
478 getticks(&rp->r_alive_tm); /* currently alive */
479 rp->r_stop_tm = 0; /* not exiting yet */
480 rp->r_backoff = 0; /* not to be restarted */
481 rproc_ptr[child_proc_nr_n] = rp; /* mapping for fast access */
482 rpub->in_use = TRUE; /* public entry is now in use */
484 /* Set and synch the privilege structure for the new service. */
485 if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_SET_SYS, &rp->r_priv)) != OK
486 || (s = sys_getpriv(&rp->r_priv, child_proc_nr_e)) != OK) {
487 printf("RS: unable to set privilege structure: %d\n", s);
488 cleanup_service(rp);
489 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
490 return ENOMEM;
493 /* Set the scheduler for this process */
494 if ((s = sched_init_proc(rp)) != OK) {
495 printf("RS: unable to start scheduling: %d\n", s);
496 cleanup_service(rp);
497 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
498 return s;
501 /* Copy the executable image into the child process. If no copy exists,
502 * allocate one and free it right after exec completes.
504 if(use_copy) {
505 if(rs_verbose)
506 printf("RS: %s uses an in-memory copy\n",
507 srv_to_string(rp));
509 else {
510 if ((s = read_exec(rp)) != OK) {
511 printf("RS: read_exec failed: %d\n", s);
512 cleanup_service(rp);
513 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
514 return s;
517 if(rs_verbose)
518 printf("RS: execing child with srv_execve()...\n");
519 s = srv_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
520 environ);
521 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
522 if (s != OK) {
523 printf("RS: srv_execve failed: %d\n", s);
524 cleanup_service(rp);
525 return s;
527 if(!use_copy) {
528 free_exec(rp);
531 /* If this is a VM instance, let VM know now. */
532 if(rp->r_priv.s_flags & VM_SYS_PROC) {
533 if(rs_verbose)
534 printf("RS: informing VM of instance %s\n", srv_to_string(rp));
536 s = vm_memctl(rpub->endpoint, VM_RS_MEM_MAKE_VM);
537 if(s != OK) {
538 printf("vm_memctl failed: %d\n", s);
539 cleanup_service(rp);
540 return s;
544 /* Tell VM about allowed calls. */
545 if ((s = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0], TRUE)) != OK) {
546 printf("RS: vm_set_priv failed: %d\n", s);
547 cleanup_service(rp);
548 return s;
551 if(rs_verbose)
552 printf("RS: %s created\n", srv_to_string(rp));
554 return OK;
557 /*===========================================================================*
558 * clone_service *
559 *===========================================================================*/
560 int clone_service(rp, instance_flag)
561 struct rproc *rp;
562 int instance_flag;
564 /* Clone the given system service instance. */
565 struct rproc *replica_rp;
566 struct rprocpub *replica_rpub;
567 struct rproc **rp_link;
568 struct rproc **replica_link;
569 struct rproc *rs_rp;
570 int rs_flags;
571 int r;
573 if(rs_verbose)
574 printf("RS: creating a replica for %s\n", srv_to_string(rp));
576 /* Clone slot. */
577 if((r = clone_slot(rp, &replica_rp)) != OK) {
578 return r;
580 replica_rpub = replica_rp->r_pub;
582 /* Clone is a live updated or restarted service instance? */
583 if(instance_flag == LU_SYS_PROC) {
584 rp_link = &rp->r_new_rp;
585 replica_link = &replica_rp->r_old_rp;
587 else {
588 rp_link = &rp->r_next_rp;
589 replica_link = &replica_rp->r_prev_rp;
591 replica_rp->r_priv.s_flags |= instance_flag;
593 /* Link the two slots. */
594 *rp_link = replica_rp;
595 *replica_link = rp;
597 /* Create a new replica of the service. */
598 r = create_service(replica_rp);
599 if(r != OK) {
600 *rp_link = NULL;
601 return r;
604 /* If this instance is for restarting RS, set up a backup signal manager. */
605 rs_flags = (ROOT_SYS_PROC | RST_SYS_PROC);
606 if((replica_rp->r_priv.s_flags & rs_flags) == rs_flags) {
607 rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
609 /* Update signal managers. */
610 r = update_sig_mgrs(rs_rp, SELF, replica_rpub->endpoint);
611 if(r == OK) {
612 r = update_sig_mgrs(replica_rp, SELF, NONE);
614 if(r != OK) {
615 *rp_link = NULL;
616 return kill_service(replica_rp, "update_sig_mgrs failed", r);
620 return OK;
623 /*===========================================================================*
624 * publish_service *
625 *===========================================================================*/
626 int publish_service(rp)
627 struct rproc *rp; /* pointer to service slot */
629 /* Publish a service. */
630 int r;
631 struct rprocpub *rpub;
632 struct rs_pci pci_acl;
633 message m;
634 endpoint_t ep;
636 rpub = rp->r_pub;
638 /* Register label with DS. */
639 r = ds_publish_label(rpub->label, rpub->endpoint, DSF_OVERWRITE);
640 if (r != OK) {
641 return kill_service(rp, "ds_publish_label call failed", r);
644 /* If the service is a driver, map it. */
645 if (rpub->dev_nr > 0) {
646 /* The purpose of non-blocking forks is to avoid involving VFS in the
647 * forking process, because VFS may be blocked on a ipc_sendrec() to a MFS
648 * that is waiting for a endpoint update for a dead driver. We have just
649 * published that update, but VFS may still be blocked. As a result, VFS
650 * may not yet have received PM's fork message. Hence, if we call
651 * mapdriver() immediately, VFS may not know about the process and thus
652 * refuse to add the driver entry. The following temporary hack works
653 * around this by forcing blocking communication from PM to VFS. Once VFS
654 * has been made non-blocking towards MFS instances, this hack and the
655 * big part of srv_fork() can go.
657 setuid(0);
659 if ((r = mapdriver(rpub->label, rpub->dev_nr)) != OK) {
660 return kill_service(rp, "couldn't map driver", r);
664 #if USE_PCI
665 /* If PCI properties are set, inform the PCI driver about the new service. */
666 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
667 pci_acl = rpub->pci_acl;
668 strcpy(pci_acl.rsp_label, rpub->label);
669 pci_acl.rsp_endpoint= rpub->endpoint;
671 r = pci_set_acl(&pci_acl);
672 if (r != OK) {
673 return kill_service(rp, "pci_set_acl call failed", r);
676 #endif /* USE_PCI */
678 if (rpub->devman_id != 0) {
679 r = ds_retrieve_label_endpt("devman",&ep);
681 if (r != OK) {
682 return kill_service(rp, "devman not running?", r);
684 m.m_type = DEVMAN_BIND;
685 m.DEVMAN_ENDPOINT = rpub->endpoint;
686 m.DEVMAN_DEVICE_ID = rpub->devman_id;
687 r = ipc_sendrec(ep, &m);
688 if (r != OK || m.DEVMAN_RESULT != OK) {
689 return kill_service(rp, "devman bind device failed", r);
693 if(rs_verbose)
694 printf("RS: %s published\n", srv_to_string(rp));
696 return OK;
699 /*===========================================================================*
700 * unpublish_service *
701 *===========================================================================*/
702 int unpublish_service(rp)
703 struct rproc *rp; /* pointer to service slot */
705 /* Unpublish a service. */
706 struct rprocpub *rpub;
707 int r, result;
708 message m;
709 endpoint_t ep;
712 rpub = rp->r_pub;
713 result = OK;
715 /* Unregister label with DS. */
716 r = ds_delete_label(rpub->label);
717 if (r != OK && !shutting_down) {
718 printf("RS: ds_delete_label call failed (error %d)\n", r);
719 result = r;
722 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
724 #if USE_PCI
725 /* If PCI properties are set, inform the PCI driver. */
726 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
727 r = pci_del_acl(rpub->endpoint);
728 if (r != OK && !shutting_down) {
729 printf("RS: pci_del_acl call failed (error %d)\n", r);
730 result = r;
733 #endif /* USE_PCI */
735 if (rpub->devman_id != 0) {
736 r = ds_retrieve_label_endpt("devman",&ep);
738 if (r != OK) {
739 printf("RS: devman not running?");
740 } else {
741 m.m_type = DEVMAN_UNBIND;
742 m.DEVMAN_ENDPOINT = rpub->endpoint;
743 m.DEVMAN_DEVICE_ID = rpub->devman_id;
744 r = ipc_sendrec(ep, &m);
746 if (r != OK || m.DEVMAN_RESULT != OK) {
747 printf("RS: devman unbind device failed");
752 if(rs_verbose)
753 printf("RS: %s unpublished\n", srv_to_string(rp));
755 return result;
758 /*===========================================================================*
759 * run_service *
760 *===========================================================================*/
761 int run_service(rp, init_type)
762 struct rproc *rp;
763 int init_type;
765 /* Let a newly created service run. */
766 struct rprocpub *rpub;
767 int s;
769 rpub = rp->r_pub;
771 /* Allow the service to run. */
772 if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
773 return kill_service(rp, "unable to allow the service to run",s);
776 /* Initialize service. */
777 if((s = init_service(rp, init_type)) != OK) {
778 return kill_service(rp, "unable to initialize service", s);
781 if(rs_verbose)
782 printf("RS: %s allowed to run\n", srv_to_string(rp));
784 return OK;
787 /*===========================================================================*
788 * start_service *
789 *===========================================================================*/
790 int start_service(rp)
791 struct rproc *rp;
793 /* Start a system service. */
794 int r, init_type;
795 struct rprocpub *rpub;
797 rpub = rp->r_pub;
799 /* Create and make active. */
800 r = create_service(rp);
801 if(r != OK) {
802 return r;
804 activate_service(rp, NULL);
806 /* Publish service properties. */
807 r = publish_service(rp);
808 if (r != OK) {
809 return r;
812 /* Run. */
813 init_type = SEF_INIT_FRESH;
814 r = run_service(rp, init_type);
815 if(r != OK) {
816 return r;
819 if(rs_verbose)
820 printf("RS: %s started with major %d\n", srv_to_string(rp),
821 rpub->dev_nr);
823 return OK;
826 /*===========================================================================*
827 * stop_service *
828 *===========================================================================*/
829 void stop_service(struct rproc *rp,int how)
831 struct rprocpub *rpub;
832 int signo;
834 rpub = rp->r_pub;
836 /* Try to stop the system service. First send a SIGTERM signal to ask the
837 * system service to terminate. If the service didn't install a signal
838 * handler, it will be killed. If it did and ignores the signal, we'll
839 * find out because we record the time here and send a SIGKILL.
841 if(rs_verbose)
842 printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp));
844 signo = rpub->endpoint != RS_PROC_NR ? SIGTERM : SIGHUP; /* SIGHUP for RS. */
846 rp->r_flags |= how; /* what to on exit? */
847 sys_kill(rpub->endpoint, signo); /* first try friendly */
848 getticks(&rp->r_stop_tm); /* record current time */
851 /*===========================================================================*
852 * update_service *
853 *===========================================================================*/
854 int update_service(src_rpp, dst_rpp, swap_flag)
855 struct rproc **src_rpp;
856 struct rproc **dst_rpp;
857 int swap_flag;
859 /* Update an existing service. */
860 int r;
861 struct rproc *src_rp;
862 struct rproc *dst_rp;
863 struct rprocpub *src_rpub;
864 struct rprocpub *dst_rpub;
865 int pid;
866 endpoint_t endpoint;
868 src_rp = *src_rpp;
869 dst_rp = *dst_rpp;
870 src_rpub = src_rp->r_pub;
871 dst_rpub = dst_rp->r_pub;
873 if(rs_verbose)
874 printf("RS: %s updating into %s\n",
875 srv_to_string(src_rp), srv_to_string(dst_rp));
877 /* Swap the slots of the two processes when asked to. */
878 if(swap_flag == RS_SWAP) {
879 if((r = srv_update(src_rpub->endpoint, dst_rpub->endpoint)) != OK) {
880 return r;
884 /* Swap slots here as well. */
885 pid = src_rp->r_pid;
886 endpoint = src_rpub->endpoint;
887 swap_slot(&src_rp, &dst_rp);
889 /* Reassign pids and endpoints. */
890 src_rp->r_pid = dst_rp->r_pid;
891 src_rp->r_pub->endpoint = dst_rp->r_pub->endpoint;
892 rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)] = src_rp;
893 dst_rp->r_pid = pid;
894 dst_rp->r_pub->endpoint = endpoint;
895 rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)] = dst_rp;
897 /* Adjust input pointers. */
898 *src_rpp = src_rp;
899 *dst_rpp = dst_rp;
901 /* Make the new version active. */
902 activate_service(dst_rp, src_rp);
904 if(rs_verbose)
905 printf("RS: %s updated into %s\n",
906 srv_to_string(src_rp), srv_to_string(dst_rp));
908 return OK;
911 /*===========================================================================*
912 * activate_service *
913 *===========================================================================*/
914 void activate_service(struct rproc *rp, struct rproc *ex_rp)
916 /* Activate a service instance and deactivate another one if requested. */
918 if(ex_rp && (ex_rp->r_flags & RS_ACTIVE) ) {
919 ex_rp->r_flags &= ~RS_ACTIVE;
920 if(rs_verbose)
921 printf("RS: %s becomes inactive\n", srv_to_string(ex_rp));
924 if(! (rp->r_flags & RS_ACTIVE) ) {
925 rp->r_flags |= RS_ACTIVE;
926 if(rs_verbose)
927 printf("RS: %s becomes active\n", srv_to_string(rp));
931 /*===========================================================================*
932 * reincarnate_service *
933 *===========================================================================*/
934 void reincarnate_service(struct rproc *rp)
936 /* Restart a service as if it were never started before. */
937 struct rprocpub *rpub;
938 int i;
940 rpub = rp->r_pub;
942 rp->r_flags &= RS_IN_USE;
943 rp->r_pid = -1;
944 rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
946 /* Restore original IRQ and I/O range tables in the priv struct. This is the
947 * only part of the privilege structure that can be modified by processes
948 * other than RS itself.
950 rp->r_priv.s_nr_irq = rp->r_nr_irq;
951 for (i = 0; i < rp->r_nr_irq; i++)
952 rp->r_priv.s_irq_tab[i] = rp->r_irq_tab[i];
953 rp->r_priv.s_nr_io_range = rp->r_nr_io_range;
954 for (i = 0; i < rp->r_nr_io_range; i++)
955 rp->r_priv.s_io_tab[i] = rp->r_io_tab[i];
957 rp->r_old_rp = NULL;
958 rp->r_new_rp = NULL;
959 rp->r_prev_rp = NULL;
960 rp->r_next_rp = NULL;
962 start_service(rp);
965 /*===========================================================================*
966 * terminate_service *
967 *===========================================================================*/
968 void terminate_service(struct rproc *rp)
970 /* Handle a termination event for a system service. */
971 struct rproc **rps;
972 struct rprocpub *rpub;
973 int nr_rps;
974 int i, r;
976 rpub = rp->r_pub;
978 if(rs_verbose)
979 printf("RS: %s terminated\n", srv_to_string(rp));
981 /* Deal with failures during initialization. */
982 if(rp->r_flags & RS_INITIALIZING) {
983 if (rpub->sys_flags & SF_NO_BIN_EXP) {
984 /* If service was deliberately started with binary exponential offset
985 * disabled, we're going to assume we want to refresh a service upon
986 * failure.
988 if(rs_verbose)
989 printf("RS: service '%s' exited during initialization; "
990 "refreshing\n", rpub->label);
991 rp->r_flags |= RS_REFRESHING; /* restart initialization. */
992 } else {
993 if(rs_verbose)
994 printf("RS: service '%s' exited during initialization; "
995 "not restarting\n", rpub->label);
996 rp->r_flags |= RS_EXITING; /* don't restart. */
999 /* If updating, rollback. */
1000 if(rp->r_flags & RS_UPDATING) {
1001 struct rproc *old_rp, *new_rp;
1002 printf("RS: update failed: state transfer failed. Rolling back...\n");
1003 new_rp = rp;
1004 old_rp = new_rp->r_old_rp;
1005 new_rp->r_flags &= ~RS_INITIALIZING;
1006 r = update_service(&new_rp, &old_rp, RS_SWAP);
1007 assert(r == OK); /* can't fail */
1008 end_update(ERESTART, RS_REPLY);
1009 return;
1013 if (rp->r_flags & RS_EXITING) {
1014 /* If a core system service is exiting, we are in trouble. */
1015 if (rp->r_pub->sys_flags & SF_CORE_SRV && !shutting_down) {
1016 printf("core system service died: %s\n", srv_to_string(rp));
1017 _exit(1);
1020 /* See if a late reply has to be sent. */
1021 r = (rp->r_caller_request == RS_DOWN ? OK : EDEADEPT);
1022 late_reply(rp, r);
1024 /* Unpublish the service. */
1025 unpublish_service(rp);
1027 /* Cleanup all the instances of the service. */
1028 get_service_instances(rp, &rps, &nr_rps);
1029 for(i=0;i<nr_rps;i++) {
1030 cleanup_service(rps[i]);
1033 /* If the service is reincarnating, its slot has not been cleaned up.
1034 * Check for this flag now, and attempt to start the service again.
1035 * If this fails, start_service() itself will perform cleanup.
1037 if (rp->r_flags & RS_REINCARNATE) {
1038 reincarnate_service(rp);
1041 else if(rp->r_flags & RS_REFRESHING) {
1042 /* Restart service. */
1043 restart_service(rp);
1045 else {
1046 /* If an update is in progress, end it. The old version
1047 * that just exited will continue executing.
1049 if(rp->r_flags & RS_UPDATING) {
1050 end_update(ERESTART, RS_DONTREPLY);
1053 /* Determine what to do. If this is the first unexpected
1054 * exit, immediately restart this service. Otherwise use
1055 * a binary exponential backoff.
1057 if (rp->r_restarts > 0) {
1058 if (!(rpub->sys_flags & SF_NO_BIN_EXP)) {
1059 rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
1060 rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
1061 if ((rpub->sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
1062 rp->r_backoff= 1;
1064 else {
1065 rp->r_backoff = 1;
1067 return;
1070 /* Restart service. */
1071 restart_service(rp);
1075 /*===========================================================================*
1076 * run_script *
1077 *===========================================================================*/
1078 static int run_script(struct rproc *rp)
1080 int r, endpoint;
1081 pid_t pid;
1082 char *reason;
1083 char incarnation_str[20]; /* Enough for a counter? */
1084 char *envp[1] = { NULL };
1085 struct rprocpub *rpub;
1087 rpub = rp->r_pub;
1088 if (rp->r_flags & RS_REFRESHING)
1089 reason= "restart";
1090 else if (rp->r_flags & RS_NOPINGREPLY)
1091 reason= "no-heartbeat";
1092 else reason= "terminated";
1093 sprintf(incarnation_str, "%d", rp->r_restarts);
1095 if(rs_verbose) {
1096 printf("RS: %s:\n", srv_to_string(rp));
1097 printf("RS: calling script '%s'\n", rp->r_script);
1098 printf("RS: reason: '%s'\n", reason);
1099 printf("RS: incarnation: '%s'\n", incarnation_str);
1102 pid= fork();
1103 switch(pid)
1105 case -1:
1106 return kill_service(rp, "unable to fork script", errno);
1107 case 0:
1108 execle(_PATH_BSHELL, "sh", rp->r_script, rpub->label, reason,
1109 incarnation_str, (char*) NULL, envp);
1110 printf("RS: run_script: execl '%s' failed: %s\n",
1111 rp->r_script, strerror(errno));
1112 exit(1);
1113 default:
1114 /* Set the privilege structure for the child process. */
1115 if ((r = getprocnr(pid, &endpoint)) != 0)
1116 panic("unable to get child endpoint: %d", r);
1117 if ((r = sys_privctl(endpoint, SYS_PRIV_SET_USER, NULL))
1118 != OK) {
1119 return kill_service(rp,"can't set script privileges",r);
1121 /* Set the script's privileges on other servers. */
1122 vm_set_priv(endpoint, NULL, FALSE);
1123 if ((r = vm_set_priv(endpoint, NULL, FALSE)) != OK) {
1124 return kill_service(rp,"can't set script VM privs",r);
1126 /* Allow the script to run. */
1127 if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
1128 return kill_service(rp,"can't let the script run",r);
1130 /* Pin RS memory again after fork()ing. */
1131 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
1133 return OK;
1136 /*===========================================================================*
1137 * restart_service *
1138 *===========================================================================*/
1139 void restart_service(struct rproc *rp)
1141 /* Restart service via a recovery script or directly. */
1142 struct rproc *replica_rp;
1143 int r;
1145 /* See if a late reply has to be sent. */
1146 late_reply(rp, OK);
1148 /* This hack disables restarting of file servers, which at the moment always
1149 * cause VFS to hang indefinitely. As soon as VFS no longer blocks on calls
1150 * to file servers, this exception can be removed again.
1152 if (!strncmp(rp->r_pub->label, "fs_", 3)) {
1153 kill_service(rp, "file servers cannot be restarted yet", ENOSYS);
1154 return;
1157 /* Run a recovery script if available. */
1158 if (rp->r_script[0] != '\0') {
1159 run_script(rp);
1160 return;
1163 /* Restart directly. We need a replica if not already available. */
1164 if(rp->r_next_rp == NULL) {
1165 /* Create the replica. */
1166 r = clone_service(rp, RST_SYS_PROC);
1167 if(r != OK) {
1168 kill_service(rp, "unable to clone service", r);
1169 return;
1172 replica_rp = rp->r_next_rp;
1174 /* Update the service into the replica. */
1175 r = update_service(&rp, &replica_rp, RS_SWAP);
1176 if(r != OK) {
1177 kill_service(rp, "unable to update into new replica", r);
1178 return;
1181 /* Let the new replica run. */
1182 r = run_service(replica_rp, SEF_INIT_RESTART);
1183 if(r != OK) {
1184 kill_service(rp, "unable to let the replica run", r);
1185 return;
1188 if(rs_verbose)
1189 printf("RS: %s restarted into %s\n",
1190 srv_to_string(rp), srv_to_string(replica_rp));
1193 /*===========================================================================*
1194 * inherit_service_defaults *
1195 *===========================================================================*/
1196 void inherit_service_defaults(def_rp, rp)
1197 struct rproc *def_rp;
1198 struct rproc *rp;
1200 struct rprocpub *def_rpub;
1201 struct rprocpub *rpub;
1203 def_rpub = def_rp->r_pub;
1204 rpub = rp->r_pub;
1206 /* Device and PCI settings. These properties cannot change. */
1207 rpub->dev_nr = def_rpub->dev_nr;
1208 rpub->pci_acl = def_rpub->pci_acl;
1210 /* Immutable system and privilege flags. */
1211 rpub->sys_flags &= ~IMM_SF;
1212 rpub->sys_flags |= (def_rpub->sys_flags & IMM_SF);
1213 rp->r_priv.s_flags &= ~IMM_F;
1214 rp->r_priv.s_flags |= (def_rp->r_priv.s_flags & IMM_F);
1216 /* Allowed traps. They cannot change. */
1217 rp->r_priv.s_trap_mask = def_rp->r_priv.s_trap_mask;
1220 /*===========================================================================*
1221 * get_service_instances *
1222 *===========================================================================*/
1223 void get_service_instances(rp, rps, length)
1224 struct rproc *rp;
1225 struct rproc ***rps;
1226 int *length;
1228 /* Retrieve all the service instances of a given service. */
1229 static struct rproc *instances[5];
1230 int nr_instances;
1232 nr_instances = 0;
1233 instances[nr_instances++] = rp;
1234 if(rp->r_prev_rp) instances[nr_instances++] = rp->r_prev_rp;
1235 if(rp->r_next_rp) instances[nr_instances++] = rp->r_next_rp;
1236 if(rp->r_old_rp) instances[nr_instances++] = rp->r_old_rp;
1237 if(rp->r_new_rp) instances[nr_instances++] = rp->r_new_rp;
1239 *rps = instances;
1240 *length = nr_instances;
1243 /*===========================================================================*
1244 * share_exec *
1245 *===========================================================================*/
1246 void share_exec(rp_dst, rp_src)
1247 struct rproc *rp_dst, *rp_src;
1249 if(rs_verbose)
1250 printf("RS: %s shares exec image with %s\n",
1251 srv_to_string(rp_dst), srv_to_string(rp_src));
1253 /* Share exec image from rp_src to rp_dst. */
1254 rp_dst->r_exec_len = rp_src->r_exec_len;
1255 rp_dst->r_exec = rp_src->r_exec;
1258 /*===========================================================================*
1259 * read_exec *
1260 *===========================================================================*/
1261 int read_exec(rp)
1262 struct rproc *rp;
1264 int e, r, fd;
1265 char *e_name;
1266 struct stat sb;
1268 e_name= rp->r_argv[0];
1269 if(rs_verbose)
1270 printf("RS: service '%s' reads exec image from: %s\n", rp->r_pub->label,
1271 e_name);
1273 r= stat(e_name, &sb);
1274 if (r != 0)
1275 return -errno;
1277 if (sb.st_size < sizeof(Elf_Ehdr))
1278 return ENOEXEC;
1280 fd= open(e_name, O_RDONLY);
1281 if (fd == -1)
1282 return -errno;
1284 rp->r_exec_len= sb.st_size;
1285 rp->r_exec= malloc(rp->r_exec_len);
1286 if (rp->r_exec == NULL)
1288 printf("RS: read_exec: unable to allocate %d bytes\n",
1289 rp->r_exec_len);
1290 close(fd);
1291 return ENOMEM;
1294 r= read(fd, rp->r_exec, rp->r_exec_len);
1295 e= errno;
1296 close(fd);
1297 if (r == rp->r_exec_len)
1298 return OK;
1300 printf("RS: read_exec: read failed %d, errno %d\n", r, e);
1302 free_exec(rp);
1304 if (r >= 0)
1305 return EIO;
1306 else
1307 return -e;
1310 /*===========================================================================*
1311 * free_exec *
1312 *===========================================================================*/
1313 void free_exec(rp)
1314 struct rproc *rp;
1316 /* Free an exec image. */
1317 int slot_nr, has_shared_exec;
1318 struct rproc *other_rp;
1320 /* Search for some other slot sharing the same exec image. */
1321 has_shared_exec = FALSE;
1322 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1323 other_rp = &rproc[slot_nr]; /* get pointer to slot */
1324 if (other_rp->r_flags & RS_IN_USE && other_rp != rp
1325 && other_rp->r_exec == rp->r_exec) { /* found! */
1326 has_shared_exec = TRUE;
1327 break;
1331 /* If nobody uses our copy of the exec image, we can try to get rid of it. */
1332 if(!has_shared_exec) {
1333 if(rs_verbose)
1334 printf("RS: %s frees exec image\n", srv_to_string(rp));
1335 free(rp->r_exec);
1337 else {
1338 if(rs_verbose)
1339 printf("RS: %s no longer sharing exec image with %s\n",
1340 srv_to_string(rp), srv_to_string(other_rp));
1342 rp->r_exec = NULL;
1343 rp->r_exec_len = 0;
1346 /*===========================================================================*
1347 * edit_slot *
1348 *===========================================================================*/
1349 int edit_slot(rp, rs_start, source)
1350 struct rproc *rp;
1351 struct rs_start *rs_start;
1352 endpoint_t source;
1354 /* Edit a given slot to override existing settings. */
1355 struct rprocpub *rpub;
1356 char *label;
1357 int len;
1358 int s, i;
1359 int basic_kc[] = { SYS_BASIC_CALLS, NULL_C };
1360 int basic_vmc[] = { VM_BASIC_CALLS, NULL_C };
1362 rpub = rp->r_pub;
1364 /* Update IPC target list. */
1365 if (rs_start->rss_ipclen==0 || rs_start->rss_ipclen+1>sizeof(rp->r_ipc_list)){
1366 printf("RS: edit_slot: ipc list empty or long for '%s'\n", rpub->label);
1367 return EINVAL;
1369 s=sys_datacopy(source, (vir_bytes) rs_start->rss_ipc,
1370 SELF, (vir_bytes) rp->r_ipc_list, rs_start->rss_ipclen);
1371 if (s != OK) return(s);
1372 rp->r_ipc_list[rs_start->rss_ipclen]= '\0';
1374 /* Update IRQs. */
1375 if(rs_start->rss_nr_irq == RSS_IRQ_ALL) {
1376 rs_start->rss_nr_irq = 0;
1378 else {
1379 rp->r_priv.s_flags |= CHECK_IRQ;
1381 if (rs_start->rss_nr_irq > NR_IRQ) {
1382 printf("RS: edit_slot: too many IRQs requested\n");
1383 return EINVAL;
1385 rp->r_nr_irq= rp->r_priv.s_nr_irq= rs_start->rss_nr_irq;
1386 for (i= 0; i<rp->r_priv.s_nr_irq; i++) {
1387 rp->r_irq_tab[i]= rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i];
1388 if(rs_verbose)
1389 printf("RS: edit_slot: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
1392 /* Update I/O ranges. */
1393 if(rs_start->rss_nr_io == RSS_IO_ALL) {
1394 rs_start->rss_nr_io = 0;
1396 else {
1397 rp->r_priv.s_flags |= CHECK_IO_PORT;
1399 if (rs_start->rss_nr_io > NR_IO_RANGE) {
1400 printf("RS: edit_slot: too many I/O ranges requested\n");
1401 return EINVAL;
1403 rp->r_nr_io_range= rp->r_priv.s_nr_io_range= rs_start->rss_nr_io;
1404 for (i= 0; i<rp->r_priv.s_nr_io_range; i++) {
1405 rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base;
1406 rp->r_priv.s_io_tab[i].ior_limit=
1407 rs_start->rss_io[i].base+rs_start->rss_io[i].len-1;
1408 rp->r_io_tab[i] = rp->r_priv.s_io_tab[i];
1409 if(rs_verbose)
1410 printf("RS: edit_slot: I/O [%x..%x]\n",
1411 rp->r_priv.s_io_tab[i].ior_base,
1412 rp->r_priv.s_io_tab[i].ior_limit);
1415 /* Update kernel call mask. Inherit basic kernel calls when asked to. */
1416 memcpy(rp->r_priv.s_k_call_mask, rs_start->rss_system,
1417 sizeof(rp->r_priv.s_k_call_mask));
1418 if(rs_start->rss_flags & RSS_SYS_BASIC_CALLS) {
1419 fill_call_mask(basic_kc, NR_SYS_CALLS,
1420 rp->r_priv.s_k_call_mask, KERNEL_CALL, FALSE);
1423 /* Update VM call mask. Inherit basic VM calls. */
1424 memcpy(rpub->vm_call_mask, rs_start->rss_vm,
1425 sizeof(rpub->vm_call_mask));
1426 if(rs_start->rss_flags & RSS_VM_BASIC_CALLS) {
1427 fill_call_mask(basic_vmc, NR_VM_CALLS,
1428 rpub->vm_call_mask, VM_RQ_BASE, FALSE);
1431 /* Update control labels. */
1432 if(rs_start->rss_nr_control > 0) {
1433 int i, s;
1434 if (rs_start->rss_nr_control > RS_NR_CONTROL) {
1435 printf("RS: edit_slot: too many control labels\n");
1436 return EINVAL;
1438 for (i=0; i<rs_start->rss_nr_control; i++) {
1439 s = copy_label(source, rs_start->rss_control[i].l_addr,
1440 rs_start->rss_control[i].l_len, rp->r_control[i],
1441 sizeof(rp->r_control[i]));
1442 if(s != OK)
1443 return s;
1445 rp->r_nr_control = rs_start->rss_nr_control;
1447 if (rs_verbose) {
1448 printf("RS: edit_slot: control labels:");
1449 for (i=0; i<rp->r_nr_control; i++)
1450 printf(" %s", rp->r_control[i]);
1451 printf("\n");
1455 /* Update signal manager. */
1456 rp->r_priv.s_sig_mgr = rs_start->rss_sigmgr;
1458 /* Update scheduling properties if possible. */
1459 if(rp->r_scheduler != NONE) {
1460 rp->r_scheduler = rs_start->rss_scheduler;
1461 rp->r_priority = rs_start->rss_priority;
1462 rp->r_quantum = rs_start->rss_quantum;
1463 rp->r_cpu = rs_start->rss_cpu;
1466 /* Update command and arguments. */
1467 if (rs_start->rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
1468 s=sys_datacopy(source, (vir_bytes) rs_start->rss_cmd,
1469 SELF, (vir_bytes) rp->r_cmd, rs_start->rss_cmdlen);
1470 if (s != OK) return(s);
1471 rp->r_cmd[rs_start->rss_cmdlen] = '\0'; /* ensure it is terminated */
1472 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
1474 /* Build cmd dependencies: argv and program name. */
1475 build_cmd_dep(rp);
1477 /* Update label if not already set. */
1478 if(!strcmp(rpub->label, "")) {
1479 if(rs_start->rss_label.l_len > 0) {
1480 /* RS_UP caller has supplied a custom label for this service. */
1481 int s = copy_label(source, rs_start->rss_label.l_addr,
1482 rs_start->rss_label.l_len, rpub->label, sizeof(rpub->label));
1483 if(s != OK)
1484 return s;
1485 if(rs_verbose)
1486 printf("RS: edit_slot: using label (custom) '%s'\n", rpub->label);
1487 } else {
1488 /* Default label for the service. */
1489 label = rpub->proc_name;
1490 len= strlen(label);
1491 memcpy(rpub->label, label, len);
1492 rpub->label[len]= '\0';
1493 if(rs_verbose)
1494 printf("RS: edit_slot: using label (from proc_name) '%s'\n",
1495 rpub->label);
1499 /* Update recovery script. */
1500 if (rs_start->rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
1501 if (rs_start->rss_script != NULL && !(rpub->sys_flags & SF_CORE_SRV)) {
1502 s=sys_datacopy(source, (vir_bytes) rs_start->rss_script,
1503 SELF, (vir_bytes) rp->r_script, rs_start->rss_scriptlen);
1504 if (s != OK) return(s);
1505 rp->r_script[rs_start->rss_scriptlen] = '\0';
1508 /* Update system flags and in-memory copy. */
1509 if ((rs_start->rss_flags & RSS_COPY) && !(rpub->sys_flags & SF_USE_COPY)) {
1510 int exst_cpy;
1511 struct rproc *rp2;
1512 struct rprocpub *rpub2;
1513 exst_cpy = 0;
1515 if(rs_start->rss_flags & RSS_REUSE) {
1516 int i;
1518 for(i = 0; i < NR_SYS_PROCS; i++) {
1519 rp2 = &rproc[i];
1520 if (!(rp2->r_flags & RS_IN_USE)) {
1521 continue;
1523 rpub2 = rproc[i].r_pub;
1524 if(strcmp(rpub->proc_name, rpub2->proc_name) == 0 &&
1525 (rpub2->sys_flags & SF_USE_COPY)) {
1526 /* We have found the same binary that's
1527 * already been copied */
1528 exst_cpy = 1;
1529 break;
1534 s = OK;
1535 if(!exst_cpy)
1536 s = read_exec(rp);
1537 else
1538 share_exec(rp, rp2);
1540 if (s != OK)
1541 return s;
1543 rpub->sys_flags |= SF_USE_COPY;
1545 if (rs_start->rss_flags & RSS_REPLICA) {
1546 rpub->sys_flags |= SF_USE_REPL;
1548 if (rs_start->rss_flags & RSS_NO_BIN_EXP) {
1549 rpub->sys_flags |= SF_NO_BIN_EXP;
1552 /* Update period. */
1553 if(rpub->endpoint != RS_PROC_NR) {
1554 rp->r_period = rs_start->rss_period;
1557 /* (Re)initialize privilege settings. */
1558 init_privs(rp, &rp->r_priv);
1560 return OK;
1563 /*===========================================================================*
1564 * init_slot *
1565 *===========================================================================*/
1566 int init_slot(rp, rs_start, source)
1567 struct rproc *rp;
1568 struct rs_start *rs_start;
1569 endpoint_t source;
1571 /* Initialize a slot as requested by the client. */
1572 struct rprocpub *rpub;
1573 int i;
1575 rpub = rp->r_pub;
1577 /* All dynamically created services get the same sys and privilege flags, and
1578 * allowed traps. Other privilege settings can be specified at runtime. The
1579 * privilege id is dynamically allocated by the kernel.
1581 rpub->sys_flags = DSRV_SF; /* system flags */
1582 rp->r_priv.s_flags = DSRV_F; /* privilege flags */
1583 rp->r_priv.s_trap_mask = DSRV_T; /* allowed traps */
1584 rp->r_priv.s_bak_sig_mgr = NONE; /* backup signal manager */
1586 /* Initialize uid. */
1587 rp->r_uid= rs_start->rss_uid;
1589 /* Initialize device driver settings. */
1590 rpub->dev_nr = rs_start->rss_major;
1591 rpub->devman_id = rs_start->devman_id;
1593 /* Initialize pci settings. */
1594 if (rs_start->rss_nr_pci_id > RS_NR_PCI_DEVICE) {
1595 printf("RS: init_slot: too many PCI device IDs\n");
1596 return EINVAL;
1598 rpub->pci_acl.rsp_nr_device = rs_start->rss_nr_pci_id;
1599 for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++) {
1600 rpub->pci_acl.rsp_device[i].vid= rs_start->rss_pci_id[i].vid;
1601 rpub->pci_acl.rsp_device[i].did= rs_start->rss_pci_id[i].did;
1602 rpub->pci_acl.rsp_device[i].sub_vid= rs_start->rss_pci_id[i].sub_vid;
1603 rpub->pci_acl.rsp_device[i].sub_did= rs_start->rss_pci_id[i].sub_did;
1604 if(rs_verbose)
1605 printf("RS: init_slot: PCI %04x/%04x (sub %04x:%04x)\n",
1606 rpub->pci_acl.rsp_device[i].vid,
1607 rpub->pci_acl.rsp_device[i].did,
1608 rpub->pci_acl.rsp_device[i].sub_vid,
1609 rpub->pci_acl.rsp_device[i].sub_did);
1611 if (rs_start->rss_nr_pci_class > RS_NR_PCI_CLASS) {
1612 printf("RS: init_slot: too many PCI class IDs\n");
1613 return EINVAL;
1615 rpub->pci_acl.rsp_nr_class= rs_start->rss_nr_pci_class;
1616 for (i= 0; i<rpub->pci_acl.rsp_nr_class; i++) {
1617 rpub->pci_acl.rsp_class[i].pciclass=rs_start->rss_pci_class[i].pciclass;
1618 rpub->pci_acl.rsp_class[i].mask= rs_start->rss_pci_class[i].mask;
1619 if(rs_verbose)
1620 printf("RS: init_slot: PCI class %06x mask %06x\n",
1621 (unsigned int) rpub->pci_acl.rsp_class[i].pciclass,
1622 (unsigned int) rpub->pci_acl.rsp_class[i].mask);
1625 /* Initialize some fields. */
1626 rp->r_restarts = 0; /* no restarts yet */
1627 rp->r_old_rp = NULL; /* no old version yet */
1628 rp->r_new_rp = NULL; /* no new version yet */
1629 rp->r_prev_rp = NULL; /* no prev replica yet */
1630 rp->r_next_rp = NULL; /* no next replica yet */
1631 rp->r_exec = NULL; /* no in-memory copy yet */
1632 rp->r_exec_len = 0;
1633 rp->r_script[0]= '\0'; /* no recovery script yet */
1634 rpub->label[0]= '\0'; /* no label yet */
1635 rp->r_scheduler = -1; /* no scheduler yet */
1636 rp->r_priv.s_sig_mgr = -1; /* no signal manager yet */
1638 /* Initialize editable slot settings. */
1639 return edit_slot(rp, rs_start, source);
1642 /*===========================================================================*
1643 * clone_slot *
1644 *===========================================================================*/
1645 int clone_slot(rp, clone_rpp)
1646 struct rproc *rp;
1647 struct rproc **clone_rpp;
1649 int r;
1650 struct rproc *clone_rp;
1651 struct rprocpub *rpub, *clone_rpub;
1653 /* Allocate a system service slot for the clone. */
1654 r = alloc_slot(&clone_rp);
1655 if(r != OK) {
1656 printf("RS: clone_slot: unable to allocate a new slot: %d\n", r);
1657 return r;
1660 rpub = rp->r_pub;
1661 clone_rpub = clone_rp->r_pub;
1663 /* Synch the privilege structure of the source with the kernel. */
1664 if ((r = sys_getpriv(&(rp->r_priv), rpub->endpoint)) != OK) {
1665 panic("unable to synch privilege structure: %d", r);
1668 /* Shallow copy. */
1669 *clone_rp = *rp;
1670 *clone_rpub = *rpub;
1672 /* Deep copy. */
1673 clone_rp->r_flags &= ~RS_ACTIVE; /* the clone is not active yet */
1674 clone_rp->r_pid = -1; /* no pid yet */
1675 clone_rpub->endpoint = -1; /* no endpoint yet */
1676 clone_rp->r_pub = clone_rpub; /* restore pointer to public entry */
1677 build_cmd_dep(clone_rp); /* rebuild cmd dependencies */
1678 if(clone_rpub->sys_flags & SF_USE_COPY) {
1679 share_exec(clone_rp, rp); /* share exec image */
1681 clone_rp->r_old_rp = NULL; /* no old version yet */
1682 clone_rp->r_new_rp = NULL; /* no new version yet */
1683 clone_rp->r_prev_rp = NULL; /* no prev replica yet */
1684 clone_rp->r_next_rp = NULL; /* no next replica yet */
1686 /* Force dynamic privilege id. */
1687 clone_rp->r_priv.s_flags |= DYN_PRIV_ID;
1689 /* Clear instance flags. */
1690 clone_rp->r_priv.s_flags &= ~(LU_SYS_PROC | RST_SYS_PROC);
1692 *clone_rpp = clone_rp;
1693 return OK;
1696 /*===========================================================================*
1697 * swap_slot_pointer *
1698 *===========================================================================*/
1699 static void swap_slot_pointer(struct rproc **rpp, struct rproc *src_rp,
1700 struct rproc *dst_rp)
1702 if(*rpp == src_rp) {
1703 *rpp = dst_rp;
1705 else if(*rpp == dst_rp) {
1706 *rpp = src_rp;
1710 /*===========================================================================*
1711 * swap_slot *
1712 *===========================================================================*/
1713 void swap_slot(src_rpp, dst_rpp)
1714 struct rproc **src_rpp;
1715 struct rproc **dst_rpp;
1717 /* Swap two service slots. */
1718 struct rproc *src_rp;
1719 struct rproc *dst_rp;
1720 struct rprocpub *src_rpub;
1721 struct rprocpub *dst_rpub;
1722 struct rproc orig_src_rproc, orig_dst_rproc;
1723 struct rprocpub orig_src_rprocpub, orig_dst_rprocpub;
1725 src_rp = *src_rpp;
1726 dst_rp = *dst_rpp;
1727 src_rpub = src_rp->r_pub;
1728 dst_rpub = dst_rp->r_pub;
1730 /* Save existing data first. */
1731 orig_src_rproc = *src_rp;
1732 orig_src_rprocpub = *src_rpub;
1733 orig_dst_rproc = *dst_rp;
1734 orig_dst_rprocpub = *dst_rpub;
1736 /* Swap slots. */
1737 *src_rp = orig_dst_rproc;
1738 *src_rpub = orig_dst_rprocpub;
1739 *dst_rp = orig_src_rproc;
1740 *dst_rpub = orig_src_rprocpub;
1742 /* Restore public entries. */
1743 src_rp->r_pub = orig_src_rproc.r_pub;
1744 dst_rp->r_pub = orig_dst_rproc.r_pub;
1746 /* Rebuild command dependencies. */
1747 build_cmd_dep(src_rp);
1748 build_cmd_dep(dst_rp);
1750 /* Swap local slot pointers. */
1751 swap_slot_pointer(&src_rp->r_prev_rp, src_rp, dst_rp);
1752 swap_slot_pointer(&src_rp->r_next_rp, src_rp, dst_rp);
1753 swap_slot_pointer(&src_rp->r_old_rp, src_rp, dst_rp);
1754 swap_slot_pointer(&src_rp->r_new_rp, src_rp, dst_rp);
1755 swap_slot_pointer(&dst_rp->r_prev_rp, src_rp, dst_rp);
1756 swap_slot_pointer(&dst_rp->r_next_rp, src_rp, dst_rp);
1757 swap_slot_pointer(&dst_rp->r_old_rp, src_rp, dst_rp);
1758 swap_slot_pointer(&dst_rp->r_new_rp, src_rp, dst_rp);
1760 /* Swap global slot pointers. */
1761 swap_slot_pointer(&rupdate.rp, src_rp, dst_rp);
1762 swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)],
1763 src_rp, dst_rp);
1764 swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)],
1765 src_rp, dst_rp);
1767 /* Adjust input pointers. */
1768 *src_rpp = dst_rp;
1769 *dst_rpp = src_rp;
1772 /*===========================================================================*
1773 * lookup_slot_by_label *
1774 *===========================================================================*/
1775 struct rproc* lookup_slot_by_label(char *label)
1777 /* Lookup a service slot matching the given label. */
1778 int slot_nr;
1779 struct rproc *rp;
1780 struct rprocpub *rpub;
1782 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1783 rp = &rproc[slot_nr];
1784 if (!(rp->r_flags & RS_ACTIVE)) {
1785 continue;
1787 rpub = rp->r_pub;
1788 if (strcmp(rpub->label, label) == 0) {
1789 return rp;
1793 return NULL;
1796 /*===========================================================================*
1797 * lookup_slot_by_pid *
1798 *===========================================================================*/
1799 struct rproc* lookup_slot_by_pid(pid_t pid)
1801 /* Lookup a service slot matching the given pid. */
1802 int slot_nr;
1803 struct rproc *rp;
1805 if(pid < 0) {
1806 return NULL;
1809 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1810 rp = &rproc[slot_nr];
1811 if (!(rp->r_flags & RS_IN_USE)) {
1812 continue;
1814 if (rp->r_pid == pid) {
1815 return rp;
1819 return NULL;
1822 /*===========================================================================*
1823 * lookup_slot_by_dev_nr *
1824 *===========================================================================*/
1825 struct rproc* lookup_slot_by_dev_nr(dev_t dev_nr)
1827 /* Lookup a service slot matching the given device number. */
1828 int slot_nr;
1829 struct rproc *rp;
1830 struct rprocpub *rpub;
1832 if(dev_nr <= 0) {
1833 return NULL;
1836 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1837 rp = &rproc[slot_nr];
1838 rpub = rp->r_pub;
1839 if (!(rp->r_flags & RS_IN_USE)) {
1840 continue;
1842 if (rpub->dev_nr == dev_nr) {
1843 return rp;
1847 return NULL;
1850 /*===========================================================================*
1851 * lookup_slot_by_flags *
1852 *===========================================================================*/
1853 struct rproc* lookup_slot_by_flags(int flags)
1855 /* Lookup a service slot matching the given flags. */
1856 int slot_nr;
1857 struct rproc *rp;
1859 if(!flags) {
1860 return NULL;
1863 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1864 rp = &rproc[slot_nr];
1865 if (!(rp->r_flags & RS_IN_USE)) {
1866 continue;
1868 if (rp->r_flags & flags) {
1869 return rp;
1873 return NULL;
1876 /*===========================================================================*
1877 * alloc_slot *
1878 *===========================================================================*/
1879 int alloc_slot(rpp)
1880 struct rproc **rpp;
1882 /* Alloc a new system service slot. */
1883 int slot_nr;
1885 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
1886 *rpp = &rproc[slot_nr]; /* get pointer to slot */
1887 if (!((*rpp)->r_flags & RS_IN_USE)) /* check if available */
1888 break;
1890 if (slot_nr >= NR_SYS_PROCS) {
1891 return ENOMEM;
1894 return OK;
1897 /*===========================================================================*
1898 * free_slot *
1899 *===========================================================================*/
1900 void free_slot(rp)
1901 struct rproc *rp;
1903 /* Free a system service slot. */
1904 struct rprocpub *rpub;
1906 rpub = rp->r_pub;
1908 /* Send a late reply if there is any pending. */
1909 late_reply(rp, OK);
1911 /* Free memory if necessary. */
1912 if(rpub->sys_flags & SF_USE_COPY) {
1913 free_exec(rp);
1916 /* Mark slot as no longer in use.. */
1917 rp->r_flags = 0;
1918 rp->r_pid = -1;
1919 rpub->in_use = FALSE;
1920 rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
1924 /*===========================================================================*
1925 * get_next_name *
1926 *===========================================================================*/
1927 static char *get_next_name(ptr, name, caller_label)
1928 char *ptr;
1929 char *name;
1930 char *caller_label;
1932 /* Get the next name from the list of (IPC) program names.
1934 char *p, *q;
1935 size_t len;
1937 for (p= ptr; p[0] != '\0'; p= q)
1939 /* Skip leading space */
1940 while (p[0] != '\0' && isspace((unsigned char)p[0]))
1941 p++;
1943 /* Find start of next word */
1944 q= p;
1945 while (q[0] != '\0' && !isspace((unsigned char)q[0]))
1946 q++;
1947 if (q == p)
1948 continue;
1949 len= q-p;
1950 if (len > RS_MAX_LABEL_LEN)
1952 printf(
1953 "rs:get_next_name: bad ipc list entry '%.*s' for %s: too long\n",
1954 len, p, caller_label);
1955 continue;
1957 memcpy(name, p, len);
1958 name[len]= '\0';
1960 return q; /* found another */
1963 return NULL; /* done */
1966 /*===========================================================================*
1967 * add_forward_ipc *
1968 *===========================================================================*/
1969 void add_forward_ipc(rp, privp)
1970 struct rproc *rp;
1971 struct priv *privp;
1973 /* Add IPC send permissions to a process based on that process's IPC
1974 * list.
1976 char name[RS_MAX_LABEL_LEN+1], *p;
1977 struct rproc *rrp;
1978 endpoint_t endpoint;
1979 int r;
1980 int priv_id;
1981 struct priv priv;
1982 struct rprocpub *rpub;
1984 rpub = rp->r_pub;
1985 p = rp->r_ipc_list;
1987 while ((p = get_next_name(p, name, rpub->label)) != NULL) {
1989 if (strcmp(name, "SYSTEM") == 0)
1990 endpoint= SYSTEM;
1991 else if (strcmp(name, "USER") == 0)
1992 endpoint= INIT_PROC_NR; /* all user procs */
1993 else
1995 /* Set a privilege bit for every process matching the
1996 * given process name. It is perfectly fine if this
1997 * loop does not find any matches, as the target
1998 * process(es) may not have been started yet. See
1999 * add_backward_ipc() below.
2001 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
2002 if (!(rrp->r_flags & RS_IN_USE))
2003 continue;
2005 if (!strcmp(rrp->r_pub->proc_name, name)) {
2006 #if PRIV_DEBUG
2007 printf(" RS: add_forward_ipc: setting"
2008 " sendto bit for %d...\n",
2009 rrp->r_pub->endpoint);
2010 #endif
2012 priv_id= rrp->r_priv.s_id;
2013 set_sys_bit(privp->s_ipc_to, priv_id);
2017 continue;
2020 /* This code only applies to the exception cases. */
2021 if ((r = sys_getpriv(&priv, endpoint)) < 0)
2023 printf(
2024 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
2025 name, r);
2026 continue;
2029 #if PRIV_DEBUG
2030 printf(" RS: add_forward_ipc: setting sendto bit for %d...\n",
2031 endpoint);
2032 #endif
2033 priv_id= priv.s_id;
2034 set_sys_bit(privp->s_ipc_to, priv_id);
2039 /*===========================================================================*
2040 * add_backward_ipc *
2041 *===========================================================================*/
2042 void add_backward_ipc(rp, privp)
2043 struct rproc *rp;
2044 struct priv *privp;
2046 /* Add IPC send permissions to a process based on other processes' IPC
2047 * lists. This is enough to allow each such two processes to talk to
2048 * each other, as the kernel guarantees send mask symmetry. We need to
2049 * add these permissions now because the current process may not yet
2050 * have existed at the time that the other process was initialized.
2052 char name[RS_MAX_LABEL_LEN+1], *p;
2053 struct rproc *rrp;
2054 struct rprocpub *rrpub;
2055 char *proc_name;
2056 int priv_id, is_ipc_all, is_ipc_all_sys;
2058 proc_name = rp->r_pub->proc_name;
2060 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
2061 if (!(rrp->r_flags & RS_IN_USE))
2062 continue;
2064 if (!rrp->r_ipc_list[0])
2065 continue;
2067 /* If the process being checked is set to allow IPC to all
2068 * other processes, or for all other system processes and the
2069 * target process is a system process, add a permission bit.
2071 rrpub = rrp->r_pub;
2073 is_ipc_all = !strcmp(rrp->r_ipc_list, RSS_IPC_ALL);
2074 is_ipc_all_sys = !strcmp(rrp->r_ipc_list, RSS_IPC_ALL_SYS);
2076 if (is_ipc_all ||
2077 (is_ipc_all_sys && (privp->s_flags & SYS_PROC))) {
2078 #if PRIV_DEBUG
2079 printf(" RS: add_backward_ipc: setting sendto bit "
2080 "for %d...\n", rrpub->endpoint);
2081 #endif
2082 priv_id= rrp->r_priv.s_id;
2083 set_sys_bit(privp->s_ipc_to, priv_id);
2085 continue;
2088 /* An IPC target list was provided for the process being
2089 * checked here. Make sure that the name of the new process
2090 * is in that process's list. There may be multiple matches.
2092 p = rrp->r_ipc_list;
2094 while ((p = get_next_name(p, name, rrpub->label)) != NULL) {
2095 if (!strcmp(proc_name, name)) {
2096 #if PRIV_DEBUG
2097 printf(" RS: add_backward_ipc: setting sendto"
2098 " bit for %d...\n",
2099 rrpub->endpoint);
2100 #endif
2101 priv_id= rrp->r_priv.s_id;
2102 set_sys_bit(privp->s_ipc_to, priv_id);
2109 /*===========================================================================*
2110 * init_privs *
2111 *===========================================================================*/
2112 void init_privs(rp, privp)
2113 struct rproc *rp;
2114 struct priv *privp;
2116 int i;
2117 int is_ipc_all, is_ipc_all_sys;
2119 /* Clear s_ipc_to */
2120 fill_send_mask(&privp->s_ipc_to, FALSE);
2122 is_ipc_all = !strcmp(rp->r_ipc_list, RSS_IPC_ALL);
2123 is_ipc_all_sys = !strcmp(rp->r_ipc_list, RSS_IPC_ALL_SYS);
2125 #if PRIV_DEBUG
2126 printf(" RS: init_privs: ipc list is '%s'...\n", rp->r_ipc_list);
2127 #endif
2129 if (!is_ipc_all && !is_ipc_all_sys)
2131 add_forward_ipc(rp, privp);
2132 add_backward_ipc(rp, privp);
2135 else
2137 for (i= 0; i<NR_SYS_PROCS; i++)
2139 if (is_ipc_all || i != USER_PRIV_ID)
2140 set_sys_bit(privp->s_ipc_to, i);