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)
12 #include "kernel/proc.h"
14 /*===========================================================================*
16 *===========================================================================*/
17 static int caller_is_root(endpoint
)
18 endpoint_t endpoint
; /* caller endpoint */
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
);
32 /*===========================================================================*
33 * caller_can_control *
34 *===========================================================================*/
35 static int caller_can_control(endpoint
, target_rp
)
37 struct rproc
*target_rp
;
39 int control_allowed
= 0;
40 register struct rproc
*rp
;
41 register struct rprocpub
*rpub
;
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
))
53 if (rpub
->endpoint
== endpoint
) {
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) {
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
)
82 /* Check if the caller has permission to execute a particular call. */
83 struct rprocpub
*rpub
;
86 /* Caller should be either root or have control privileges. */
87 call_allowed
= caller_is_root(caller
);
89 call_allowed
|= caller_can_control(caller
, rp
);
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
)) {
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
;
123 /*===========================================================================*
125 *===========================================================================*/
126 int copy_rs_start(src_e
, src_rs_start
, dst_rs_start
)
129 struct rs_start
*dst_rs_start
;
133 r
= sys_datacopy(src_e
, (vir_bytes
) src_rs_start
,
134 SELF
, (vir_bytes
) dst_rs_start
, sizeof(struct rs_start
));
139 /*===========================================================================*
141 *===========================================================================*/
142 int copy_label(src_e
, src_label
, src_len
, dst_label
, dst_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
;
162 /*===========================================================================*
164 *===========================================================================*/
165 void build_cmd_dep(struct rproc
*rp
)
167 struct rprocpub
*rpub
;
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");
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], '/');
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 /*===========================================================================*
215 *===========================================================================*/
216 pid_t
srv_fork(uid_t reuid
, gid_t regid
)
220 m
.m1_i1
= (int) reuid
;
221 m
.m1_i2
= (int) regid
;
222 return _syscall(PM_PROC_NR
, SRV_FORK
, &m
);
225 /*===========================================================================*
227 *===========================================================================*/
228 int srv_kill(pid_t pid
, int sig
)
234 return(_syscall(PM_PROC_NR
, SRV_KILL
, &m
));
237 /*===========================================================================*
239 *===========================================================================*/
240 int srv_update(endpoint_t src_e
, endpoint_t dst_e
)
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
);
253 r
= sys_update(src_e
, dst_e
);
259 /*===========================================================================*
261 *===========================================================================*/
262 void update_period(message
*m_ptr
)
264 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
265 short has_update_timed_out
;
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
);
290 /* Send request message to the system service. */
291 asynsend(rpub
->endpoint
, &m
);
296 /*===========================================================================*
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
;
315 new_rp
= old_rp
->r_new_rp
;
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
);
326 rupdate
.flags
&= ~RS_UPDATING
;
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
) {
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
]);
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
)
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 */
375 /*===========================================================================*
376 * crash_service_debug *
377 *===========================================================================*/
378 int crash_service_debug(file
, line
, rp
)
383 /* Simluate a crash in a system service. */
384 struct rprocpub
*rpub
;
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
) {
397 return sys_kill(rpub
->endpoint
, SIGKILL
);
400 /*===========================================================================*
401 * cleanup_service_debug *
402 *===========================================================================*/
403 void cleanup_service_debug(file
, line
, rp
)
408 struct rprocpub
*rpub
;
414 printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp
),
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");
427 srv_kill(rp
->r_pid
, SIGKILL
);
430 /* Free slot, unless we're about to reuse it */
431 if (!(rp
->r_flags
& RS_REINCARNATE
))
435 /*===========================================================================*
437 *===========================================================================*/
438 int create_service(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
;
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",
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",
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",
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
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
);
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
);
510 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
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
);
518 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
522 /* Copy the executable image into the child process. If no copy exists,
523 * allocate one and free it right after exec completes.
527 printf("RS: %s uses an in-memory copy\n",
531 if ((s
= read_exec(rp
)) != OK
) {
532 printf("RS: read_exec failed: %d\n", s
);
534 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
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
,
542 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
544 printf("RS: srv_execve failed: %d\n", s
);
552 /* If this is a VM instance, let VM know now. */
553 if(rp
->r_priv
.s_flags
& VM_SYS_PROC
) {
555 printf("RS: informing VM of instance %s\n", srv_to_string(rp
));
557 s
= vm_memctl(rpub
->endpoint
, VM_RS_MEM_MAKE_VM
);
559 printf("vm_memctl failed: %d\n", 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
);
573 printf("RS: %s created\n", srv_to_string(rp
));
578 /*===========================================================================*
580 *===========================================================================*/
581 int clone_service(rp
, 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
;
595 printf("RS: creating a replica for %s\n", srv_to_string(rp
));
598 if((r
= clone_slot(rp
, &replica_rp
)) != OK
) {
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
;
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
;
618 /* Create a new replica of the service. */
619 r
= create_service(replica_rp
);
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
);
633 r
= update_sig_mgrs(replica_rp
, SELF
, NONE
);
637 return kill_service(replica_rp
, "update_sig_mgrs failed", r
);
644 /*===========================================================================*
646 *===========================================================================*/
647 int publish_service(rp
)
648 struct rproc
*rp
; /* pointer to service slot */
650 /* Publish a service. */
652 struct rprocpub
*rpub
;
653 struct rs_pci pci_acl
;
659 /* Register label with DS. */
660 r
= ds_publish_label(rpub
->label
, rpub
->endpoint
, DSF_OVERWRITE
);
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.
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
);
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
);
695 return kill_service(rp
, "pci_set_acl call failed", r
);
700 if (rpub
->devman_id
!= 0) {
701 r
= ds_retrieve_label_endpt("devman",&ep
);
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
;
710 if (r
!= OK
|| m
.DEVMAN_RESULT
!= OK
) {
711 return kill_service(rp
, "devman bind device failed", r
);
716 printf("RS: %s published\n", srv_to_string(rp
));
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
;
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
);
744 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
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
);
757 if (rpub
->devman_id
!= 0) {
758 r
= ds_retrieve_label_endpt("devman",&ep
);
761 printf("RS: devman not running?");
763 m
.m_type
= DEVMAN_UNBIND
;
764 m
.DEVMAN_ENDPOINT
= rpub
->endpoint
;
765 m
.DEVMAN_DEVICE_ID
= rpub
->devman_id
;
768 if (r
!= OK
|| m
.DEVMAN_RESULT
!= OK
) {
769 printf("RS: devman unbind device failed");
775 printf("RS: %s unpublished\n", srv_to_string(rp
));
780 /*===========================================================================*
782 *===========================================================================*/
783 int run_service(rp
, init_type
)
787 /* Let a newly created service run. */
788 struct rprocpub
*rpub
;
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
);
804 printf("RS: %s allowed to run\n", srv_to_string(rp
));
809 /*===========================================================================*
811 *===========================================================================*/
812 int start_service(rp
)
815 /* Start a system service. */
817 struct rprocpub
*rpub
;
821 /* Create and make active. */
822 r
= create_service(rp
);
826 activate_service(rp
, NULL
);
828 /* Publish service properties. */
829 r
= publish_service(rp
);
835 init_type
= SEF_INIT_FRESH
;
836 r
= run_service(rp
, init_type
);
842 printf("RS: %s started with major %d\n", srv_to_string(rp
),
848 /*===========================================================================*
850 *===========================================================================*/
851 void stop_service(struct rproc
*rp
,int how
)
853 struct rprocpub
*rpub
;
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.
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 /*===========================================================================*
875 *===========================================================================*/
876 int update_service(src_rpp
, dst_rpp
, swap_flag
)
877 struct rproc
**src_rpp
;
878 struct rproc
**dst_rpp
;
881 /* Update an existing service. */
883 struct rproc
*src_rp
;
884 struct rproc
*dst_rp
;
885 struct rprocpub
*src_rpub
;
886 struct rprocpub
*dst_rpub
;
892 src_rpub
= src_rp
->r_pub
;
893 dst_rpub
= dst_rp
->r_pub
;
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
) {
906 /* Swap slots here as well. */
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
;
916 dst_rp
->r_pub
->endpoint
= endpoint
;
917 rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)] = dst_rp
;
919 /* Adjust input pointers. */
923 /* Make the new version active. */
924 activate_service(dst_rp
, src_rp
);
927 printf("RS: %s updated into %s\n",
928 srv_to_string(src_rp
), srv_to_string(dst_rp
));
933 /*===========================================================================*
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
;
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
;
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
;
964 rp
->r_flags
&= RS_IN_USE
;
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
];
981 rp
->r_prev_rp
= NULL
;
982 rp
->r_next_rp
= NULL
;
987 /*===========================================================================*
988 * terminate_service *
989 *===========================================================================*/
990 void terminate_service(struct rproc
*rp
)
992 /* Handle a termination event for a system service. */
994 struct rprocpub
*rpub
;
1001 printf("RS: %s terminated\n", srv_to_string(rp
));
1003 /* Deal with failures during initialization. */
1004 if(rp
->r_flags
& RS_INITIALIZING
) {
1006 printf("RS: service '%s' exited during initialization\n",
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");
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
);
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
));
1031 /* See if a late reply has to be sent. */
1032 r
= (rp
->r_caller_request
== RS_DOWN
? OK
: EDEADEPT
);
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
);
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)
1076 /* Restart service. */
1077 restart_service(rp
);
1081 /*===========================================================================*
1083 *===========================================================================*/
1084 static int run_script(struct rproc
*rp
)
1089 char incarnation_str
[20]; /* Enough for a counter? */
1090 char *envp
[1] = { NULL
};
1091 struct rprocpub
*rpub
;
1094 if (rp
->r_flags
& RS_REFRESHING
)
1096 else if (rp
->r_flags
& RS_NOPINGREPLY
)
1097 reason
= "no-heartbeat";
1098 else reason
= "terminated";
1099 sprintf(incarnation_str
, "%d", rp
->r_restarts
);
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
);
1112 return kill_service(rp
, "unable to fork script", errno
);
1114 execle(_PATH_BSHELL
, 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
));
1120 /* Set the privilege structure for the child process. */
1121 endpoint
= getnprocnr(pid
);
1122 if ((r
= sys_privctl(endpoint
, SYS_PRIV_SET_USER
, NULL
))
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
);
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_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
)
1228 struct rproc
***rps
;
1231 /* Retrieve all the service instances of a given service. */
1232 static struct rproc
*instances
[5];
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
;
1243 *length
= nr_instances
;
1246 /*===========================================================================*
1248 *===========================================================================*/
1249 void share_exec(rp_dst
, rp_src
)
1250 struct rproc
*rp_dst
, *rp_src
;
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 /*===========================================================================*
1263 *===========================================================================*/
1271 e_name
= rp
->r_argv
[0];
1273 printf("RS: service '%s' reads exec image from: %s\n", rp
->r_pub
->label
,
1276 r
= stat(e_name
, &sb
);
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
;
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
);
1560 /*===========================================================================*
1562 *===========================================================================*/
1563 int init_slot(rp
, rs_start
, source
)
1565 struct rs_start
*rs_start
;
1568 /* Initialize a slot as requested by the client. */
1569 struct rprocpub
*rpub
;
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");
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");
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
;
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");
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
);