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 "kernel/proc.h"
12 /*===========================================================================*
14 *===========================================================================*/
15 static int caller_is_root(endpoint
)
16 endpoint_t endpoint
; /* caller endpoint */
20 /* Check if caller has root user ID. */
21 euid
= getnuid(endpoint
);
22 if (rs_verbose
&& euid
!= 0)
24 printf("RS: got unauthorized request from endpoint %d\n", endpoint
);
30 /*===========================================================================*
31 * caller_can_control *
32 *===========================================================================*/
33 static int caller_can_control(endpoint
, target_rp
)
35 struct rproc
*target_rp
;
37 int control_allowed
= 0;
38 register struct rproc
*rp
;
39 register struct rprocpub
*rpub
;
43 proc_name
= target_rp
->r_pub
->proc_name
;
45 /* Check if label is listed in caller's isolation policy. */
46 for (rp
= BEG_RPROC_ADDR
; rp
< END_RPROC_ADDR
; rp
++) {
47 if (!(rp
->r_flags
& RS_IN_USE
))
51 if (rpub
->endpoint
== endpoint
) {
55 if (rp
== END_RPROC_ADDR
) return 0;
57 for (c
= 0; c
< rp
->r_nr_control
; c
++) {
58 if (strcmp(rp
->r_control
[c
], proc_name
) == 0) {
65 printf("RS: allowing %u control over %s via policy: %s\n",
66 endpoint
, target_rp
->r_pub
->label
,
67 control_allowed
? "yes" : "no");
69 return control_allowed
;
72 /*===========================================================================*
73 * check_call_permission *
74 *===========================================================================*/
75 int check_call_permission(caller
, call
, rp
)
80 /* Check if the caller has permission to execute a particular call. */
81 struct rprocpub
*rpub
;
84 /* Caller should be either root or have control privileges. */
85 call_allowed
= caller_is_root(caller
);
87 call_allowed
|= caller_can_control(caller
, rp
);
96 /* Only allow RS_EDIT if the target is a user process. */
97 if(!(rp
->r_priv
.s_flags
& SYS_PROC
)) {
98 if(call
!= RS_EDIT
) return EPERM
;
101 /* Disallow the call if another call is in progress for the service. */
102 if((rp
->r_flags
& RS_LATEREPLY
)
103 || (rp
->r_flags
& RS_INITIALIZING
) || (rp
->r_flags
& RS_UPDATING
)) {
107 /* Only allow RS_DOWN and RS_RESTART if the service has terminated. */
108 if(rp
->r_flags
& RS_TERMINATED
) {
109 if(call
!= RS_DOWN
&& call
!= RS_RESTART
) return EPERM
;
112 /* Disallow RS_DOWN for core system services. */
113 if (rpub
->sys_flags
& SF_CORE_SRV
) {
114 if(call
== RS_DOWN
) return EPERM
;
121 /*===========================================================================*
123 *===========================================================================*/
124 int copy_rs_start(src_e
, src_rs_start
, dst_rs_start
)
127 struct rs_start
*dst_rs_start
;
131 r
= sys_datacopy(src_e
, (vir_bytes
) src_rs_start
,
132 SELF
, (vir_bytes
) dst_rs_start
, sizeof(struct rs_start
));
137 /*===========================================================================*
139 *===========================================================================*/
140 int copy_label(src_e
, src_label
, src_len
, dst_label
, dst_len
)
149 len
= MIN(dst_len
-1, src_len
);
151 s
= sys_datacopy(src_e
, (vir_bytes
) src_label
,
152 SELF
, (vir_bytes
) dst_label
, len
);
153 if (s
!= OK
) return s
;
160 /*===========================================================================*
162 *===========================================================================*/
163 void build_cmd_dep(struct rproc
*rp
)
165 struct rprocpub
*rpub
;
172 /* Build argument vector to be passed to execute call. The format of the
173 * arguments vector is: path, arguments, NULL.
175 strcpy(rp
->r_args
, rp
->r_cmd
); /* copy raw command */
176 arg_count
= 0; /* initialize arg count */
177 rp
->r_argv
[arg_count
++] = rp
->r_args
; /* start with path */
178 cmd_ptr
= rp
->r_args
; /* do some parsing */
179 while(*cmd_ptr
!= '\0') { /* stop at end of string */
180 if (*cmd_ptr
== ' ') { /* next argument */
181 *cmd_ptr
= '\0'; /* terminate previous */
182 while (*++cmd_ptr
== ' ') ; /* skip spaces */
183 if (*cmd_ptr
== '\0') break; /* no arg following */
184 /* There are ARGV_ELEMENTS elements; must leave one for null */
185 if (arg_count
>=ARGV_ELEMENTS
-1) { /* arg vector full */
186 printf("RS: build_cmd_dep: too many args\n");
189 assert(arg_count
< ARGV_ELEMENTS
);
190 rp
->r_argv
[arg_count
++] = cmd_ptr
; /* add to arg vector */
192 cmd_ptr
++; /* continue parsing */
194 assert(arg_count
< ARGV_ELEMENTS
);
195 rp
->r_argv
[arg_count
] = NULL
; /* end with NULL pointer */
196 rp
->r_argc
= arg_count
;
198 /* Build process name. */
199 cmd_ptr
= strrchr(rp
->r_argv
[0], '/');
203 cmd_ptr
= rp
->r_argv
[0];
204 len
= strlen(cmd_ptr
);
205 if (len
> RS_MAX_LABEL_LEN
-1)
206 len
= RS_MAX_LABEL_LEN
-1; /* truncate name */
207 memcpy(rpub
->proc_name
, cmd_ptr
, len
);
208 rpub
->proc_name
[len
]= '\0';
211 /*===========================================================================*
213 *===========================================================================*/
214 pid_t
srv_fork(uid_t reuid
, gid_t regid
)
218 m
.m1_i1
= (int) reuid
;
219 m
.m1_i2
= (int) regid
;
220 return _syscall(PM_PROC_NR
, SRV_FORK
, &m
);
223 /*===========================================================================*
225 *===========================================================================*/
226 int srv_kill(pid_t pid
, int sig
)
232 return(_syscall(PM_PROC_NR
, SRV_KILL
, &m
));
235 /*===========================================================================*
237 *===========================================================================*/
238 int srv_update(endpoint_t src_e
, endpoint_t dst_e
)
242 /* Ask VM to swap the slots of the two processes and tell the kernel to
243 * do the same. If VM is the service being updated, only perform the kernel
244 * part of the call. The new instance of VM will do the rest at
245 * initialization time.
247 if(src_e
!= VM_PROC_NR
) {
248 r
= vm_update(src_e
, dst_e
);
251 r
= sys_update(src_e
, dst_e
);
257 /*===========================================================================*
259 *===========================================================================*/
260 void update_period(message
*m_ptr
)
262 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
263 short has_update_timed_out
;
265 struct rprocpub
*rpub
;
267 rpub
= rupdate
.rp
->r_pub
;
269 /* See if a timeout has occurred. */
270 has_update_timed_out
= (now
- rupdate
.prepare_tm
> rupdate
.prepare_maxtime
);
272 /* If an update timed out, end the update process and notify
273 * the old version that the update has been canceled. From now on, the old
274 * version will continue executing.
276 if(has_update_timed_out
) {
277 printf("RS: update failed: maximum prepare time reached\n");
278 end_update(EINTR
, RS_DONTREPLY
);
280 /* Prepare cancel request. */
281 m
.m_type
= RS_LU_PREPARE
;
282 m
.RS_LU_STATE
= SEF_LU_STATE_NULL
;
283 if(rpub
->endpoint
== RS_PROC_NR
) {
284 /* RS can process the request directly. */
285 do_sef_lu_request(&m
);
288 /* Send request message to the system service. */
289 asynsend(rpub
->endpoint
, &m
);
294 /*===========================================================================*
296 *===========================================================================*/
297 void end_update(int result
, int reply_flag
)
299 /* End the update process. There are two possibilities:
300 * 1) the update succeeded. In that case, cleanup the old version and mark the
301 * new version as no longer under update.
302 * 2) the update failed. In that case, cleanup the new version and mark the old
303 * version as no longer under update. Eventual late ready to update
304 * messages (if any) will simply be ignored and the service can
305 * continue executing. In addition, reset the check timestamp, so that if the
306 * service has a period, a status request will be forced in the next period.
308 struct rproc
*old_rp
, *new_rp
, *exiting_rp
, *surviving_rp
;
313 new_rp
= old_rp
->r_new_rp
;
316 printf("RS: ending update from %s to %s with result: %d\n",
317 srv_to_string(old_rp
), srv_to_string(new_rp
), result
);
319 /* Decide which version has to die out and which version has to survive. */
320 surviving_rp
= (result
== OK
? new_rp
: old_rp
);
321 exiting_rp
= (result
== OK
? old_rp
: new_rp
);
324 rupdate
.flags
&= ~RS_UPDATING
;
326 old_rp
->r_new_rp
= NULL
;
327 new_rp
->r_old_rp
= NULL
;
328 old_rp
->r_check_tm
= 0;
330 /* Send a late reply if necessary. */
331 late_reply(old_rp
, result
);
333 /* Mark the version that has to survive as no longer updating and
334 * reply when asked to.
336 surviving_rp
->r_flags
&= ~RS_UPDATING
;
337 if(reply_flag
== RS_REPLY
) {
340 reply(surviving_rp
->r_pub
->endpoint
, surviving_rp
, &m
);
343 /* Cleanup the version that has to die out. */
344 get_service_instances(exiting_rp
, &rps
, &nr_rps
);
345 for(i
=0;i
<nr_rps
;i
++) {
346 cleanup_service(rps
[i
]);
350 printf("RS: %s ended the update\n", srv_to_string(surviving_rp
));
353 /*===========================================================================*
354 * kill_service_debug *
355 *===========================================================================*/
356 int kill_service_debug(file
, line
, rp
, errstr
, err
)
363 /* Crash a system service and don't let it restart. */
364 if(errstr
&& !shutting_down
) {
365 printf("RS: %s (error %d)\n", errstr
, err
);
367 rp
->r_flags
|= RS_EXITING
; /* expect exit */
368 crash_service_debug(file
, line
, rp
); /* simulate crash */
373 /*===========================================================================*
374 * crash_service_debug *
375 *===========================================================================*/
376 int crash_service_debug(file
, line
, rp
)
381 /* Simluate a crash in a system service. */
382 struct rprocpub
*rpub
;
387 printf("RS: %s %skilled at %s:%d\n", srv_to_string(rp
),
388 rp
->r_flags
& RS_EXITING
? "lethally " : "", file
, line
);
390 /* RS should simply exit() directly. */
391 if(rpub
->endpoint
== RS_PROC_NR
) {
395 return sys_kill(rpub
->endpoint
, SIGKILL
);
398 /*===========================================================================*
399 * cleanup_service_debug *
400 *===========================================================================*/
401 void cleanup_service_debug(file
, line
, rp
)
406 struct rprocpub
*rpub
;
412 printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp
),
415 /* Tell scheduler this process is finished */
416 if ((s
= sched_stop(rp
->r_scheduler
, rpub
->endpoint
)) != OK
) {
417 printf("RS: warning: scheduler won't give up process: %d\n", s
);
420 /* Ask PM to exit the service */
421 if(rp
->r_pid
== -1) {
422 printf("RS: warning: attempt to kill pid -1!\n");
425 srv_kill(rp
->r_pid
, SIGKILL
);
428 /* Free slot, unless we're about to reuse it */
429 if (!(rp
->r_flags
& RS_REINCARNATE
))
433 /*===========================================================================*
435 *===========================================================================*/
436 int create_service(rp
)
439 /* Create the given system service. */
440 int child_proc_nr_e
, child_proc_nr_n
; /* child process slot */
441 pid_t child_pid
; /* child's process id */
442 int s
, use_copy
, has_replica
;
443 extern char **environ
;
444 struct rprocpub
*rpub
;
447 use_copy
= (rpub
->sys_flags
& SF_USE_COPY
);
448 has_replica
= (rp
->r_old_rp
449 || (rp
->r_prev_rp
&& !(rp
->r_prev_rp
->r_flags
& RS_TERMINATED
)));
451 /* Do we need an existing replica to create the service? */
452 if(!has_replica
&& (rpub
->sys_flags
& SF_NEED_REPL
)) {
453 printf("RS: unable to create service '%s' without a replica\n",
459 /* Do we need an in-memory copy to create the service? */
460 if(!use_copy
&& (rpub
->sys_flags
& SF_NEED_COPY
)) {
461 printf("RS: unable to create service '%s' without an in-memory copy\n",
467 /* Do we have a copy or a command to create the service? */
468 if(!use_copy
&& !strcmp(rp
->r_cmd
, "")) {
469 printf("RS: unable to create service '%s' without a copy or command\n",
475 /* Now fork and branch for parent and child process (and check for error).
476 * After fork()ing, we need to pin RS memory again or pagefaults will occur
480 printf("RS: forking child with srv_fork()...\n");
481 child_pid
= srv_fork(rp
->r_uid
, 0); /* Force group to operator for now */
482 if(child_pid
== -1) {
483 printf("RS: srv_fork() failed (error %d)\n", errno
);
488 /* Get endpoint of the child. */
489 child_proc_nr_e
= getnprocnr(child_pid
);
491 /* There is now a child process. Update the system process table. */
492 child_proc_nr_n
= _ENDPOINT_P(child_proc_nr_e
);
493 rp
->r_flags
= RS_IN_USE
; /* mark slot in use */
494 rpub
->endpoint
= child_proc_nr_e
; /* set child endpoint */
495 rp
->r_pid
= child_pid
; /* set child pid */
496 rp
->r_check_tm
= 0; /* not checked yet */
497 getuptime(&rp
->r_alive_tm
); /* currently alive */
498 rp
->r_stop_tm
= 0; /* not exiting yet */
499 rp
->r_backoff
= 0; /* not to be restarted */
500 rproc_ptr
[child_proc_nr_n
] = rp
; /* mapping for fast access */
501 rpub
->in_use
= TRUE
; /* public entry is now in use */
503 /* Set and synch the privilege structure for the new service. */
504 if ((s
= sys_privctl(child_proc_nr_e
, SYS_PRIV_SET_SYS
, &rp
->r_priv
)) != OK
505 || (s
= sys_getpriv(&rp
->r_priv
, child_proc_nr_e
)) != OK
) {
506 printf("RS: unable to set privilege structure: %d\n", s
);
508 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
512 /* Set the scheduler for this process */
513 if ((s
= sched_init_proc(rp
)) != OK
) {
514 printf("RS: unable to start scheduling: %d\n", s
);
516 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
520 /* Copy the executable image into the child process. If no copy exists,
521 * allocate one and free it right after exec completes.
525 printf("RS: %s uses an in-memory copy\n",
529 if ((s
= read_exec(rp
)) != OK
) {
530 printf("RS: read_exec failed: %d\n", s
);
532 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
537 printf("RS: execing child with srv_execve()...\n");
538 s
= srv_execve(child_proc_nr_e
, rp
->r_exec
, rp
->r_exec_len
, rp
->r_argv
,
540 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
542 printf("RS: srv_execve failed: %d\n", s
);
550 /* If this is a VM instance, let VM know now. */
551 if(rp
->r_priv
.s_flags
& VM_SYS_PROC
) {
553 printf("RS: informing VM of instance %s\n", srv_to_string(rp
));
555 s
= vm_memctl(rpub
->endpoint
, VM_RS_MEM_MAKE_VM
);
557 printf("vm_memctl failed: %d\n", s
);
563 /* Tell VM about allowed calls. */
564 if ((s
= vm_set_priv(rpub
->endpoint
, &rpub
->vm_call_mask
[0])) != OK
) {
565 printf("RS: vm_set_priv failed: %d\n", s
);
571 printf("RS: %s created\n", srv_to_string(rp
));
576 /*===========================================================================*
578 *===========================================================================*/
579 int clone_service(rp
, instance_flag
)
583 /* Clone the given system service instance. */
584 struct rproc
*replica_rp
;
585 struct rprocpub
*replica_rpub
;
586 struct rproc
**rp_link
;
587 struct rproc
**replica_link
;
593 printf("RS: creating a replica for %s\n", srv_to_string(rp
));
596 if((r
= clone_slot(rp
, &replica_rp
)) != OK
) {
599 replica_rpub
= replica_rp
->r_pub
;
601 /* Clone is a live updated or restarted service instance? */
602 if(instance_flag
== LU_SYS_PROC
) {
603 rp_link
= &rp
->r_new_rp
;
604 replica_link
= &replica_rp
->r_old_rp
;
607 rp_link
= &rp
->r_next_rp
;
608 replica_link
= &replica_rp
->r_prev_rp
;
610 replica_rp
->r_priv
.s_flags
|= instance_flag
;
612 /* Link the two slots. */
613 *rp_link
= replica_rp
;
616 /* Create a new replica of the service. */
617 r
= create_service(replica_rp
);
623 /* If this instance is for restarting RS, set up a backup signal manager. */
624 rs_flags
= (ROOT_SYS_PROC
| RST_SYS_PROC
);
625 if((replica_rp
->r_priv
.s_flags
& rs_flags
) == rs_flags
) {
626 rs_rp
= rproc_ptr
[_ENDPOINT_P(RS_PROC_NR
)];
628 /* Update signal managers. */
629 r
= update_sig_mgrs(rs_rp
, SELF
, replica_rpub
->endpoint
);
631 r
= update_sig_mgrs(replica_rp
, SELF
, NONE
);
635 return kill_service(replica_rp
, "update_sig_mgrs failed", r
);
642 /*===========================================================================*
644 *===========================================================================*/
645 int publish_service(rp
)
646 struct rproc
*rp
; /* pointer to service slot */
648 /* Publish a service. */
650 struct rprocpub
*rpub
;
651 struct rs_pci pci_acl
;
657 /* Register label with DS. */
658 r
= ds_publish_label(rpub
->label
, rpub
->endpoint
, DSF_OVERWRITE
);
660 return kill_service(rp
, "ds_publish_label call failed", r
);
663 /* If the service is a driver, map it. */
664 if (rpub
->dev_nr
> 0) {
665 /* The purpose of non-blocking forks is to avoid involving VFS in the
666 * forking process, because VFS may be blocked on a sendrec() to a MFS
667 * that is waiting for a endpoint update for a dead driver. We have just
668 * published that update, but VFS may still be blocked. As a result, VFS
669 * may not yet have received PM's fork message. Hence, if we call
670 * mapdriver() immediately, VFS may not know about the process and thus
671 * refuse to add the driver entry. The following temporary hack works
672 * around this by forcing blocking communication from PM to VFS. Once VFS
673 * has been made non-blocking towards MFS instances, this hack and the
674 * big part of srv_fork() can go.
678 if (mapdriver(rpub
->label
, rpub
->dev_nr
, rpub
->dev_style
,
679 rpub
->dev_flags
) != OK
) {
680 return kill_service(rp
, "couldn't map driver", errno
);
685 /* If PCI properties are set, inform the PCI driver about the new service. */
686 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
687 pci_acl
= rpub
->pci_acl
;
688 strcpy(pci_acl
.rsp_label
, rpub
->label
);
689 pci_acl
.rsp_endpoint
= rpub
->endpoint
;
691 r
= pci_set_acl(&pci_acl
);
693 return kill_service(rp
, "pci_set_acl call failed", r
);
698 if (rpub
->devman_id
!= 0) {
699 r
= ds_retrieve_label_endpt("devman",&ep
);
702 return kill_service(rp
, "devman not running?", r
);
704 m
.m_type
= DEVMAN_BIND
;
705 m
.DEVMAN_ENDPOINT
= rpub
->endpoint
;
706 m
.DEVMAN_DEVICE_ID
= rpub
->devman_id
;
708 if (r
!= OK
|| m
.DEVMAN_RESULT
!= OK
) {
709 return kill_service(rp
, "devman bind device failed", r
);
714 printf("RS: %s published\n", srv_to_string(rp
));
719 /*===========================================================================*
720 * unpublish_service *
721 *===========================================================================*/
722 int unpublish_service(rp
)
723 struct rproc
*rp
; /* pointer to service slot */
725 /* Unpublish a service. */
726 struct rprocpub
*rpub
;
735 /* Unregister label with DS. */
736 r
= ds_delete_label(rpub
->label
);
737 if (r
!= OK
&& !shutting_down
) {
738 printf("RS: ds_delete_label call failed (error %d)\n", r
);
742 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
745 /* If PCI properties are set, inform the PCI driver. */
746 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
747 r
= pci_del_acl(rpub
->endpoint
);
748 if (r
!= OK
&& !shutting_down
) {
749 printf("RS: pci_del_acl call failed (error %d)\n", r
);
755 if (rpub
->devman_id
!= 0) {
756 r
= ds_retrieve_label_endpt("devman",&ep
);
759 printf("RS: devman not running?");
761 m
.m_type
= DEVMAN_UNBIND
;
762 m
.DEVMAN_ENDPOINT
= rpub
->endpoint
;
763 m
.DEVMAN_DEVICE_ID
= rpub
->devman_id
;
766 if (r
!= OK
|| m
.DEVMAN_RESULT
!= OK
) {
767 printf("RS: devman unbind device failed");
773 printf("RS: %s unpublished\n", srv_to_string(rp
));
778 /*===========================================================================*
780 *===========================================================================*/
781 int run_service(rp
, init_type
)
785 /* Let a newly created service run. */
786 struct rprocpub
*rpub
;
791 /* Allow the service to run. */
792 if ((s
= sys_privctl(rpub
->endpoint
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
793 return kill_service(rp
, "unable to allow the service to run",s
);
796 /* Initialize service. */
797 if((s
= init_service(rp
, init_type
)) != OK
) {
798 return kill_service(rp
, "unable to initialize service", s
);
802 printf("RS: %s allowed to run\n", srv_to_string(rp
));
807 /*===========================================================================*
809 *===========================================================================*/
810 int start_service(rp
)
813 /* Start a system service. */
815 struct rprocpub
*rpub
;
819 /* Create and make active. */
820 r
= create_service(rp
);
824 activate_service(rp
, NULL
);
826 /* Publish service properties. */
827 r
= publish_service(rp
);
833 init_type
= SEF_INIT_FRESH
;
834 r
= run_service(rp
, init_type
);
840 printf("RS: %s started with major %d\n", srv_to_string(rp
),
846 /*===========================================================================*
848 *===========================================================================*/
849 void stop_service(struct rproc
*rp
,int how
)
851 struct rprocpub
*rpub
;
856 /* Try to stop the system service. First send a SIGTERM signal to ask the
857 * system service to terminate. If the service didn't install a signal
858 * handler, it will be killed. If it did and ignores the signal, we'll
859 * find out because we record the time here and send a SIGKILL.
862 printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp
));
864 signo
= rpub
->endpoint
!= RS_PROC_NR
? SIGTERM
: SIGHUP
; /* SIGHUP for RS. */
866 rp
->r_flags
|= how
; /* what to on exit? */
867 sys_kill(rpub
->endpoint
, signo
); /* first try friendly */
868 getuptime(&rp
->r_stop_tm
); /* record current time */
871 /*===========================================================================*
873 *===========================================================================*/
874 int update_service(src_rpp
, dst_rpp
, swap_flag
)
875 struct rproc
**src_rpp
;
876 struct rproc
**dst_rpp
;
879 /* Update an existing service. */
881 struct rproc
*src_rp
;
882 struct rproc
*dst_rp
;
883 struct rprocpub
*src_rpub
;
884 struct rprocpub
*dst_rpub
;
890 src_rpub
= src_rp
->r_pub
;
891 dst_rpub
= dst_rp
->r_pub
;
894 printf("RS: %s updating into %s\n",
895 srv_to_string(src_rp
), srv_to_string(dst_rp
));
897 /* Swap the slots of the two processes when asked to. */
898 if(swap_flag
== RS_SWAP
) {
899 if((r
= srv_update(src_rpub
->endpoint
, dst_rpub
->endpoint
)) != OK
) {
904 /* Swap slots here as well. */
906 endpoint
= src_rpub
->endpoint
;
907 swap_slot(&src_rp
, &dst_rp
);
909 /* Reassign pids and endpoints. */
910 src_rp
->r_pid
= dst_rp
->r_pid
;
911 src_rp
->r_pub
->endpoint
= dst_rp
->r_pub
->endpoint
;
912 rproc_ptr
[_ENDPOINT_P(src_rp
->r_pub
->endpoint
)] = src_rp
;
914 dst_rp
->r_pub
->endpoint
= endpoint
;
915 rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)] = dst_rp
;
917 /* Adjust input pointers. */
921 /* Make the new version active. */
922 activate_service(dst_rp
, src_rp
);
925 printf("RS: %s updated into %s\n",
926 srv_to_string(src_rp
), srv_to_string(dst_rp
));
931 /*===========================================================================*
933 *===========================================================================*/
934 void activate_service(struct rproc
*rp
, struct rproc
*ex_rp
)
936 /* Activate a service instance and deactivate another one if requested. */
938 if(ex_rp
&& (ex_rp
->r_flags
& RS_ACTIVE
) ) {
939 ex_rp
->r_flags
&= ~RS_ACTIVE
;
941 printf("RS: %s becomes inactive\n", srv_to_string(ex_rp
));
944 if(! (rp
->r_flags
& RS_ACTIVE
) ) {
945 rp
->r_flags
|= RS_ACTIVE
;
947 printf("RS: %s becomes active\n", srv_to_string(rp
));
951 /*===========================================================================*
952 * reincarnate_service *
953 *===========================================================================*/
954 void reincarnate_service(struct rproc
*rp
)
956 /* Restart a service as if it were never started before. */
957 struct rprocpub
*rpub
;
962 rp
->r_flags
&= RS_IN_USE
;
964 rproc_ptr
[_ENDPOINT_P(rpub
->endpoint
)] = NULL
;
966 /* Restore original IRQ and I/O range tables in the priv struct. This is the
967 * only part of the privilege structure that can be modified by processes
968 * other than RS itself.
970 rp
->r_priv
.s_nr_irq
= rp
->r_nr_irq
;
971 for (i
= 0; i
< rp
->r_nr_irq
; i
++)
972 rp
->r_priv
.s_irq_tab
[i
] = rp
->r_irq_tab
[i
];
973 rp
->r_priv
.s_nr_io_range
= rp
->r_nr_io_range
;
974 for (i
= 0; i
< rp
->r_nr_io_range
; i
++)
975 rp
->r_priv
.s_io_tab
[i
] = rp
->r_io_tab
[i
];
979 rp
->r_prev_rp
= NULL
;
980 rp
->r_next_rp
= NULL
;
985 /*===========================================================================*
986 * terminate_service *
987 *===========================================================================*/
988 void terminate_service(struct rproc
*rp
)
990 /* Handle a termination event for a system service. */
992 struct rprocpub
*rpub
;
999 printf("RS: %s terminated\n", srv_to_string(rp
));
1001 /* Deal with failures during initialization. */
1002 if(rp
->r_flags
& RS_INITIALIZING
) {
1004 printf("RS: service '%s' exited during initialization\n",
1006 rp
->r_flags
|= RS_EXITING
; /* don't restart. */
1008 /* If updating, rollback. */
1009 if(rp
->r_flags
& RS_UPDATING
) {
1010 struct rproc
*old_rp
, *new_rp
;
1011 printf("RS: update failed: state transfer failed. Rolling back...\n");
1013 old_rp
= new_rp
->r_old_rp
;
1014 new_rp
->r_flags
&= ~RS_INITIALIZING
;
1015 r
= update_service(&new_rp
, &old_rp
, RS_SWAP
);
1016 assert(r
== OK
); /* can't fail */
1017 end_update(ERESTART
, RS_REPLY
);
1022 if (rp
->r_flags
& RS_EXITING
) {
1023 /* If a core system service is exiting, we are in trouble. */
1024 if (rp
->r_pub
->sys_flags
& SF_CORE_SRV
&& !shutting_down
) {
1025 printf("core system service died: %s\n", srv_to_string(rp
));
1029 /* See if a late reply has to be sent. */
1030 r
= (rp
->r_caller_request
== RS_DOWN
? OK
: EDEADEPT
);
1033 /* Unpublish the service. */
1034 unpublish_service(rp
);
1036 /* Cleanup all the instances of the service. */
1037 get_service_instances(rp
, &rps
, &nr_rps
);
1038 for(i
=0;i
<nr_rps
;i
++) {
1039 cleanup_service(rps
[i
]);
1042 /* If the service is reincarnating, its slot has not been cleaned up.
1043 * Check for this flag now, and attempt to start the service again.
1044 * If this fails, start_service() itself will perform cleanup.
1046 if (rp
->r_flags
& RS_REINCARNATE
) {
1047 reincarnate_service(rp
);
1050 else if(rp
->r_flags
& RS_REFRESHING
) {
1051 /* Restart service. */
1052 restart_service(rp
);
1055 /* If an update is in progress, end it. The old version
1056 * that just exited will continue executing.
1058 if(rp
->r_flags
& RS_UPDATING
) {
1059 end_update(ERESTART
, RS_DONTREPLY
);
1062 /* Determine what to do. If this is the first unexpected
1063 * exit, immediately restart this service. Otherwise use
1064 * a binary exponential backoff.
1066 if (rp
->r_restarts
> 0) {
1067 rp
->r_backoff
= 1 << MIN(rp
->r_restarts
,(BACKOFF_BITS
-2));
1068 rp
->r_backoff
= MIN(rp
->r_backoff
,MAX_BACKOFF
);
1069 if ((rpub
->sys_flags
& SF_USE_COPY
) && rp
->r_backoff
> 1)
1074 /* Restart service. */
1075 restart_service(rp
);
1079 /*===========================================================================*
1081 *===========================================================================*/
1082 static int run_script(struct rproc
*rp
)
1087 char incarnation_str
[20]; /* Enough for a counter? */
1088 char *envp
[1] = { NULL
};
1089 struct rprocpub
*rpub
;
1092 if (rp
->r_flags
& RS_REFRESHING
)
1094 else if (rp
->r_flags
& RS_NOPINGREPLY
)
1095 reason
= "no-heartbeat";
1096 else reason
= "terminated";
1097 sprintf(incarnation_str
, "%d", rp
->r_restarts
);
1100 printf("RS: %s:\n", srv_to_string(rp
));
1101 printf("RS: calling script '%s'\n", rp
->r_script
);
1102 printf("RS: reason: '%s'\n", reason
);
1103 printf("RS: incarnation: '%s'\n", incarnation_str
);
1110 return kill_service(rp
, "unable to fork script", errno
);
1112 execle(rp
->r_script
, rp
->r_script
, rpub
->label
, reason
,
1113 incarnation_str
, (char*) NULL
, envp
);
1114 printf("RS: run_script: execl '%s' failed: %s\n",
1115 rp
->r_script
, strerror(errno
));
1118 /* Set the privilege structure for the child process. */
1119 endpoint
= getnprocnr(pid
);
1120 if ((r
= sys_privctl(endpoint
, SYS_PRIV_SET_USER
, NULL
))
1122 return kill_service(rp
,"can't set script privileges",r
);
1124 /* Allow the script to run. */
1125 if ((r
= sys_privctl(endpoint
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
1126 return kill_service(rp
,"can't let the script run",r
);
1128 /* Pin RS memory again after fork()ing. */
1129 vm_memctl(RS_PROC_NR
, VM_RS_MEM_PIN
);
1134 /*===========================================================================*
1136 *===========================================================================*/
1137 void restart_service(struct rproc
*rp
)
1139 /* Restart service via a recovery script or directly. */
1140 struct rproc
*replica_rp
;
1143 /* See if a late reply has to be sent. */
1146 /* This hack disables restarting of file servers, which at the moment always
1147 * cause VFS to hang indefinitely. As soon as VFS no longer blocks on calls
1148 * to file servers, this exception can be removed again.
1150 if (!strncmp(rp
->r_pub
->label
, "fs_", 3)) {
1151 kill_service(rp
, "file servers cannot be restarted yet", ENOSYS
);
1155 /* Run a recovery script if available. */
1156 if (rp
->r_script
[0] != '\0') {
1161 /* Restart directly. We need a replica if not already available. */
1162 if(rp
->r_next_rp
== NULL
) {
1163 /* Create the replica. */
1164 r
= clone_service(rp
, RST_SYS_PROC
);
1166 kill_service(rp
, "unable to clone service", r
);
1170 replica_rp
= rp
->r_next_rp
;
1172 /* Update the service into the replica. */
1173 r
= update_service(&rp
, &replica_rp
, RS_SWAP
);
1175 kill_service(rp
, "unable to update into new replica", r
);
1179 /* Let the new replica run. */
1180 r
= run_service(replica_rp
, SEF_INIT_RESTART
);
1182 kill_service(rp
, "unable to let the replica run", r
);
1187 printf("RS: %s restarted into %s\n",
1188 srv_to_string(rp
), srv_to_string(replica_rp
));
1191 /*===========================================================================*
1192 * inherit_service_defaults *
1193 *===========================================================================*/
1194 void inherit_service_defaults(def_rp
, rp
)
1195 struct rproc
*def_rp
;
1198 struct rprocpub
*def_rpub
;
1199 struct rprocpub
*rpub
;
1201 def_rpub
= def_rp
->r_pub
;
1204 /* Device and PCI settings. These properties cannot change. */
1205 rpub
->dev_flags
= def_rpub
->dev_flags
;
1206 rpub
->dev_nr
= def_rpub
->dev_nr
;
1207 rpub
->dev_style
= def_rpub
->dev_style
;
1208 rpub
->dev_style2
= def_rpub
->dev_style2
;
1209 rpub
->pci_acl
= def_rpub
->pci_acl
;
1211 /* Immutable system and privilege flags. */
1212 rpub
->sys_flags
&= ~IMM_SF
;
1213 rpub
->sys_flags
|= (def_rpub
->sys_flags
& IMM_SF
);
1214 rp
->r_priv
.s_flags
&= ~IMM_F
;
1215 rp
->r_priv
.s_flags
|= (def_rp
->r_priv
.s_flags
& IMM_F
);
1217 /* Allowed traps. They cannot change. */
1218 rp
->r_priv
.s_trap_mask
= def_rp
->r_priv
.s_trap_mask
;
1221 /*===========================================================================*
1222 * get_service_instances *
1223 *===========================================================================*/
1224 void get_service_instances(rp
, rps
, length
)
1226 struct rproc
***rps
;
1229 /* Retrieve all the service instances of a given service. */
1230 static struct rproc
*instances
[5];
1234 instances
[nr_instances
++] = rp
;
1235 if(rp
->r_prev_rp
) instances
[nr_instances
++] = rp
->r_prev_rp
;
1236 if(rp
->r_next_rp
) instances
[nr_instances
++] = rp
->r_next_rp
;
1237 if(rp
->r_old_rp
) instances
[nr_instances
++] = rp
->r_old_rp
;
1238 if(rp
->r_new_rp
) instances
[nr_instances
++] = rp
->r_new_rp
;
1241 *length
= nr_instances
;
1244 /*===========================================================================*
1246 *===========================================================================*/
1247 void share_exec(rp_dst
, rp_src
)
1248 struct rproc
*rp_dst
, *rp_src
;
1251 printf("RS: %s shares exec image with %s\n",
1252 srv_to_string(rp_dst
), srv_to_string(rp_src
));
1254 /* Share exec image from rp_src to rp_dst. */
1255 rp_dst
->r_exec_len
= rp_src
->r_exec_len
;
1256 rp_dst
->r_exec
= rp_src
->r_exec
;
1259 /*===========================================================================*
1261 *===========================================================================*/
1269 e_name
= rp
->r_argv
[0];
1271 printf("RS: service '%s' reads exec image from: %s\n", rp
->r_pub
->label
,
1274 r
= stat(e_name
, &sb
);
1278 fd
= open(e_name
, O_RDONLY
);
1282 rp
->r_exec_len
= sb
.st_size
;
1283 rp
->r_exec
= malloc(rp
->r_exec_len
);
1284 if (rp
->r_exec
== NULL
)
1286 printf("RS: read_exec: unable to allocate %d bytes\n",
1292 r
= read(fd
, rp
->r_exec
, rp
->r_exec_len
);
1295 if (r
== rp
->r_exec_len
)
1298 printf("RS: read_exec: read failed %d, errno %d\n", r
, e
);
1308 /*===========================================================================*
1310 *===========================================================================*/
1314 /* Free an exec image. */
1315 int slot_nr
, has_shared_exec
;
1316 struct rproc
*other_rp
;
1318 /* Search for some other slot sharing the same exec image. */
1319 has_shared_exec
= FALSE
;
1320 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1321 other_rp
= &rproc
[slot_nr
]; /* get pointer to slot */
1322 if (other_rp
->r_flags
& RS_IN_USE
&& other_rp
!= rp
1323 && other_rp
->r_exec
== rp
->r_exec
) { /* found! */
1324 has_shared_exec
= TRUE
;
1329 /* If nobody uses our copy of the exec image, we can try to get rid of it. */
1330 if(!has_shared_exec
) {
1332 printf("RS: %s frees exec image\n", srv_to_string(rp
));
1337 printf("RS: %s no longer sharing exec image with %s\n",
1338 srv_to_string(rp
), srv_to_string(other_rp
));
1344 /*===========================================================================*
1346 *===========================================================================*/
1347 int edit_slot(rp
, rs_start
, source
)
1349 struct rs_start
*rs_start
;
1352 /* Edit a given slot to override existing settings. */
1353 struct rprocpub
*rpub
;
1357 int basic_kc
[] = { SYS_BASIC_CALLS
, NULL_C
};
1358 int basic_vmc
[] = { VM_BASIC_CALLS
, NULL_C
};
1362 /* Update IPC target list. */
1363 if (rs_start
->rss_ipclen
==0 || rs_start
->rss_ipclen
+1>sizeof(rp
->r_ipc_list
)){
1364 printf("RS: edit_slot: ipc list empty or long for '%s'\n", rpub
->label
);
1367 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_ipc
,
1368 SELF
, (vir_bytes
) rp
->r_ipc_list
, rs_start
->rss_ipclen
);
1369 if (s
!= OK
) return(s
);
1370 rp
->r_ipc_list
[rs_start
->rss_ipclen
]= '\0';
1373 if(rs_start
->rss_nr_irq
== RSS_IRQ_ALL
) {
1374 rs_start
->rss_nr_irq
= 0;
1377 rp
->r_priv
.s_flags
|= CHECK_IRQ
;
1379 if (rs_start
->rss_nr_irq
> NR_IRQ
) {
1380 printf("RS: edit_slot: too many IRQs requested\n");
1383 rp
->r_nr_irq
= rp
->r_priv
.s_nr_irq
= rs_start
->rss_nr_irq
;
1384 for (i
= 0; i
<rp
->r_priv
.s_nr_irq
; i
++) {
1385 rp
->r_irq_tab
[i
]= rp
->r_priv
.s_irq_tab
[i
]= rs_start
->rss_irq
[i
];
1387 printf("RS: edit_slot: IRQ %d\n", rp
->r_priv
.s_irq_tab
[i
]);
1390 /* Update I/O ranges. */
1391 if(rs_start
->rss_nr_io
== RSS_IO_ALL
) {
1392 rs_start
->rss_nr_io
= 0;
1395 rp
->r_priv
.s_flags
|= CHECK_IO_PORT
;
1397 if (rs_start
->rss_nr_io
> NR_IO_RANGE
) {
1398 printf("RS: edit_slot: too many I/O ranges requested\n");
1401 rp
->r_nr_io_range
= rp
->r_priv
.s_nr_io_range
= rs_start
->rss_nr_io
;
1402 for (i
= 0; i
<rp
->r_priv
.s_nr_io_range
; i
++) {
1403 rp
->r_priv
.s_io_tab
[i
].ior_base
= rs_start
->rss_io
[i
].base
;
1404 rp
->r_priv
.s_io_tab
[i
].ior_limit
=
1405 rs_start
->rss_io
[i
].base
+rs_start
->rss_io
[i
].len
-1;
1406 rp
->r_io_tab
[i
] = rp
->r_priv
.s_io_tab
[i
];
1408 printf("RS: edit_slot: I/O [%x..%x]\n",
1409 rp
->r_priv
.s_io_tab
[i
].ior_base
,
1410 rp
->r_priv
.s_io_tab
[i
].ior_limit
);
1413 /* Update kernel call mask. Inherit basic kernel calls when asked to. */
1414 memcpy(rp
->r_priv
.s_k_call_mask
, rs_start
->rss_system
,
1415 sizeof(rp
->r_priv
.s_k_call_mask
));
1416 if(rs_start
->rss_flags
& RSS_SYS_BASIC_CALLS
) {
1417 fill_call_mask(basic_kc
, NR_SYS_CALLS
,
1418 rp
->r_priv
.s_k_call_mask
, KERNEL_CALL
, FALSE
);
1421 /* Update VM call mask. Inherit basic VM calls. */
1422 memcpy(rpub
->vm_call_mask
, rs_start
->rss_vm
,
1423 sizeof(rpub
->vm_call_mask
));
1424 if(rs_start
->rss_flags
& RSS_VM_BASIC_CALLS
) {
1425 fill_call_mask(basic_vmc
, NR_VM_CALLS
,
1426 rpub
->vm_call_mask
, VM_RQ_BASE
, FALSE
);
1429 /* Update control labels. */
1430 if(rs_start
->rss_nr_control
> 0) {
1432 if (rs_start
->rss_nr_control
> RS_NR_CONTROL
) {
1433 printf("RS: edit_slot: too many control labels\n");
1436 for (i
=0; i
<rs_start
->rss_nr_control
; i
++) {
1437 s
= copy_label(source
, rs_start
->rss_control
[i
].l_addr
,
1438 rs_start
->rss_control
[i
].l_len
, rp
->r_control
[i
],
1439 sizeof(rp
->r_control
[i
]));
1443 rp
->r_nr_control
= rs_start
->rss_nr_control
;
1446 printf("RS: edit_slot: control labels:");
1447 for (i
=0; i
<rp
->r_nr_control
; i
++)
1448 printf(" %s", rp
->r_control
[i
]);
1453 /* Update signal manager. */
1454 rp
->r_priv
.s_sig_mgr
= rs_start
->rss_sigmgr
;
1456 /* Update scheduling properties if possible. */
1457 if(rp
->r_scheduler
!= NONE
) {
1458 rp
->r_scheduler
= rs_start
->rss_scheduler
;
1459 rp
->r_priority
= rs_start
->rss_priority
;
1460 rp
->r_quantum
= rs_start
->rss_quantum
;
1461 rp
->r_cpu
= rs_start
->rss_cpu
;
1464 /* Update command and arguments. */
1465 if (rs_start
->rss_cmdlen
> MAX_COMMAND_LEN
-1) return(E2BIG
);
1466 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_cmd
,
1467 SELF
, (vir_bytes
) rp
->r_cmd
, rs_start
->rss_cmdlen
);
1468 if (s
!= OK
) return(s
);
1469 rp
->r_cmd
[rs_start
->rss_cmdlen
] = '\0'; /* ensure it is terminated */
1470 if (rp
->r_cmd
[0] != '/') return(EINVAL
); /* insist on absolute path */
1472 /* Build cmd dependencies: argv and program name. */
1475 /* Update label if not already set. */
1476 if(!strcmp(rpub
->label
, "")) {
1477 if(rs_start
->rss_label
.l_len
> 0) {
1478 /* RS_UP caller has supplied a custom label for this service. */
1479 int s
= copy_label(source
, rs_start
->rss_label
.l_addr
,
1480 rs_start
->rss_label
.l_len
, rpub
->label
, sizeof(rpub
->label
));
1484 printf("RS: edit_slot: using label (custom) '%s'\n", rpub
->label
);
1486 /* Default label for the service. */
1487 label
= rpub
->proc_name
;
1489 memcpy(rpub
->label
, label
, len
);
1490 rpub
->label
[len
]= '\0';
1492 printf("RS: edit_slot: using label (from proc_name) '%s'\n",
1497 /* Update recovery script. */
1498 if (rs_start
->rss_scriptlen
> MAX_SCRIPT_LEN
-1) return(E2BIG
);
1499 if (rs_start
->rss_script
!= NULL
&& !(rpub
->sys_flags
& SF_CORE_SRV
)) {
1500 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_script
,
1501 SELF
, (vir_bytes
) rp
->r_script
, rs_start
->rss_scriptlen
);
1502 if (s
!= OK
) return(s
);
1503 rp
->r_script
[rs_start
->rss_scriptlen
] = '\0';
1506 /* Update system flags and in-memory copy. */
1507 if ((rs_start
->rss_flags
& RSS_COPY
) && !(rpub
->sys_flags
& SF_USE_COPY
)) {
1510 struct rprocpub
*rpub2
;
1513 if(rs_start
->rss_flags
& RSS_REUSE
) {
1516 for(i
= 0; i
< NR_SYS_PROCS
; i
++) {
1518 if (!(rp2
->r_flags
& RS_IN_USE
)) {
1521 rpub2
= rproc
[i
].r_pub
;
1522 if(strcmp(rpub
->proc_name
, rpub2
->proc_name
) == 0 &&
1523 (rpub2
->sys_flags
& SF_USE_COPY
)) {
1524 /* We have found the same binary that's
1525 * already been copied */
1536 share_exec(rp
, rp2
);
1541 rpub
->sys_flags
|= SF_USE_COPY
;
1543 if (rs_start
->rss_flags
& RSS_REPLICA
) {
1544 rpub
->sys_flags
|= SF_USE_REPL
;
1547 /* Update period. */
1548 if(rpub
->endpoint
!= RS_PROC_NR
) {
1549 rp
->r_period
= rs_start
->rss_period
;
1552 /* (Re)initialize privilege settings. */
1553 init_privs(rp
, &rp
->r_priv
);
1558 /*===========================================================================*
1560 *===========================================================================*/
1561 int init_slot(rp
, rs_start
, source
)
1563 struct rs_start
*rs_start
;
1566 /* Initialize a slot as requested by the client. */
1567 struct rprocpub
*rpub
;
1572 /* All dynamically created services get the same sys and privilege flags, and
1573 * allowed traps. Other privilege settings can be specified at runtime. The
1574 * privilege id is dynamically allocated by the kernel.
1576 rpub
->sys_flags
= DSRV_SF
; /* system flags */
1577 rp
->r_priv
.s_flags
= DSRV_F
; /* privilege flags */
1578 rp
->r_priv
.s_trap_mask
= DSRV_T
; /* allowed traps */
1579 rp
->r_priv
.s_bak_sig_mgr
= NONE
; /* backup signal manager */
1581 /* Initialize uid. */
1582 rp
->r_uid
= rs_start
->rss_uid
;
1584 /* Initialize device driver settings. */
1585 rpub
->dev_flags
= DSRV_DF
;
1586 rpub
->dev_nr
= rs_start
->rss_major
;
1587 rpub
->dev_style
= rs_start
->rss_dev_style
;
1588 rpub
->devman_id
= rs_start
->devman_id
;
1589 if(rpub
->dev_nr
&& !IS_DEV_STYLE(rs_start
->rss_dev_style
)) {
1590 printf("RS: init_slot: bad device style\n");
1593 rpub
->dev_style2
= STYLE_NDEV
;
1595 /* Initialize pci settings. */
1596 if (rs_start
->rss_nr_pci_id
> RS_NR_PCI_DEVICE
) {
1597 printf("RS: init_slot: too many PCI device IDs\n");
1600 rpub
->pci_acl
.rsp_nr_device
= rs_start
->rss_nr_pci_id
;
1601 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_device
; i
++) {
1602 rpub
->pci_acl
.rsp_device
[i
].vid
= rs_start
->rss_pci_id
[i
].vid
;
1603 rpub
->pci_acl
.rsp_device
[i
].did
= rs_start
->rss_pci_id
[i
].did
;
1605 printf("RS: init_slot: PCI %04x/%04x\n",
1606 rpub
->pci_acl
.rsp_device
[i
].vid
,
1607 rpub
->pci_acl
.rsp_device
[i
].did
);
1609 if (rs_start
->rss_nr_pci_class
> RS_NR_PCI_CLASS
) {
1610 printf("RS: init_slot: too many PCI class IDs\n");
1613 rpub
->pci_acl
.rsp_nr_class
= rs_start
->rss_nr_pci_class
;
1614 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_class
; i
++) {
1615 rpub
->pci_acl
.rsp_class
[i
].pciclass
=rs_start
->rss_pci_class
[i
].pciclass
;
1616 rpub
->pci_acl
.rsp_class
[i
].mask
= rs_start
->rss_pci_class
[i
].mask
;
1618 printf("RS: init_slot: PCI class %06x mask %06x\n",
1619 (unsigned int) rpub
->pci_acl
.rsp_class
[i
].pciclass
,
1620 (unsigned int) rpub
->pci_acl
.rsp_class
[i
].mask
);
1623 /* Initialize some fields. */
1624 rp
->r_restarts
= 0; /* no restarts yet */
1625 rp
->r_old_rp
= NULL
; /* no old version yet */
1626 rp
->r_new_rp
= NULL
; /* no new version yet */
1627 rp
->r_prev_rp
= NULL
; /* no prev replica yet */
1628 rp
->r_next_rp
= NULL
; /* no next replica yet */
1629 rp
->r_exec
= NULL
; /* no in-memory copy yet */
1631 rp
->r_script
[0]= '\0'; /* no recovery script yet */
1632 rpub
->label
[0]= '\0'; /* no label yet */
1633 rp
->r_scheduler
= -1; /* no scheduler yet */
1634 rp
->r_priv
.s_sig_mgr
= -1; /* no signal manager yet */
1636 /* Initialize editable slot settings. */
1637 return edit_slot(rp
, rs_start
, source
);
1640 /*===========================================================================*
1642 *===========================================================================*/
1643 int clone_slot(rp
, clone_rpp
)
1645 struct rproc
**clone_rpp
;
1648 struct rproc
*clone_rp
;
1649 struct rprocpub
*rpub
, *clone_rpub
;
1651 /* Allocate a system service slot for the clone. */
1652 r
= alloc_slot(&clone_rp
);
1654 printf("RS: clone_slot: unable to allocate a new slot: %d\n", r
);
1659 clone_rpub
= clone_rp
->r_pub
;
1661 /* Synch the privilege structure of the source with the kernel. */
1662 if ((r
= sys_getpriv(&(rp
->r_priv
), rpub
->endpoint
)) != OK
) {
1663 panic("unable to synch privilege structure: %d", r
);
1668 *clone_rpub
= *rpub
;
1671 clone_rp
->r_flags
&= ~RS_ACTIVE
; /* the clone is not active yet */
1672 clone_rp
->r_pid
= -1; /* no pid yet */
1673 clone_rpub
->endpoint
= -1; /* no endpoint yet */
1674 clone_rp
->r_pub
= clone_rpub
; /* restore pointer to public entry */
1675 build_cmd_dep(clone_rp
); /* rebuild cmd dependencies */
1676 if(clone_rpub
->sys_flags
& SF_USE_COPY
) {
1677 share_exec(clone_rp
, rp
); /* share exec image */
1679 clone_rp
->r_old_rp
= NULL
; /* no old version yet */
1680 clone_rp
->r_new_rp
= NULL
; /* no new version yet */
1681 clone_rp
->r_prev_rp
= NULL
; /* no prev replica yet */
1682 clone_rp
->r_next_rp
= NULL
; /* no next replica yet */
1684 /* Force dynamic privilege id. */
1685 clone_rp
->r_priv
.s_flags
|= DYN_PRIV_ID
;
1687 /* Clear instance flags. */
1688 clone_rp
->r_priv
.s_flags
&= ~(LU_SYS_PROC
| RST_SYS_PROC
);
1690 *clone_rpp
= clone_rp
;
1694 /*===========================================================================*
1695 * swap_slot_pointer *
1696 *===========================================================================*/
1697 static void swap_slot_pointer(struct rproc
**rpp
, struct rproc
*src_rp
,
1698 struct rproc
*dst_rp
)
1700 if(*rpp
== src_rp
) {
1703 else if(*rpp
== dst_rp
) {
1708 /*===========================================================================*
1710 *===========================================================================*/
1711 void swap_slot(src_rpp
, dst_rpp
)
1712 struct rproc
**src_rpp
;
1713 struct rproc
**dst_rpp
;
1715 /* Swap two service slots. */
1716 struct rproc
*src_rp
;
1717 struct rproc
*dst_rp
;
1718 struct rprocpub
*src_rpub
;
1719 struct rprocpub
*dst_rpub
;
1720 struct rproc orig_src_rproc
, orig_dst_rproc
;
1721 struct rprocpub orig_src_rprocpub
, orig_dst_rprocpub
;
1725 src_rpub
= src_rp
->r_pub
;
1726 dst_rpub
= dst_rp
->r_pub
;
1728 /* Save existing data first. */
1729 orig_src_rproc
= *src_rp
;
1730 orig_src_rprocpub
= *src_rpub
;
1731 orig_dst_rproc
= *dst_rp
;
1732 orig_dst_rprocpub
= *dst_rpub
;
1735 *src_rp
= orig_dst_rproc
;
1736 *src_rpub
= orig_dst_rprocpub
;
1737 *dst_rp
= orig_src_rproc
;
1738 *dst_rpub
= orig_src_rprocpub
;
1740 /* Restore public entries. */
1741 src_rp
->r_pub
= orig_src_rproc
.r_pub
;
1742 dst_rp
->r_pub
= orig_dst_rproc
.r_pub
;
1744 /* Rebuild command dependencies. */
1745 build_cmd_dep(src_rp
);
1746 build_cmd_dep(dst_rp
);
1748 /* Swap local slot pointers. */
1749 swap_slot_pointer(&src_rp
->r_prev_rp
, src_rp
, dst_rp
);
1750 swap_slot_pointer(&src_rp
->r_next_rp
, src_rp
, dst_rp
);
1751 swap_slot_pointer(&src_rp
->r_old_rp
, src_rp
, dst_rp
);
1752 swap_slot_pointer(&src_rp
->r_new_rp
, src_rp
, dst_rp
);
1753 swap_slot_pointer(&dst_rp
->r_prev_rp
, src_rp
, dst_rp
);
1754 swap_slot_pointer(&dst_rp
->r_next_rp
, src_rp
, dst_rp
);
1755 swap_slot_pointer(&dst_rp
->r_old_rp
, src_rp
, dst_rp
);
1756 swap_slot_pointer(&dst_rp
->r_new_rp
, src_rp
, dst_rp
);
1758 /* Swap global slot pointers. */
1759 swap_slot_pointer(&rupdate
.rp
, src_rp
, dst_rp
);
1760 swap_slot_pointer(&rproc_ptr
[_ENDPOINT_P(src_rp
->r_pub
->endpoint
)],
1762 swap_slot_pointer(&rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)],
1765 /* Adjust input pointers. */
1770 /*===========================================================================*
1771 * lookup_slot_by_label *
1772 *===========================================================================*/
1773 struct rproc
* lookup_slot_by_label(char *label
)
1775 /* Lookup a service slot matching the given label. */
1778 struct rprocpub
*rpub
;
1780 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1781 rp
= &rproc
[slot_nr
];
1782 if (!(rp
->r_flags
& RS_ACTIVE
)) {
1786 if (strcmp(rpub
->label
, label
) == 0) {
1794 /*===========================================================================*
1795 * lookup_slot_by_pid *
1796 *===========================================================================*/
1797 struct rproc
* lookup_slot_by_pid(pid_t pid
)
1799 /* Lookup a service slot matching the given pid. */
1807 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1808 rp
= &rproc
[slot_nr
];
1809 if (!(rp
->r_flags
& RS_IN_USE
)) {
1812 if (rp
->r_pid
== pid
) {
1820 /*===========================================================================*
1821 * lookup_slot_by_dev_nr *
1822 *===========================================================================*/
1823 struct rproc
* lookup_slot_by_dev_nr(dev_t dev_nr
)
1825 /* Lookup a service slot matching the given device number. */
1828 struct rprocpub
*rpub
;
1834 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1835 rp
= &rproc
[slot_nr
];
1837 if (!(rp
->r_flags
& RS_IN_USE
)) {
1840 if (rpub
->dev_nr
== dev_nr
) {
1848 /*===========================================================================*
1849 * lookup_slot_by_flags *
1850 *===========================================================================*/
1851 struct rproc
* lookup_slot_by_flags(int flags
)
1853 /* Lookup a service slot matching the given flags. */
1861 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1862 rp
= &rproc
[slot_nr
];
1863 if (!(rp
->r_flags
& RS_IN_USE
)) {
1866 if (rp
->r_flags
& flags
) {
1874 /*===========================================================================*
1876 *===========================================================================*/
1880 /* Alloc a new system service slot. */
1883 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1884 *rpp
= &rproc
[slot_nr
]; /* get pointer to slot */
1885 if (!((*rpp
)->r_flags
& RS_IN_USE
)) /* check if available */
1888 if (slot_nr
>= NR_SYS_PROCS
) {
1895 /*===========================================================================*
1897 *===========================================================================*/
1901 /* Free a system service slot. */
1902 struct rprocpub
*rpub
;
1906 /* Send a late reply if there is any pending. */
1909 /* Free memory if necessary. */
1910 if(rpub
->sys_flags
& SF_USE_COPY
) {
1914 /* Mark slot as no longer in use.. */
1917 rpub
->in_use
= FALSE
;
1918 rproc_ptr
[_ENDPOINT_P(rpub
->endpoint
)] = NULL
;
1922 /*===========================================================================*
1924 *===========================================================================*/
1925 static char *get_next_name(ptr
, name
, caller_label
)
1930 /* Get the next name from the list of (IPC) program names.
1935 for (p
= ptr
; p
[0] != '\0'; p
= q
)
1937 /* Skip leading space */
1938 while (p
[0] != '\0' && isspace((unsigned char)p
[0]))
1941 /* Find start of next word */
1943 while (q
[0] != '\0' && !isspace((unsigned char)q
[0]))
1948 if (len
> RS_MAX_LABEL_LEN
)
1951 "rs:get_next_name: bad ipc list entry '%.*s' for %s: too long\n",
1952 len
, p
, caller_label
);
1955 memcpy(name
, p
, len
);
1958 return q
; /* found another */
1961 return NULL
; /* done */
1964 /*===========================================================================*
1966 *===========================================================================*/
1967 void add_forward_ipc(rp
, privp
)
1971 /* Add IPC send permissions to a process based on that process's IPC
1974 char name
[RS_MAX_LABEL_LEN
+1], *p
;
1976 endpoint_t endpoint
;
1980 struct rprocpub
*rpub
;
1985 while ((p
= get_next_name(p
, name
, rpub
->label
)) != NULL
) {
1987 if (strcmp(name
, "SYSTEM") == 0)
1989 else if (strcmp(name
, "USER") == 0)
1990 endpoint
= INIT_PROC_NR
; /* all user procs */
1993 /* Set a privilege bit for every process matching the
1994 * given process name. It is perfectly fine if this
1995 * loop does not find any matches, as the target
1996 * process(es) may not have been started yet. See
1997 * add_backward_ipc() below.
1999 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
2000 if (!(rrp
->r_flags
& RS_IN_USE
))
2003 if (!strcmp(rrp
->r_pub
->proc_name
, name
)) {
2005 printf(" RS: add_forward_ipc: setting"
2006 " sendto bit for %d...\n",
2007 rrp
->r_pub
->endpoint
);
2010 priv_id
= rrp
->r_priv
.s_id
;
2011 set_sys_bit(privp
->s_ipc_to
, priv_id
);
2018 /* This code only applies to the exception cases. */
2019 if ((r
= sys_getpriv(&priv
, endpoint
)) < 0)
2022 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
2028 printf(" RS: add_forward_ipc: setting sendto bit for %d...\n",
2032 set_sys_bit(privp
->s_ipc_to
, priv_id
);
2037 /*===========================================================================*
2038 * add_backward_ipc *
2039 *===========================================================================*/
2040 void add_backward_ipc(rp
, privp
)
2044 /* Add IPC send permissions to a process based on other processes' IPC
2045 * lists. This is enough to allow each such two processes to talk to
2046 * each other, as the kernel guarantees send mask symmetry. We need to
2047 * add these permissions now because the current process may not yet
2048 * have existed at the time that the other process was initialized.
2050 char name
[RS_MAX_LABEL_LEN
+1], *p
;
2052 struct rprocpub
*rrpub
;
2054 int priv_id
, is_ipc_all
, is_ipc_all_sys
;
2056 proc_name
= rp
->r_pub
->proc_name
;
2058 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
2059 if (!(rrp
->r_flags
& RS_IN_USE
))
2062 if (!rrp
->r_ipc_list
[0])
2065 /* If the process being checked is set to allow IPC to all
2066 * other processes, or for all other system processes and the
2067 * target process is a system process, add a permission bit.
2071 is_ipc_all
= !strcmp(rrp
->r_ipc_list
, RSS_IPC_ALL
);
2072 is_ipc_all_sys
= !strcmp(rrp
->r_ipc_list
, RSS_IPC_ALL_SYS
);
2075 (is_ipc_all_sys
&& (privp
->s_flags
& SYS_PROC
))) {
2077 printf(" RS: add_backward_ipc: setting sendto bit "
2078 "for %d...\n", rrpub
->endpoint
);
2080 priv_id
= rrp
->r_priv
.s_id
;
2081 set_sys_bit(privp
->s_ipc_to
, priv_id
);
2086 /* An IPC target list was provided for the process being
2087 * checked here. Make sure that the name of the new process
2088 * is in that process's list. There may be multiple matches.
2090 p
= rrp
->r_ipc_list
;
2092 while ((p
= get_next_name(p
, name
, rrpub
->label
)) != NULL
) {
2093 if (!strcmp(proc_name
, name
)) {
2095 printf(" RS: add_backward_ipc: setting sendto"
2099 priv_id
= rrp
->r_priv
.s_id
;
2100 set_sys_bit(privp
->s_ipc_to
, priv_id
);
2107 /*===========================================================================*
2109 *===========================================================================*/
2110 void init_privs(rp
, privp
)
2115 int is_ipc_all
, is_ipc_all_sys
;
2117 /* Clear s_ipc_to */
2118 fill_send_mask(&privp
->s_ipc_to
, FALSE
);
2120 is_ipc_all
= !strcmp(rp
->r_ipc_list
, RSS_IPC_ALL
);
2121 is_ipc_all_sys
= !strcmp(rp
->r_ipc_list
, RSS_IPC_ALL_SYS
);
2124 printf(" RS: init_privs: ipc list is '%s'...\n", rp
->r_ipc_list
);
2127 if (!is_ipc_all
&& !is_ipc_all_sys
)
2129 add_forward_ipc(rp
, privp
);
2130 add_backward_ipc(rp
, privp
);
2135 for (i
= 0; i
<NR_SYS_PROCS
; i
++)
2137 if (is_ipc_all
|| i
!= USER_PRIV_ID
)
2138 set_sys_bit(privp
->s_ipc_to
, i
);