opendir change: refinement
[minix.git] / servers / rs / manager.c
blob9b4d69030fba5e2abfd19353eaa688631d9d2dd9
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 "inc.h"
12 #include "kernel/proc.h"
14 /*===========================================================================*
15 * caller_is_root *
16 *===========================================================================*/
17 static int caller_is_root(endpoint)
18 endpoint_t endpoint; /* caller endpoint */
20 uid_t euid;
22 /* Check if caller has root user ID. */
23 euid = getnuid(endpoint);
24 if (rs_verbose && euid != 0)
26 printf("RS: got unauthorized request from endpoint %d\n", endpoint);
29 return euid == 0;
32 /*===========================================================================*
33 * caller_can_control *
34 *===========================================================================*/
35 static int caller_can_control(endpoint, target_rp)
36 endpoint_t endpoint;
37 struct rproc *target_rp;
39 int control_allowed = 0;
40 register struct rproc *rp;
41 register struct rprocpub *rpub;
42 char *proc_name;
43 int c;
45 proc_name = target_rp->r_pub->proc_name;
47 /* Check if label is listed in caller's isolation policy. */
48 for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) {
49 if (!(rp->r_flags & RS_IN_USE))
50 continue;
52 rpub = rp->r_pub;
53 if (rpub->endpoint == endpoint) {
54 break;
57 if (rp == END_RPROC_ADDR) return 0;
59 for (c = 0; c < rp->r_nr_control; c++) {
60 if (strcmp(rp->r_control[c], proc_name) == 0) {
61 control_allowed = 1;
62 break;
66 if (rs_verbose)
67 printf("RS: allowing %u control over %s via policy: %s\n",
68 endpoint, target_rp->r_pub->label,
69 control_allowed ? "yes" : "no");
71 return control_allowed;
74 /*===========================================================================*
75 * check_call_permission *
76 *===========================================================================*/
77 int check_call_permission(caller, call, rp)
78 endpoint_t caller;
79 int call;
80 struct rproc *rp;
82 /* Check if the caller has permission to execute a particular call. */
83 struct rprocpub *rpub;
84 int call_allowed;
86 /* Caller should be either root or have control privileges. */
87 call_allowed = caller_is_root(caller);
88 if(rp) {
89 call_allowed |= caller_can_control(caller, rp);
91 if(!call_allowed) {
92 return EPERM;
95 if(rp) {
96 rpub = rp->r_pub;
98 /* Only allow RS_EDIT if the target is a user process. */
99 if(!(rp->r_priv.s_flags & SYS_PROC)) {
100 if(call != RS_EDIT) return EPERM;
103 /* Disallow the call if another call is in progress for the service. */
104 if((rp->r_flags & RS_LATEREPLY)
105 || (rp->r_flags & RS_INITIALIZING) || (rp->r_flags & RS_UPDATING)) {
106 return EBUSY;
109 /* Only allow RS_DOWN and RS_RESTART if the service has terminated. */
110 if(rp->r_flags & RS_TERMINATED) {
111 if(call != RS_DOWN && call != RS_RESTART) return EPERM;
114 /* Disallow RS_DOWN for core system services. */
115 if (rpub->sys_flags & SF_CORE_SRV) {
116 if(call == RS_DOWN) return EPERM;
120 return OK;
123 /*===========================================================================*
124 * copy_rs_start *
125 *===========================================================================*/
126 int copy_rs_start(src_e, src_rs_start, dst_rs_start)
127 endpoint_t src_e;
128 char *src_rs_start;
129 struct rs_start *dst_rs_start;
131 int r;
133 r = sys_datacopy(src_e, (vir_bytes) src_rs_start,
134 SELF, (vir_bytes) dst_rs_start, sizeof(struct rs_start));
136 return r;
139 /*===========================================================================*
140 * copy_label *
141 *===========================================================================*/
142 int copy_label(src_e, src_label, src_len, dst_label, dst_len)
143 endpoint_t src_e;
144 char *src_label;
145 size_t src_len;
146 char *dst_label;
147 size_t dst_len;
149 int s, len;
151 len = MIN(dst_len-1, src_len);
153 s = sys_datacopy(src_e, (vir_bytes) src_label,
154 SELF, (vir_bytes) dst_label, len);
155 if (s != OK) return s;
157 dst_label[len] = 0;
159 return OK;
162 /*===========================================================================*
163 * build_cmd_dep *
164 *===========================================================================*/
165 void build_cmd_dep(struct rproc *rp)
167 struct rprocpub *rpub;
168 int arg_count;
169 int len;
170 char *cmd_ptr;
172 rpub = rp->r_pub;
174 /* Build argument vector to be passed to execute call. The format of the
175 * arguments vector is: path, arguments, NULL.
177 strcpy(rp->r_args, rp->r_cmd); /* copy raw command */
178 arg_count = 0; /* initialize arg count */
179 rp->r_argv[arg_count++] = rp->r_args; /* start with path */
180 cmd_ptr = rp->r_args; /* do some parsing */
181 while(*cmd_ptr != '\0') { /* stop at end of string */
182 if (*cmd_ptr == ' ') { /* next argument */
183 *cmd_ptr = '\0'; /* terminate previous */
184 while (*++cmd_ptr == ' ') ; /* skip spaces */
185 if (*cmd_ptr == '\0') break; /* no arg following */
186 /* There are ARGV_ELEMENTS elements; must leave one for null */
187 if (arg_count>=ARGV_ELEMENTS-1) { /* arg vector full */
188 printf("RS: build_cmd_dep: too many args\n");
189 break;
191 assert(arg_count < ARGV_ELEMENTS);
192 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
194 cmd_ptr ++; /* continue parsing */
196 assert(arg_count < ARGV_ELEMENTS);
197 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
198 rp->r_argc = arg_count;
200 /* Build process name. */
201 cmd_ptr = strrchr(rp->r_argv[0], '/');
202 if (cmd_ptr)
203 cmd_ptr++;
204 else
205 cmd_ptr= rp->r_argv[0];
206 len= strlen(cmd_ptr);
207 if (len > RS_MAX_LABEL_LEN-1)
208 len= RS_MAX_LABEL_LEN-1; /* truncate name */
209 memcpy(rpub->proc_name, cmd_ptr, len);
210 rpub->proc_name[len]= '\0';
213 /*===========================================================================*
214 * srv_fork *
215 *===========================================================================*/
216 pid_t srv_fork(uid_t reuid, gid_t regid)
218 message m;
220 m.m1_i1 = (int) reuid;
221 m.m1_i2 = (int) regid;
222 return _syscall(PM_PROC_NR, SRV_FORK, &m);
225 /*===========================================================================*
226 * srv_kill *
227 *===========================================================================*/
228 int srv_kill(pid_t pid, int sig)
230 message m;
232 m.m1_i1 = pid;
233 m.m1_i2 = sig;
234 return(_syscall(PM_PROC_NR, SRV_KILL, &m));
237 /*===========================================================================*
238 * srv_update *
239 *===========================================================================*/
240 int srv_update(endpoint_t src_e, endpoint_t dst_e)
242 int r;
244 /* Ask VM to swap the slots of the two processes and tell the kernel to
245 * do the same. If VM is the service being updated, only perform the kernel
246 * part of the call. The new instance of VM will do the rest at
247 * initialization time.
249 if(src_e != VM_PROC_NR) {
250 r = vm_update(src_e, dst_e);
252 else {
253 r = sys_update(src_e, dst_e);
256 return r;
259 /*===========================================================================*
260 * update_period *
261 *===========================================================================*/
262 void update_period(message *m_ptr)
264 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
265 short has_update_timed_out;
266 message m;
267 struct rprocpub *rpub;
269 rpub = rupdate.rp->r_pub;
271 /* See if a timeout has occurred. */
272 has_update_timed_out = (now - rupdate.prepare_tm > rupdate.prepare_maxtime);
274 /* If an update timed out, end the update process and notify
275 * the old version that the update has been canceled. From now on, the old
276 * version will continue executing.
278 if(has_update_timed_out) {
279 printf("RS: update failed: maximum prepare time reached\n");
280 end_update(EINTR, RS_DONTREPLY);
282 /* Prepare cancel request. */
283 m.m_type = RS_LU_PREPARE;
284 m.RS_LU_STATE = SEF_LU_STATE_NULL;
285 if(rpub->endpoint == RS_PROC_NR) {
286 /* RS can process the request directly. */
287 do_sef_lu_request(&m);
289 else {
290 /* Send request message to the system service. */
291 asynsend(rpub->endpoint, &m);
296 /*===========================================================================*
297 * end_update *
298 *===========================================================================*/
299 void end_update(int result, int reply_flag)
301 /* End the update process. There are two possibilities:
302 * 1) the update succeeded. In that case, cleanup the old version and mark the
303 * new version as no longer under update.
304 * 2) the update failed. In that case, cleanup the new version and mark the old
305 * version as no longer under update. Eventual late ready to update
306 * messages (if any) will simply be ignored and the service can
307 * continue executing. In addition, reset the check timestamp, so that if the
308 * service has a period, a status request will be forced in the next period.
310 struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp;
311 struct rproc **rps;
312 int nr_rps, i;
314 old_rp = rupdate.rp;
315 new_rp = old_rp->r_new_rp;
317 if(rs_verbose)
318 printf("RS: ending update from %s to %s with result: %d\n",
319 srv_to_string(old_rp), srv_to_string(new_rp), result);
321 /* Decide which version has to die out and which version has to survive. */
322 surviving_rp = (result == OK ? new_rp : old_rp);
323 exiting_rp = (result == OK ? old_rp : new_rp);
325 /* End update. */
326 rupdate.flags &= ~RS_UPDATING;
327 rupdate.rp = NULL;
328 old_rp->r_new_rp = NULL;
329 new_rp->r_old_rp = NULL;
330 old_rp->r_check_tm = 0;
332 /* Send a late reply if necessary. */
333 late_reply(old_rp, result);
335 /* Mark the version that has to survive as no longer updating and
336 * reply when asked to.
338 surviving_rp->r_flags &= ~RS_UPDATING;
339 if(reply_flag == RS_REPLY) {
340 message m;
341 m.m_type = result;
342 reply(surviving_rp->r_pub->endpoint, surviving_rp, &m);
345 /* Cleanup the version that has to die out. */
346 get_service_instances(exiting_rp, &rps, &nr_rps);
347 for(i=0;i<nr_rps;i++) {
348 cleanup_service(rps[i]);
351 if(rs_verbose)
352 printf("RS: %s ended the update\n", srv_to_string(surviving_rp));
355 /*===========================================================================*
356 * kill_service_debug *
357 *===========================================================================*/
358 int kill_service_debug(file, line, rp, errstr, err)
359 char *file;
360 int line;
361 struct rproc *rp;
362 char *errstr;
363 int err;
365 /* Crash a system service and don't let it restart. */
366 if(errstr && !shutting_down) {
367 printf("RS: %s (error %d)\n", errstr, err);
369 rp->r_flags |= RS_EXITING; /* expect exit */
370 crash_service_debug(file, line, rp); /* simulate crash */
372 return err;
375 /*===========================================================================*
376 * crash_service_debug *
377 *===========================================================================*/
378 int crash_service_debug(file, line, rp)
379 char *file;
380 int line;
381 struct rproc *rp;
383 /* Simluate a crash in a system service. */
384 struct rprocpub *rpub;
386 rpub = rp->r_pub;
388 if(rs_verbose)
389 printf("RS: %s %skilled at %s:%d\n", srv_to_string(rp),
390 rp->r_flags & RS_EXITING ? "lethally " : "", file, line);
392 /* RS should simply exit() directly. */
393 if(rpub->endpoint == RS_PROC_NR) {
394 exit(1);
397 return sys_kill(rpub->endpoint, SIGKILL);
400 /*===========================================================================*
401 * cleanup_service_debug *
402 *===========================================================================*/
403 void cleanup_service_debug(file, line, rp)
404 char *file;
405 int line;
406 struct rproc *rp;
408 struct rprocpub *rpub;
409 int s;
411 rpub = rp->r_pub;
413 if(rs_verbose)
414 printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp),
415 file, line);
417 /* Tell scheduler this process is finished */
418 if ((s = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) {
419 printf("RS: warning: scheduler won't give up process: %d\n", s);
422 /* Ask PM to exit the service */
423 if(rp->r_pid == -1) {
424 printf("RS: warning: attempt to kill pid -1!\n");
426 else {
427 srv_kill(rp->r_pid, SIGKILL);
430 /* Free slot, unless we're about to reuse it */
431 if (!(rp->r_flags & RS_REINCARNATE))
432 free_slot(rp);
435 /*===========================================================================*
436 * create_service *
437 *===========================================================================*/
438 int create_service(rp)
439 struct rproc *rp;
441 /* Create the given system service. */
442 int child_proc_nr_e, child_proc_nr_n; /* child process slot */
443 pid_t child_pid; /* child's process id */
444 int s, use_copy, has_replica;
445 extern char **environ;
446 struct rprocpub *rpub;
448 rpub = rp->r_pub;
449 use_copy= (rpub->sys_flags & SF_USE_COPY);
450 has_replica= (rp->r_old_rp
451 || (rp->r_prev_rp && !(rp->r_prev_rp->r_flags & RS_TERMINATED)));
453 /* Do we need an existing replica to create the service? */
454 if(!has_replica && (rpub->sys_flags & SF_NEED_REPL)) {
455 printf("RS: unable to create service '%s' without a replica\n",
456 rpub->label);
457 free_slot(rp);
458 return(EPERM);
461 /* Do we need an in-memory copy to create the service? */
462 if(!use_copy && (rpub->sys_flags & SF_NEED_COPY)) {
463 printf("RS: unable to create service '%s' without an in-memory copy\n",
464 rpub->label);
465 free_slot(rp);
466 return(EPERM);
469 /* Do we have a copy or a command to create the service? */
470 if(!use_copy && !strcmp(rp->r_cmd, "")) {
471 printf("RS: unable to create service '%s' without a copy or command\n",
472 rpub->label);
473 free_slot(rp);
474 return(EPERM);
477 /* Now fork and branch for parent and child process (and check for error).
478 * After fork()ing, we need to pin RS memory again or pagefaults will occur
479 * on future writes.
481 if(rs_verbose)
482 printf("RS: forking child with srv_fork()...\n");
483 child_pid= srv_fork(rp->r_uid, 0); /* Force group to operator for now */
484 if(child_pid == -1) {
485 printf("RS: srv_fork() failed (error %d)\n", errno);
486 free_slot(rp);
487 return(errno);
490 /* Get endpoint of the child. */
491 child_proc_nr_e = getnprocnr(child_pid);
493 /* There is now a child process. Update the system process table. */
494 child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
495 rp->r_flags = RS_IN_USE; /* mark slot in use */
496 rpub->endpoint = child_proc_nr_e; /* set child endpoint */
497 rp->r_pid = child_pid; /* set child pid */
498 rp->r_check_tm = 0; /* not checked yet */
499 getuptime(&rp->r_alive_tm); /* currently alive */
500 rp->r_stop_tm = 0; /* not exiting yet */
501 rp->r_backoff = 0; /* not to be restarted */
502 rproc_ptr[child_proc_nr_n] = rp; /* mapping for fast access */
503 rpub->in_use = TRUE; /* public entry is now in use */
505 /* Set and synch the privilege structure for the new service. */
506 if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_SET_SYS, &rp->r_priv)) != OK
507 || (s = sys_getpriv(&rp->r_priv, child_proc_nr_e)) != OK) {
508 printf("RS: unable to set privilege structure: %d\n", s);
509 cleanup_service(rp);
510 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
511 return ENOMEM;
514 /* Set the scheduler for this process */
515 if ((s = sched_init_proc(rp)) != OK) {
516 printf("RS: unable to start scheduling: %d\n", s);
517 cleanup_service(rp);
518 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
519 return s;
522 /* Copy the executable image into the child process. If no copy exists,
523 * allocate one and free it right after exec completes.
525 if(use_copy) {
526 if(rs_verbose)
527 printf("RS: %s uses an in-memory copy\n",
528 srv_to_string(rp));
530 else {
531 if ((s = read_exec(rp)) != OK) {
532 printf("RS: read_exec failed: %d\n", s);
533 cleanup_service(rp);
534 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
535 return s;
538 if(rs_verbose)
539 printf("RS: execing child with srv_execve()...\n");
540 s = srv_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
541 environ);
542 vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN);
543 if (s != OK) {
544 printf("RS: srv_execve failed: %d\n", s);
545 cleanup_service(rp);
546 return s;
548 if(!use_copy) {
549 free_exec(rp);
552 /* If this is a VM instance, let VM know now. */
553 if(rp->r_priv.s_flags & VM_SYS_PROC) {
554 if(rs_verbose)
555 printf("RS: informing VM of instance %s\n", srv_to_string(rp));
557 s = vm_memctl(rpub->endpoint, VM_RS_MEM_MAKE_VM);
558 if(s != OK) {
559 printf("vm_memctl failed: %d\n", s);
560 cleanup_service(rp);
561 return s;
565 /* Tell VM about allowed calls. */
566 if ((s = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0])) != OK) {
567 printf("RS: vm_set_priv failed: %d\n", s);
568 cleanup_service(rp);
569 return s;
572 if(rs_verbose)
573 printf("RS: %s created\n", srv_to_string(rp));
575 return OK;
578 /*===========================================================================*
579 * clone_service *
580 *===========================================================================*/
581 int clone_service(rp, instance_flag)
582 struct rproc *rp;
583 int instance_flag;
585 /* Clone the given system service instance. */
586 struct rproc *replica_rp;
587 struct rprocpub *replica_rpub;
588 struct rproc **rp_link;
589 struct rproc **replica_link;
590 struct rproc *rs_rp;
591 int rs_flags;
592 int r;
594 if(rs_verbose)
595 printf("RS: creating a replica for %s\n", srv_to_string(rp));
597 /* Clone slot. */
598 if((r = clone_slot(rp, &replica_rp)) != OK) {
599 return r;
601 replica_rpub = replica_rp->r_pub;
603 /* Clone is a live updated or restarted service instance? */
604 if(instance_flag == LU_SYS_PROC) {
605 rp_link = &rp->r_new_rp;
606 replica_link = &replica_rp->r_old_rp;
608 else {
609 rp_link = &rp->r_next_rp;
610 replica_link = &replica_rp->r_prev_rp;
612 replica_rp->r_priv.s_flags |= instance_flag;
614 /* Link the two slots. */
615 *rp_link = replica_rp;
616 *replica_link = rp;
618 /* Create a new replica of the service. */
619 r = create_service(replica_rp);
620 if(r != OK) {
621 *rp_link = NULL;
622 return r;
625 /* If this instance is for restarting RS, set up a backup signal manager. */
626 rs_flags = (ROOT_SYS_PROC | RST_SYS_PROC);
627 if((replica_rp->r_priv.s_flags & rs_flags) == rs_flags) {
628 rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
630 /* Update signal managers. */
631 r = update_sig_mgrs(rs_rp, SELF, replica_rpub->endpoint);
632 if(r == OK) {
633 r = update_sig_mgrs(replica_rp, SELF, NONE);
635 if(r != OK) {
636 *rp_link = NULL;
637 return kill_service(replica_rp, "update_sig_mgrs failed", r);
641 return OK;
644 /*===========================================================================*
645 * publish_service *
646 *===========================================================================*/
647 int publish_service(rp)
648 struct rproc *rp; /* pointer to service slot */
650 /* Publish a service. */
651 int r;
652 struct rprocpub *rpub;
653 struct rs_pci pci_acl;
654 message m;
655 endpoint_t ep;
657 rpub = rp->r_pub;
659 /* Register label with DS. */
660 r = ds_publish_label(rpub->label, rpub->endpoint, DSF_OVERWRITE);
661 if (r != OK) {
662 return kill_service(rp, "ds_publish_label call failed", r);
665 /* If the service is a driver, map it. */
666 if (rpub->dev_nr > 0) {
667 /* The purpose of non-blocking forks is to avoid involving VFS in the
668 * forking process, because VFS may be blocked on a sendrec() to a MFS
669 * that is waiting for a endpoint update for a dead driver. We have just
670 * published that update, but VFS may still be blocked. As a result, VFS
671 * may not yet have received PM's fork message. Hence, if we call
672 * mapdriver() immediately, VFS may not know about the process and thus
673 * refuse to add the driver entry. The following temporary hack works
674 * around this by forcing blocking communication from PM to VFS. Once VFS
675 * has been made non-blocking towards MFS instances, this hack and the
676 * big part of srv_fork() can go.
678 setuid(0);
680 if (mapdriver(rpub->label, rpub->dev_nr, rpub->dev_style,
681 rpub->dev_flags) != OK) {
682 return kill_service(rp, "couldn't map driver", errno);
686 #if USE_PCI
687 /* If PCI properties are set, inform the PCI driver about the new service. */
688 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
689 pci_acl = rpub->pci_acl;
690 strcpy(pci_acl.rsp_label, rpub->label);
691 pci_acl.rsp_endpoint= rpub->endpoint;
693 r = pci_set_acl(&pci_acl);
694 if (r != OK) {
695 return kill_service(rp, "pci_set_acl call failed", r);
698 #endif /* USE_PCI */
700 if (rpub->devman_id != 0) {
701 r = ds_retrieve_label_endpt("devman",&ep);
703 if (r != OK) {
704 return kill_service(rp, "devman not running?", r);
706 m.m_type = DEVMAN_BIND;
707 m.DEVMAN_ENDPOINT = rpub->endpoint;
708 m.DEVMAN_DEVICE_ID = rpub->devman_id;
709 r = sendrec(ep, &m);
710 if (r != OK || m.DEVMAN_RESULT != OK) {
711 return kill_service(rp, "devman bind device failed", r);
715 if(rs_verbose)
716 printf("RS: %s published\n", srv_to_string(rp));
718 return OK;
721 /*===========================================================================*
722 * unpublish_service *
723 *===========================================================================*/
724 int unpublish_service(rp)
725 struct rproc *rp; /* pointer to service slot */
727 /* Unpublish a service. */
728 struct rprocpub *rpub;
729 int r, result;
730 message m;
731 endpoint_t ep;
734 rpub = rp->r_pub;
735 result = OK;
737 /* Unregister label with DS. */
738 r = ds_delete_label(rpub->label);
739 if (r != OK && !shutting_down) {
740 printf("RS: ds_delete_label call failed (error %d)\n", r);
741 result = r;
744 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
746 #if USE_PCI
747 /* If PCI properties are set, inform the PCI driver. */
748 if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
749 r = pci_del_acl(rpub->endpoint);
750 if (r != OK && !shutting_down) {
751 printf("RS: pci_del_acl call failed (error %d)\n", r);
752 result = r;
755 #endif /* USE_PCI */
757 if (rpub->devman_id != 0) {
758 r = ds_retrieve_label_endpt("devman",&ep);
760 if (r != OK) {
761 printf("RS: devman not running?");
762 } else {
763 m.m_type = DEVMAN_UNBIND;
764 m.DEVMAN_ENDPOINT = rpub->endpoint;
765 m.DEVMAN_DEVICE_ID = rpub->devman_id;
766 r = sendrec(ep, &m);
768 if (r != OK || m.DEVMAN_RESULT != OK) {
769 printf("RS: devman unbind device failed");
774 if(rs_verbose)
775 printf("RS: %s unpublished\n", srv_to_string(rp));
777 return result;
780 /*===========================================================================*
781 * run_service *
782 *===========================================================================*/
783 int run_service(rp, init_type)
784 struct rproc *rp;
785 int init_type;
787 /* Let a newly created service run. */
788 struct rprocpub *rpub;
789 int s;
791 rpub = rp->r_pub;
793 /* Allow the service to run. */
794 if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
795 return kill_service(rp, "unable to allow the service to run",s);
798 /* Initialize service. */
799 if((s = init_service(rp, init_type)) != OK) {
800 return kill_service(rp, "unable to initialize service", s);
803 if(rs_verbose)
804 printf("RS: %s allowed to run\n", srv_to_string(rp));
806 return OK;
809 /*===========================================================================*
810 * start_service *
811 *===========================================================================*/
812 int start_service(rp)
813 struct rproc *rp;
815 /* Start a system service. */
816 int r, init_type;
817 struct rprocpub *rpub;
819 rpub = rp->r_pub;
821 /* Create and make active. */
822 r = create_service(rp);
823 if(r != OK) {
824 return r;
826 activate_service(rp, NULL);
828 /* Publish service properties. */
829 r = publish_service(rp);
830 if (r != OK) {
831 return r;
834 /* Run. */
835 init_type = SEF_INIT_FRESH;
836 r = run_service(rp, init_type);
837 if(r != OK) {
838 return r;
841 if(rs_verbose)
842 printf("RS: %s started with major %d\n", srv_to_string(rp),
843 rpub->dev_nr);
845 return OK;
848 /*===========================================================================*
849 * stop_service *
850 *===========================================================================*/
851 void stop_service(struct rproc *rp,int how)
853 struct rprocpub *rpub;
854 int signo;
856 rpub = rp->r_pub;
858 /* Try to stop the system service. First send a SIGTERM signal to ask the
859 * system service to terminate. If the service didn't install a signal
860 * handler, it will be killed. If it did and ignores the signal, we'll
861 * find out because we record the time here and send a SIGKILL.
863 if(rs_verbose)
864 printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp));
866 signo = rpub->endpoint != RS_PROC_NR ? SIGTERM : SIGHUP; /* SIGHUP for RS. */
868 rp->r_flags |= how; /* what to on exit? */
869 sys_kill(rpub->endpoint, signo); /* first try friendly */
870 getuptime(&rp->r_stop_tm); /* record current time */
873 /*===========================================================================*
874 * update_service *
875 *===========================================================================*/
876 int update_service(src_rpp, dst_rpp, swap_flag)
877 struct rproc **src_rpp;
878 struct rproc **dst_rpp;
879 int swap_flag;
881 /* Update an existing service. */
882 int r;
883 struct rproc *src_rp;
884 struct rproc *dst_rp;
885 struct rprocpub *src_rpub;
886 struct rprocpub *dst_rpub;
887 int pid;
888 endpoint_t endpoint;
890 src_rp = *src_rpp;
891 dst_rp = *dst_rpp;
892 src_rpub = src_rp->r_pub;
893 dst_rpub = dst_rp->r_pub;
895 if(rs_verbose)
896 printf("RS: %s updating into %s\n",
897 srv_to_string(src_rp), srv_to_string(dst_rp));
899 /* Swap the slots of the two processes when asked to. */
900 if(swap_flag == RS_SWAP) {
901 if((r = srv_update(src_rpub->endpoint, dst_rpub->endpoint)) != OK) {
902 return r;
906 /* Swap slots here as well. */
907 pid = src_rp->r_pid;
908 endpoint = src_rpub->endpoint;
909 swap_slot(&src_rp, &dst_rp);
911 /* Reassign pids and endpoints. */
912 src_rp->r_pid = dst_rp->r_pid;
913 src_rp->r_pub->endpoint = dst_rp->r_pub->endpoint;
914 rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)] = src_rp;
915 dst_rp->r_pid = pid;
916 dst_rp->r_pub->endpoint = endpoint;
917 rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)] = dst_rp;
919 /* Adjust input pointers. */
920 *src_rpp = src_rp;
921 *dst_rpp = dst_rp;
923 /* Make the new version active. */
924 activate_service(dst_rp, src_rp);
926 if(rs_verbose)
927 printf("RS: %s updated into %s\n",
928 srv_to_string(src_rp), srv_to_string(dst_rp));
930 return OK;
933 /*===========================================================================*
934 * activate_service *
935 *===========================================================================*/
936 void activate_service(struct rproc *rp, struct rproc *ex_rp)
938 /* Activate a service instance and deactivate another one if requested. */
940 if(ex_rp && (ex_rp->r_flags & RS_ACTIVE) ) {
941 ex_rp->r_flags &= ~RS_ACTIVE;
942 if(rs_verbose)
943 printf("RS: %s becomes inactive\n", srv_to_string(ex_rp));
946 if(! (rp->r_flags & RS_ACTIVE) ) {
947 rp->r_flags |= RS_ACTIVE;
948 if(rs_verbose)
949 printf("RS: %s becomes active\n", srv_to_string(rp));
953 /*===========================================================================*
954 * reincarnate_service *
955 *===========================================================================*/
956 void reincarnate_service(struct rproc *rp)
958 /* Restart a service as if it were never started before. */
959 struct rprocpub *rpub;
960 int i;
962 rpub = rp->r_pub;
964 rp->r_flags &= RS_IN_USE;
965 rp->r_pid = -1;
966 rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
968 /* Restore original IRQ and I/O range tables in the priv struct. This is the
969 * only part of the privilege structure that can be modified by processes
970 * other than RS itself.
972 rp->r_priv.s_nr_irq = rp->r_nr_irq;
973 for (i = 0; i < rp->r_nr_irq; i++)
974 rp->r_priv.s_irq_tab[i] = rp->r_irq_tab[i];
975 rp->r_priv.s_nr_io_range = rp->r_nr_io_range;
976 for (i = 0; i < rp->r_nr_io_range; i++)
977 rp->r_priv.s_io_tab[i] = rp->r_io_tab[i];
979 rp->r_old_rp = NULL;
980 rp->r_new_rp = NULL;
981 rp->r_prev_rp = NULL;
982 rp->r_next_rp = NULL;
984 start_service(rp);
987 /*===========================================================================*
988 * terminate_service *
989 *===========================================================================*/
990 void terminate_service(struct rproc *rp)
992 /* Handle a termination event for a system service. */
993 struct rproc **rps;
994 struct rprocpub *rpub;
995 int nr_rps;
996 int i, r;
998 rpub = rp->r_pub;
1000 if(rs_verbose)
1001 printf("RS: %s terminated\n", srv_to_string(rp));
1003 /* Deal with failures during initialization. */
1004 if(rp->r_flags & RS_INITIALIZING) {
1005 if(rs_verbose)
1006 printf("RS: service '%s' exited during initialization\n",
1007 rpub->label);
1008 rp->r_flags |= RS_EXITING; /* don't restart. */
1010 /* If updating, rollback. */
1011 if(rp->r_flags & RS_UPDATING) {
1012 struct rproc *old_rp, *new_rp;
1013 printf("RS: update failed: state transfer failed. Rolling back...\n");
1014 new_rp = rp;
1015 old_rp = new_rp->r_old_rp;
1016 new_rp->r_flags &= ~RS_INITIALIZING;
1017 r = update_service(&new_rp, &old_rp, RS_SWAP);
1018 assert(r == OK); /* can't fail */
1019 end_update(ERESTART, RS_REPLY);
1020 return;
1024 if (rp->r_flags & RS_EXITING) {
1025 /* If a core system service is exiting, we are in trouble. */
1026 if (rp->r_pub->sys_flags & SF_CORE_SRV && !shutting_down) {
1027 printf("core system service died: %s\n", srv_to_string(rp));
1028 _exit(1);
1031 /* See if a late reply has to be sent. */
1032 r = (rp->r_caller_request == RS_DOWN ? OK : EDEADEPT);
1033 late_reply(rp, r);
1035 /* Unpublish the service. */
1036 unpublish_service(rp);
1038 /* Cleanup all the instances of the service. */
1039 get_service_instances(rp, &rps, &nr_rps);
1040 for(i=0;i<nr_rps;i++) {
1041 cleanup_service(rps[i]);
1044 /* If the service is reincarnating, its slot has not been cleaned up.
1045 * Check for this flag now, and attempt to start the service again.
1046 * If this fails, start_service() itself will perform cleanup.
1048 if (rp->r_flags & RS_REINCARNATE) {
1049 reincarnate_service(rp);
1052 else if(rp->r_flags & RS_REFRESHING) {
1053 /* Restart service. */
1054 restart_service(rp);
1056 else {
1057 /* If an update is in progress, end it. The old version
1058 * that just exited will continue executing.
1060 if(rp->r_flags & RS_UPDATING) {
1061 end_update(ERESTART, RS_DONTREPLY);
1064 /* Determine what to do. If this is the first unexpected
1065 * exit, immediately restart this service. Otherwise use
1066 * a binary exponential backoff.
1068 if (rp->r_restarts > 0) {
1069 rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
1070 rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
1071 if ((rpub->sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
1072 rp->r_backoff= 1;
1073 return;
1076 /* Restart service. */
1077 restart_service(rp);
1081 /*===========================================================================*
1082 * run_script *
1083 *===========================================================================*/
1084 static int run_script(struct rproc *rp)
1086 int r, endpoint;
1087 pid_t pid;
1088 char *reason;
1089 char incarnation_str[20]; /* Enough for a counter? */
1090 char *envp[1] = { NULL };
1091 struct rprocpub *rpub;
1093 rpub = rp->r_pub;
1094 if (rp->r_flags & RS_REFRESHING)
1095 reason= "restart";
1096 else if (rp->r_flags & RS_NOPINGREPLY)
1097 reason= "no-heartbeat";
1098 else reason= "terminated";
1099 sprintf(incarnation_str, "%d", rp->r_restarts);
1101 if(rs_verbose) {
1102 printf("RS: %s:\n", srv_to_string(rp));
1103 printf("RS: calling script '%s'\n", rp->r_script);
1104 printf("RS: reason: '%s'\n", reason);
1105 printf("RS: incarnation: '%s'\n", incarnation_str);
1108 pid= fork();
1109 switch(pid)
1111 case -1:
1112 return kill_service(rp, "unable to fork script", errno);
1113 case 0:
1114 execle(_PATH_BSHELL, "sh", rp->r_script, rpub->label, reason,
1115 incarnation_str, (char*) NULL, envp);
1116 printf("RS: run_script: execl '%s' failed: %s\n",
1117 rp->r_script, strerror(errno));
1118 exit(1);
1119 default:
1120 /* Set the privilege structure for the child process. */
1121 endpoint = getnprocnr(pid);
1122 if ((r = sys_privctl(endpoint, SYS_PRIV_SET_USER, NULL))
1123 != OK) {
1124 return kill_service(rp,"can't set script privileges",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_flags = def_rpub->dev_flags;
1208 rpub->dev_nr = def_rpub->dev_nr;
1209 rpub->dev_style = def_rpub->dev_style;
1210 rpub->dev_style2 = def_rpub->dev_style2;
1211 rpub->pci_acl = def_rpub->pci_acl;
1213 /* Immutable system and privilege flags. */
1214 rpub->sys_flags &= ~IMM_SF;
1215 rpub->sys_flags |= (def_rpub->sys_flags & IMM_SF);
1216 rp->r_priv.s_flags &= ~IMM_F;
1217 rp->r_priv.s_flags |= (def_rp->r_priv.s_flags & IMM_F);
1219 /* Allowed traps. They cannot change. */
1220 rp->r_priv.s_trap_mask = def_rp->r_priv.s_trap_mask;
1223 /*===========================================================================*
1224 * get_service_instances *
1225 *===========================================================================*/
1226 void get_service_instances(rp, rps, length)
1227 struct rproc *rp;
1228 struct rproc ***rps;
1229 int *length;
1231 /* Retrieve all the service instances of a given service. */
1232 static struct rproc *instances[5];
1233 int nr_instances;
1235 nr_instances = 0;
1236 instances[nr_instances++] = rp;
1237 if(rp->r_prev_rp) instances[nr_instances++] = rp->r_prev_rp;
1238 if(rp->r_next_rp) instances[nr_instances++] = rp->r_next_rp;
1239 if(rp->r_old_rp) instances[nr_instances++] = rp->r_old_rp;
1240 if(rp->r_new_rp) instances[nr_instances++] = rp->r_new_rp;
1242 *rps = instances;
1243 *length = nr_instances;
1246 /*===========================================================================*
1247 * share_exec *
1248 *===========================================================================*/
1249 void share_exec(rp_dst, rp_src)
1250 struct rproc *rp_dst, *rp_src;
1252 if(rs_verbose)
1253 printf("RS: %s shares exec image with %s\n",
1254 srv_to_string(rp_dst), srv_to_string(rp_src));
1256 /* Share exec image from rp_src to rp_dst. */
1257 rp_dst->r_exec_len = rp_src->r_exec_len;
1258 rp_dst->r_exec = rp_src->r_exec;
1261 /*===========================================================================*
1262 * read_exec *
1263 *===========================================================================*/
1264 int read_exec(rp)
1265 struct rproc *rp;
1267 int e, r, fd;
1268 char *e_name;
1269 struct stat sb;
1271 e_name= rp->r_argv[0];
1272 if(rs_verbose)
1273 printf("RS: service '%s' reads exec image from: %s\n", rp->r_pub->label,
1274 e_name);
1276 r= stat(e_name, &sb);
1277 if (r != 0)
1278 return -errno;
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;
1549 /* Update period. */
1550 if(rpub->endpoint != RS_PROC_NR) {
1551 rp->r_period = rs_start->rss_period;
1554 /* (Re)initialize privilege settings. */
1555 init_privs(rp, &rp->r_priv);
1557 return OK;
1560 /*===========================================================================*
1561 * init_slot *
1562 *===========================================================================*/
1563 int init_slot(rp, rs_start, source)
1564 struct rproc *rp;
1565 struct rs_start *rs_start;
1566 endpoint_t source;
1568 /* Initialize a slot as requested by the client. */
1569 struct rprocpub *rpub;
1570 int i;
1572 rpub = rp->r_pub;
1574 /* All dynamically created services get the same sys and privilege flags, and
1575 * allowed traps. Other privilege settings can be specified at runtime. The
1576 * privilege id is dynamically allocated by the kernel.
1578 rpub->sys_flags = DSRV_SF; /* system flags */
1579 rp->r_priv.s_flags = DSRV_F; /* privilege flags */
1580 rp->r_priv.s_trap_mask = DSRV_T; /* allowed traps */
1581 rp->r_priv.s_bak_sig_mgr = NONE; /* backup signal manager */
1583 /* Initialize uid. */
1584 rp->r_uid= rs_start->rss_uid;
1586 /* Initialize device driver settings. */
1587 rpub->dev_flags = DSRV_DF;
1588 rpub->dev_nr = rs_start->rss_major;
1589 rpub->dev_style = rs_start->rss_dev_style;
1590 rpub->devman_id = rs_start->devman_id;
1591 if(rpub->dev_nr && !IS_DEV_STYLE(rs_start->rss_dev_style)) {
1592 printf("RS: init_slot: bad device style\n");
1593 return EINVAL;
1595 rpub->dev_style2 = STYLE_NDEV;
1597 /* Initialize pci settings. */
1598 if (rs_start->rss_nr_pci_id > RS_NR_PCI_DEVICE) {
1599 printf("RS: init_slot: too many PCI device IDs\n");
1600 return EINVAL;
1602 rpub->pci_acl.rsp_nr_device = rs_start->rss_nr_pci_id;
1603 for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++) {
1604 rpub->pci_acl.rsp_device[i].vid= rs_start->rss_pci_id[i].vid;
1605 rpub->pci_acl.rsp_device[i].did= rs_start->rss_pci_id[i].did;
1606 if(rs_verbose)
1607 printf("RS: init_slot: PCI %04x/%04x\n",
1608 rpub->pci_acl.rsp_device[i].vid,
1609 rpub->pci_acl.rsp_device[i].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);