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)
10 #include <sys/exec_elf.h>
14 #include "kernel/proc.h"
16 /*===========================================================================*
18 *===========================================================================*/
19 static int caller_is_root(endpoint
)
20 endpoint_t endpoint
; /* caller endpoint */
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
);
34 /*===========================================================================*
35 * caller_can_control *
36 *===========================================================================*/
37 static int caller_can_control(endpoint
, target_rp
)
39 struct rproc
*target_rp
;
41 int control_allowed
= 0;
42 register struct rproc
*rp
;
43 register struct rprocpub
*rpub
;
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
))
55 if (rpub
->endpoint
== endpoint
) {
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) {
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
)
84 /* Check if the caller has permission to execute a particular call. */
85 struct rprocpub
*rpub
;
88 /* Caller should be either root or have control privileges. */
89 call_allowed
= caller_is_root(caller
);
91 call_allowed
|= caller_can_control(caller
, rp
);
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
)) {
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
;
125 /*===========================================================================*
127 *===========================================================================*/
128 int copy_rs_start(src_e
, src_rs_start
, dst_rs_start
)
131 struct rs_start
*dst_rs_start
;
135 r
= sys_datacopy(src_e
, (vir_bytes
) src_rs_start
,
136 SELF
, (vir_bytes
) dst_rs_start
, sizeof(struct rs_start
));
141 /*===========================================================================*
143 *===========================================================================*/
144 int copy_label(src_e
, src_label
, src_len
, dst_label
, dst_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
;
164 /*===========================================================================*
166 *===========================================================================*/
167 void build_cmd_dep(struct rproc
*rp
)
169 struct rprocpub
*rpub
;
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");
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], '/');
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 /*===========================================================================*
217 *===========================================================================*/
218 int srv_update(endpoint_t src_e
, endpoint_t dst_e
)
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
);
231 r
= sys_update(src_e
, dst_e
);
237 /*===========================================================================*
239 *===========================================================================*/
240 void update_period(message
*m_ptr
)
242 clock_t now
= m_ptr
->m_notify
.timestamp
;
243 short has_update_timed_out
;
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
);
268 /* Send request message to the system service. */
269 asynsend(rpub
->endpoint
, &m
);
274 /*===========================================================================*
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
;
293 new_rp
= old_rp
->r_new_rp
;
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
);
304 rupdate
.flags
&= ~RS_UPDATING
;
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
) {
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
]);
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
)
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 */
353 /*===========================================================================*
354 * crash_service_debug *
355 *===========================================================================*/
356 int crash_service_debug(file
, line
, rp
)
361 /* Simluate a crash in a system service. */
362 struct rprocpub
*rpub
;
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
) {
375 return sys_kill(rpub
->endpoint
, SIGKILL
);
378 /*===========================================================================*
379 * cleanup_service_debug *
380 *===========================================================================*/
381 void cleanup_service_debug(file
, line
, rp
)
386 struct rprocpub
*rpub
;
392 printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp
),
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");
405 srv_kill(rp
->r_pid
, SIGKILL
);
408 /* Free slot, unless we're about to reuse it */
409 if (!(rp
->r_flags
& RS_REINCARNATE
))
413 /*===========================================================================*
415 *===========================================================================*/
416 int create_service(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
;
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",
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",
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",
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
460 printf("RS: forking child with srv_fork()...\n");
461 child_pid
= srv_fork(rp
->r_uid
, 0); /* Force group to operator for now */
463 printf("RS: srv_fork() failed (error %d)\n", 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
);
489 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
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
);
497 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
501 /* Copy the executable image into the child process. If no copy exists,
502 * allocate one and free it right after exec completes.
506 printf("RS: %s uses an in-memory copy\n",
510 if ((s
= read_exec(rp
)) != OK
) {
511 printf("RS: read_exec failed: %d\n", s
);
513 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
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
,
521 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
523 printf("RS: srv_execve failed: %d\n", s
);
531 /* If this is a VM instance, let VM know now. */
532 if(rp
->r_priv
.s_flags
& VM_SYS_PROC
) {
534 printf("RS: informing VM of instance %s\n", srv_to_string(rp
));
536 s
= vm_memctl(rpub
->endpoint
, VM_RS_MEM_MAKE_VM
);
538 printf("vm_memctl failed: %d\n", 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
);
552 printf("RS: %s created\n", srv_to_string(rp
));
557 /*===========================================================================*
559 *===========================================================================*/
560 int clone_service(rp
, 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
;
574 printf("RS: creating a replica for %s\n", srv_to_string(rp
));
577 if((r
= clone_slot(rp
, &replica_rp
)) != OK
) {
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
;
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
;
597 /* Create a new replica of the service. */
598 r
= create_service(replica_rp
);
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
);
612 r
= update_sig_mgrs(replica_rp
, SELF
, NONE
);
616 return kill_service(replica_rp
, "update_sig_mgrs failed", r
);
623 /*===========================================================================*
625 *===========================================================================*/
626 int publish_service(rp
)
627 struct rproc
*rp
; /* pointer to service slot */
629 /* Publish a service. */
631 struct rprocpub
*rpub
;
632 struct rs_pci pci_acl
;
638 /* Register label with DS. */
639 r
= ds_publish_label(rpub
->label
, rpub
->endpoint
, DSF_OVERWRITE
);
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.
659 if ((r
= mapdriver(rpub
->label
, rpub
->dev_nr
)) != OK
) {
660 return kill_service(rp
, "couldn't map driver", r
);
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
);
673 return kill_service(rp
, "pci_set_acl call failed", r
);
678 if (rpub
->devman_id
!= 0) {
679 r
= ds_retrieve_label_endpt("devman",&ep
);
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
);
694 printf("RS: %s published\n", srv_to_string(rp
));
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
;
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
);
722 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
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
);
735 if (rpub
->devman_id
!= 0) {
736 r
= ds_retrieve_label_endpt("devman",&ep
);
739 printf("RS: devman not running?");
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");
753 printf("RS: %s unpublished\n", srv_to_string(rp
));
758 /*===========================================================================*
760 *===========================================================================*/
761 int run_service(rp
, init_type
)
765 /* Let a newly created service run. */
766 struct rprocpub
*rpub
;
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
);
782 printf("RS: %s allowed to run\n", srv_to_string(rp
));
787 /*===========================================================================*
789 *===========================================================================*/
790 int start_service(rp
)
793 /* Start a system service. */
795 struct rprocpub
*rpub
;
799 /* Create and make active. */
800 r
= create_service(rp
);
804 activate_service(rp
, NULL
);
806 /* Publish service properties. */
807 r
= publish_service(rp
);
813 init_type
= SEF_INIT_FRESH
;
814 r
= run_service(rp
, init_type
);
820 printf("RS: %s started with major %d\n", srv_to_string(rp
),
826 /*===========================================================================*
828 *===========================================================================*/
829 void stop_service(struct rproc
*rp
,int how
)
831 struct rprocpub
*rpub
;
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.
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 /*===========================================================================*
853 *===========================================================================*/
854 int update_service(src_rpp
, dst_rpp
, swap_flag
)
855 struct rproc
**src_rpp
;
856 struct rproc
**dst_rpp
;
859 /* Update an existing service. */
861 struct rproc
*src_rp
;
862 struct rproc
*dst_rp
;
863 struct rprocpub
*src_rpub
;
864 struct rprocpub
*dst_rpub
;
870 src_rpub
= src_rp
->r_pub
;
871 dst_rpub
= dst_rp
->r_pub
;
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
) {
884 /* Swap slots here as well. */
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
;
894 dst_rp
->r_pub
->endpoint
= endpoint
;
895 rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)] = dst_rp
;
897 /* Adjust input pointers. */
901 /* Make the new version active. */
902 activate_service(dst_rp
, src_rp
);
905 printf("RS: %s updated into %s\n",
906 srv_to_string(src_rp
), srv_to_string(dst_rp
));
911 /*===========================================================================*
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
;
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
;
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
;
942 rp
->r_flags
&= RS_IN_USE
;
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
];
959 rp
->r_prev_rp
= NULL
;
960 rp
->r_next_rp
= NULL
;
965 /*===========================================================================*
966 * terminate_service *
967 *===========================================================================*/
968 void terminate_service(struct rproc
*rp
)
970 /* Handle a termination event for a system service. */
972 struct rprocpub
*rpub
;
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
989 printf("RS: service '%s' exited during initialization; "
990 "refreshing\n", rpub
->label
);
991 rp
->r_flags
|= RS_REFRESHING
; /* restart initialization. */
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");
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
);
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
));
1020 /* See if a late reply has to be sent. */
1021 r
= (rp
->r_caller_request
== RS_DOWN
? OK
: EDEADEPT
);
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
);
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)
1070 /* Restart service. */
1071 restart_service(rp
);
1075 /*===========================================================================*
1077 *===========================================================================*/
1078 static int run_script(struct rproc
*rp
)
1083 char incarnation_str
[20]; /* Enough for a counter? */
1084 char *envp
[1] = { NULL
};
1085 struct rprocpub
*rpub
;
1088 if (rp
->r_flags
& RS_REFRESHING
)
1090 else if (rp
->r_flags
& RS_NOPINGREPLY
)
1091 reason
= "no-heartbeat";
1092 else reason
= "terminated";
1093 sprintf(incarnation_str
, "%d", rp
->r_restarts
);
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
);
1106 return kill_service(rp
, "unable to fork script", errno
);
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
));
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
))
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
);
1136 /*===========================================================================*
1138 *===========================================================================*/
1139 void restart_service(struct rproc
*rp
)
1141 /* Restart service via a recovery script or directly. */
1142 struct rproc
*replica_rp
;
1145 /* See if a late reply has to be sent. */
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
);
1157 /* Run a recovery script if available. */
1158 if (rp
->r_script
[0] != '\0') {
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
);
1168 kill_service(rp
, "unable to clone service", r
);
1172 replica_rp
= rp
->r_next_rp
;
1174 /* Update the service into the replica. */
1175 r
= update_service(&rp
, &replica_rp
, RS_SWAP
);
1177 kill_service(rp
, "unable to update into new replica", r
);
1181 /* Let the new replica run. */
1182 r
= run_service(replica_rp
, SEF_INIT_RESTART
);
1184 kill_service(rp
, "unable to let the replica run", r
);
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
;
1200 struct rprocpub
*def_rpub
;
1201 struct rprocpub
*rpub
;
1203 def_rpub
= def_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
)
1225 struct rproc
***rps
;
1228 /* Retrieve all the service instances of a given service. */
1229 static struct rproc
*instances
[5];
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
;
1240 *length
= nr_instances
;
1243 /*===========================================================================*
1245 *===========================================================================*/
1246 void share_exec(rp_dst
, rp_src
)
1247 struct rproc
*rp_dst
, *rp_src
;
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 /*===========================================================================*
1260 *===========================================================================*/
1268 e_name
= rp
->r_argv
[0];
1270 printf("RS: service '%s' reads exec image from: %s\n", rp
->r_pub
->label
,
1273 r
= stat(e_name
, &sb
);
1277 if (sb
.st_size
< sizeof(Elf_Ehdr
))
1280 fd
= open(e_name
, O_RDONLY
);
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",
1294 r
= read(fd
, rp
->r_exec
, rp
->r_exec_len
);
1297 if (r
== rp
->r_exec_len
)
1300 printf("RS: read_exec: read failed %d, errno %d\n", r
, e
);
1310 /*===========================================================================*
1312 *===========================================================================*/
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
;
1331 /* If nobody uses our copy of the exec image, we can try to get rid of it. */
1332 if(!has_shared_exec
) {
1334 printf("RS: %s frees exec image\n", srv_to_string(rp
));
1339 printf("RS: %s no longer sharing exec image with %s\n",
1340 srv_to_string(rp
), srv_to_string(other_rp
));
1346 /*===========================================================================*
1348 *===========================================================================*/
1349 int edit_slot(rp
, rs_start
, source
)
1351 struct rs_start
*rs_start
;
1354 /* Edit a given slot to override existing settings. */
1355 struct rprocpub
*rpub
;
1359 int basic_kc
[] = { SYS_BASIC_CALLS
, NULL_C
};
1360 int basic_vmc
[] = { VM_BASIC_CALLS
, NULL_C
};
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
);
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';
1375 if(rs_start
->rss_nr_irq
== RSS_IRQ_ALL
) {
1376 rs_start
->rss_nr_irq
= 0;
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");
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
];
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;
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");
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
];
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) {
1434 if (rs_start
->rss_nr_control
> RS_NR_CONTROL
) {
1435 printf("RS: edit_slot: too many control labels\n");
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
]));
1445 rp
->r_nr_control
= rs_start
->rss_nr_control
;
1448 printf("RS: edit_slot: control labels:");
1449 for (i
=0; i
<rp
->r_nr_control
; i
++)
1450 printf(" %s", rp
->r_control
[i
]);
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. */
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
));
1486 printf("RS: edit_slot: using label (custom) '%s'\n", rpub
->label
);
1488 /* Default label for the service. */
1489 label
= rpub
->proc_name
;
1491 memcpy(rpub
->label
, label
, len
);
1492 rpub
->label
[len
]= '\0';
1494 printf("RS: edit_slot: using label (from proc_name) '%s'\n",
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
)) {
1512 struct rprocpub
*rpub2
;
1515 if(rs_start
->rss_flags
& RSS_REUSE
) {
1518 for(i
= 0; i
< NR_SYS_PROCS
; i
++) {
1520 if (!(rp2
->r_flags
& RS_IN_USE
)) {
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 */
1538 share_exec(rp
, rp2
);
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
);
1563 /*===========================================================================*
1565 *===========================================================================*/
1566 int init_slot(rp
, rs_start
, source
)
1568 struct rs_start
*rs_start
;
1571 /* Initialize a slot as requested by the client. */
1572 struct rprocpub
*rpub
;
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");
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
;
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");
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
;
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 */
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 /*===========================================================================*
1644 *===========================================================================*/
1645 int clone_slot(rp
, clone_rpp
)
1647 struct rproc
**clone_rpp
;
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
);
1656 printf("RS: clone_slot: unable to allocate a new slot: %d\n", r
);
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
);
1670 *clone_rpub
= *rpub
;
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
;
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
) {
1705 else if(*rpp
== dst_rp
) {
1710 /*===========================================================================*
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
;
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
;
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
)],
1764 swap_slot_pointer(&rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)],
1767 /* Adjust input pointers. */
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. */
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
)) {
1788 if (strcmp(rpub
->label
, label
) == 0) {
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. */
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
)) {
1814 if (rp
->r_pid
== pid
) {
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. */
1830 struct rprocpub
*rpub
;
1836 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1837 rp
= &rproc
[slot_nr
];
1839 if (!(rp
->r_flags
& RS_IN_USE
)) {
1842 if (rpub
->dev_nr
== dev_nr
) {
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. */
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
)) {
1868 if (rp
->r_flags
& flags
) {
1876 /*===========================================================================*
1878 *===========================================================================*/
1882 /* Alloc a new system service slot. */
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 */
1890 if (slot_nr
>= NR_SYS_PROCS
) {
1897 /*===========================================================================*
1899 *===========================================================================*/
1903 /* Free a system service slot. */
1904 struct rprocpub
*rpub
;
1908 /* Send a late reply if there is any pending. */
1911 /* Free memory if necessary. */
1912 if(rpub
->sys_flags
& SF_USE_COPY
) {
1916 /* Mark slot as no longer in use.. */
1919 rpub
->in_use
= FALSE
;
1920 rproc_ptr
[_ENDPOINT_P(rpub
->endpoint
)] = NULL
;
1924 /*===========================================================================*
1926 *===========================================================================*/
1927 static char *get_next_name(ptr
, name
, caller_label
)
1932 /* Get the next name from the list of (IPC) program names.
1937 for (p
= ptr
; p
[0] != '\0'; p
= q
)
1939 /* Skip leading space */
1940 while (p
[0] != '\0' && isspace((unsigned char)p
[0]))
1943 /* Find start of next word */
1945 while (q
[0] != '\0' && !isspace((unsigned char)q
[0]))
1950 if (len
> RS_MAX_LABEL_LEN
)
1953 "rs:get_next_name: bad ipc list entry '%.*s' for %s: too long\n",
1954 len
, p
, caller_label
);
1957 memcpy(name
, p
, len
);
1960 return q
; /* found another */
1963 return NULL
; /* done */
1966 /*===========================================================================*
1968 *===========================================================================*/
1969 void add_forward_ipc(rp
, privp
)
1973 /* Add IPC send permissions to a process based on that process's IPC
1976 char name
[RS_MAX_LABEL_LEN
+1], *p
;
1978 endpoint_t endpoint
;
1982 struct rprocpub
*rpub
;
1987 while ((p
= get_next_name(p
, name
, rpub
->label
)) != NULL
) {
1989 if (strcmp(name
, "SYSTEM") == 0)
1991 else if (strcmp(name
, "USER") == 0)
1992 endpoint
= INIT_PROC_NR
; /* all user procs */
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
))
2005 if (!strcmp(rrp
->r_pub
->proc_name
, name
)) {
2007 printf(" RS: add_forward_ipc: setting"
2008 " sendto bit for %d...\n",
2009 rrp
->r_pub
->endpoint
);
2012 priv_id
= rrp
->r_priv
.s_id
;
2013 set_sys_bit(privp
->s_ipc_to
, priv_id
);
2020 /* This code only applies to the exception cases. */
2021 if ((r
= sys_getpriv(&priv
, endpoint
)) < 0)
2024 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
2030 printf(" RS: add_forward_ipc: setting sendto bit for %d...\n",
2034 set_sys_bit(privp
->s_ipc_to
, priv_id
);
2039 /*===========================================================================*
2040 * add_backward_ipc *
2041 *===========================================================================*/
2042 void add_backward_ipc(rp
, 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
;
2054 struct rprocpub
*rrpub
;
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
))
2064 if (!rrp
->r_ipc_list
[0])
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.
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
);
2077 (is_ipc_all_sys
&& (privp
->s_flags
& SYS_PROC
))) {
2079 printf(" RS: add_backward_ipc: setting sendto bit "
2080 "for %d...\n", rrpub
->endpoint
);
2082 priv_id
= rrp
->r_priv
.s_id
;
2083 set_sys_bit(privp
->s_ipc_to
, priv_id
);
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
)) {
2097 printf(" RS: add_backward_ipc: setting sendto"
2101 priv_id
= rrp
->r_priv
.s_id
;
2102 set_sys_bit(privp
->s_ipc_to
, priv_id
);
2109 /*===========================================================================*
2111 *===========================================================================*/
2112 void init_privs(rp
, privp
)
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
);
2126 printf(" RS: init_privs: ipc list is '%s'...\n", rp
->r_ipc_list
);
2129 if (!is_ipc_all
&& !is_ipc_all_sys
)
2131 add_forward_ipc(rp
, privp
);
2132 add_backward_ipc(rp
, privp
);
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
);