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 /*===========================================================================*
12 *===========================================================================*/
13 PUBLIC
int caller_is_root(endpoint
)
14 endpoint_t endpoint
; /* caller endpoint */
18 /* Check if caller has root user ID. */
19 euid
= getnuid(endpoint
);
20 if (rs_verbose
&& euid
!= 0)
22 printf("RS: got unauthorized request from endpoint %d\n", endpoint
);
28 /*===========================================================================*
29 * caller_can_control *
30 *===========================================================================*/
31 PUBLIC
int caller_can_control(endpoint
, label
)
35 int control_allowed
= 0;
36 register struct rproc
*rp
;
37 register struct rprocpub
*rpub
;
41 /* Find name of binary for given label. */
42 rp
= lookup_slot_by_label(label
);
44 progname
= strrchr(rp
->r_argv
[0], '/');
48 progname
= rp
->r_argv
[0];
50 /* Check if label is listed in caller's isolation policy. */
51 for (rp
= BEG_RPROC_ADDR
; rp
< END_RPROC_ADDR
; rp
++) {
53 if (rpub
->endpoint
== endpoint
) {
57 if (rp
== END_RPROC_ADDR
) return 0;
58 if (rp
->r_nr_control
> 0) {
59 for (c
= 0; c
< rp
->r_nr_control
; c
++) {
60 if (strcmp(rp
->r_control
[c
], progname
) == 0)
66 printf("RS: allowing %u control over %s via policy: %s\n",
67 endpoint
, label
, control_allowed
? "yes" : "no");
69 return control_allowed
;
72 /*===========================================================================*
73 * check_call_permission *
74 *===========================================================================*/
75 PUBLIC
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
->r_pub
->label
);
96 /* Disallow the call if the target is RS or a user process. */
97 if(!(rp
->r_priv
.s_flags
& SYS_PROC
) || rpub
->endpoint
== RS_PROC_NR
) {
101 /* Disallow the call if another call is in progress for the service. */
102 if(rp
->r_flags
& RS_LATEREPLY
|| rp
->r_flags
& RS_INITIALIZING
) {
106 /* Only allow RS_DOWN and RS_RESTART if the service has terminated. */
107 if(rp
->r_flags
& RS_TERMINATED
) {
108 if(call
!= RS_DOWN
&& call
!= RS_RESTART
) return EPERM
;
111 /* Disallow RS_DOWN for core system services. */
112 if (rpub
->sys_flags
& SF_CORE_SRV
) {
113 if(call
== RS_DOWN
) return EPERM
;
120 /*===========================================================================*
122 *===========================================================================*/
123 PUBLIC
int copy_rs_start(src_e
, src_rs_start
, dst_rs_start
)
126 struct rs_start
*dst_rs_start
;
130 r
= sys_datacopy(src_e
, (vir_bytes
) src_rs_start
,
131 SELF
, (vir_bytes
) dst_rs_start
, sizeof(struct rs_start
));
136 /*===========================================================================*
138 *===========================================================================*/
139 PUBLIC
int copy_label(src_e
, src_label
, src_len
, dst_label
, dst_len
)
148 len
= MIN(dst_len
-1, src_len
);
150 s
= sys_datacopy(src_e
, (vir_bytes
) src_label
,
151 SELF
, (vir_bytes
) dst_label
, len
);
152 if (s
!= OK
) return s
;
159 /*===========================================================================*
161 *===========================================================================*/
162 PUBLIC
void build_cmd_dep(struct rproc
*rp
)
164 struct rprocpub
*rpub
;
171 /* Build argument vector to be passed to execute call. The format of the
172 * arguments vector is: path, arguments, NULL.
174 strcpy(rp
->r_args
, rp
->r_cmd
); /* copy raw command */
175 arg_count
= 0; /* initialize arg count */
176 rp
->r_argv
[arg_count
++] = rp
->r_args
; /* start with path */
177 cmd_ptr
= rp
->r_args
; /* do some parsing */
178 while(*cmd_ptr
!= '\0') { /* stop at end of string */
179 if (*cmd_ptr
== ' ') { /* next argument */
180 *cmd_ptr
= '\0'; /* terminate previous */
181 while (*++cmd_ptr
== ' ') ; /* skip spaces */
182 if (*cmd_ptr
== '\0') break; /* no arg following */
183 if (arg_count
>MAX_NR_ARGS
+1) break; /* arg vector full */
184 rp
->r_argv
[arg_count
++] = cmd_ptr
; /* add to arg vector */
186 cmd_ptr
++; /* continue parsing */
188 rp
->r_argv
[arg_count
] = NULL
; /* end with NULL pointer */
189 rp
->r_argc
= arg_count
;
191 /* Build process name. */
192 cmd_ptr
= strrchr(rp
->r_argv
[0], '/');
196 cmd_ptr
= rp
->r_argv
[0];
197 len
= strlen(cmd_ptr
);
198 if (len
> RS_MAX_LABEL_LEN
-1)
199 len
= RS_MAX_LABEL_LEN
-1; /* truncate name */
200 memcpy(rpub
->proc_name
, cmd_ptr
, len
);
201 rpub
->proc_name
[len
]= '\0';
204 /*===========================================================================*
206 *===========================================================================*/
207 PUBLIC pid_t
srv_fork()
211 return(_syscall(PM_PROC_NR
, SRV_FORK
, &m
));
214 /*===========================================================================*
216 *===========================================================================*/
217 PUBLIC
int srv_kill(pid_t pid
, int sig
)
223 return(_syscall(PM_PROC_NR
, SRV_KILL
, &m
));
226 /*===========================================================================*
228 *===========================================================================*/
229 PUBLIC
int srv_update(endpoint_t src_e
, endpoint_t dst_e
)
233 /* Ask VM to swap the slots of the two processes and tell the kernel to
234 * do the same. If VM is the service being updated, only perform the kernel
235 * part of the call. The new instance of VM will do the rest at
236 * initialization time.
238 if(src_e
!= VM_PROC_NR
) {
239 r
= vm_update(src_e
, dst_e
);
242 r
= sys_update(src_e
, dst_e
);
248 /*===========================================================================*
250 *===========================================================================*/
251 PUBLIC
void update_period(message
*m_ptr
)
253 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
254 short has_update_timed_out
;
256 struct rprocpub
*rpub
;
258 rpub
= rupdate
.rp
->r_pub
;
260 /* See if a timeout has occurred. */
261 has_update_timed_out
= (now
- rupdate
.prepare_tm
> rupdate
.prepare_maxtime
);
263 /* If an update timed out, end the update process and notify
264 * the old version that the update has been canceled. From now on, the old
265 * version will continue executing.
267 if(has_update_timed_out
) {
268 printf("RS: update failed: maximum prepare time reached\n");
271 /* Prepare cancel request. */
272 m
.m_type
= RS_LU_PREPARE
;
273 m
.RS_LU_STATE
= SEF_LU_STATE_NULL
;
274 asynsend(rpub
->endpoint
, &m
);
278 /*===========================================================================*
280 *===========================================================================*/
281 PUBLIC
void end_update(int result
)
283 /* End the update process. There are two possibilities:
284 * 1) the update succeeded. In that case, cleanup the old version and mark the
285 * new version as no longer under update.
286 * 2) the update failed. In that case, cleanup the new version and mark the old
287 * version as no longer under update. Eventual late ready to update
288 * messages (if any) will simply be ignored and the service can
289 * continue executing. In addition, reset the check timestamp, so that if the
290 * service has a period, a status request will be forced in the next period.
292 struct rproc
*old_rp
, *new_rp
, *exiting_rp
, *surviving_rp
;
295 new_rp
= old_rp
->r_new_rp
;
298 printf("RS: ending update from %s to %s with result: %d\n",
299 srv_to_string(old_rp
), srv_to_string(new_rp
), result
);
301 /* Decide which version has to die out and which version has to survive. */
302 surviving_rp
= (result
== OK
? new_rp
: old_rp
);
303 exiting_rp
= (result
== OK
? old_rp
: new_rp
);
306 rupdate
.flags
&= ~RS_UPDATING
;
308 old_rp
->r_new_rp
= NULL
;
309 new_rp
->r_old_rp
= NULL
;
310 old_rp
->r_check_tm
= 0;
312 /* Send a late reply if necessary. */
313 late_reply(old_rp
, result
);
315 /* Unpublish and cleanup the version that has to die out and mark the other
316 * version as no longer updating.
318 surviving_rp
->r_flags
&= ~RS_UPDATING
;
319 cleanup_service(exiting_rp
);
322 printf("RS: service %s ended the update\n", srv_to_string(surviving_rp
));
325 /*===========================================================================*
326 * kill_service_debug *
327 *===========================================================================*/
328 PUBLIC
int kill_service_debug(file
, line
, rp
, errstr
, err
)
335 /* Crash a system service and don't let it restart. */
336 if(errstr
&& !shutting_down
) {
337 printf("RS: %s (error %d)\n", errstr
, err
);
339 rp
->r_flags
|= RS_EXITING
; /* expect exit */
340 crash_service_debug(file
, line
, rp
); /* simulate crash */
345 /*===========================================================================*
346 * crash_service_debug *
347 *===========================================================================*/
348 PUBLIC
int crash_service_debug(file
, line
, rp
)
353 /* Simluate a crash in a system service. */
354 struct rprocpub
*rpub
;
359 printf("RS: %s %skilled at %s:%d\n", srv_to_string(rp
),
360 rp
->r_flags
& RS_EXITING
? "lethally " : "", file
, line
);
362 return sys_kill(rpub
->endpoint
, SIGKILL
);
365 /*===========================================================================*
366 * cleanup_service_debug *
367 *===========================================================================*/
368 PUBLIC
void cleanup_service_debug(file
, line
, rp
)
373 /* Ask PM to exit the service and free slot. */
374 struct rprocpub
*rpub
;
379 printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp
),
382 if(rp
->r_pid
== -1) {
383 printf("RS: warning: attempt to kill pid -1!\n");
386 srv_kill(rp
->r_pid
, SIGKILL
);
392 /*===========================================================================*
394 *===========================================================================*/
395 PUBLIC
int create_service(rp
)
398 /* Create the given system service. */
399 int child_proc_nr_e
, child_proc_nr_n
; /* child process slot */
400 pid_t child_pid
; /* child's process id */
401 int s
, use_copy
, has_replica
;
402 extern char **environ
;
403 struct rprocpub
*rpub
;
406 use_copy
= (rpub
->sys_flags
& SF_USE_COPY
);
407 has_replica
= (rp
->r_prev_rp
&& !(rp
->r_prev_rp
->r_flags
& RS_TERMINATED
));
409 /* Do we need an existing replica to create the service? */
410 if(!has_replica
&& (rpub
->sys_flags
& SF_NEED_REPL
)) {
411 printf("RS: unable to create service '%s' without a replica\n",
417 /* Do we need an in-memory copy to create the service? */
418 if(!use_copy
&& (rpub
->sys_flags
& SF_NEED_COPY
)) {
419 printf("RS: unable to create service '%s' without an in-memory copy\n",
425 /* Now fork and branch for parent and child process (and check for error). */
427 printf("RS: forking child with srv_fork()...\n");
428 child_pid
= srv_fork();
429 if(child_pid
== -1) {
430 printf("RS: srv_fork() failed (error %d)\n", errno
);
435 /* Get endpoint of the child. */
436 child_proc_nr_e
= getnprocnr(child_pid
);
438 /* There is now a child process. Update the system process table. */
439 child_proc_nr_n
= _ENDPOINT_P(child_proc_nr_e
);
440 rp
->r_flags
= RS_IN_USE
; /* mark slot in use */
441 rpub
->endpoint
= child_proc_nr_e
; /* set child endpoint */
442 rp
->r_pid
= child_pid
; /* set child pid */
443 rp
->r_check_tm
= 0; /* not checked yet */
444 getuptime(&rp
->r_alive_tm
); /* currently alive */
445 rp
->r_stop_tm
= 0; /* not exiting yet */
446 rp
->r_backoff
= 0; /* not to be restarted */
447 rproc_ptr
[child_proc_nr_n
] = rp
; /* mapping for fast access */
448 rpub
->in_use
= TRUE
; /* public entry is now in use */
450 /* Set resources when asked to. */
451 if (rp
->r_set_resources
) {
452 /* Initialize privilege structure. */
453 init_privs(rp
, &rp
->r_priv
);
456 /* Set and synch the privilege structure for the new service.
457 * In case the following fails, we can't kill the process as no signal
458 * manager has been assigned yet. The solution is to directly call
459 * terminate_service() without sending any signal to the process.
461 if ((s
= sys_privctl(child_proc_nr_e
, SYS_PRIV_SET_SYS
, &rp
->r_priv
)) != OK
462 || (s
= sys_getpriv(&rp
->r_priv
, child_proc_nr_e
)) != OK
) {
463 printf("unable to set privilege structure: %d\n", s
);
468 /* Copy the executable image into the child process. If this call
469 * fails, the child process may or may not be killed already. If it is
470 * not killed, it's blocked because of NO_PRIV. Kill it now either way.
471 * If no copy exists, allocate one and free it right after exec completes.
475 printf("RS: %s uses an in-memory copy\n",
479 if ((s
= read_exec(rp
)) != OK
) {
480 printf("read_exec failed: %d\n", s
);
486 printf("RS: execing child with srv_execve()...\n");
487 s
= srv_execve(child_proc_nr_e
, rp
->r_exec
, rp
->r_exec_len
, rp
->r_argv
,
491 printf("srv_execve failed: %d\n", s
);
499 /* The purpose of non-blocking forks is to avoid involving VFS in the forking
500 * process, because VFS may be blocked on a sendrec() to a MFS that is
501 * waiting for a endpoint update for a dead driver. We have just published
502 * that update, but VFS may still be blocked. As a result, VFS may not yet
503 * have received PM's fork message. Hence, if we call mapdriver()
504 * immediately, VFS may not know about the process and thus refuse to add the
505 * driver entry. The following temporary hack works around this by forcing
506 * blocking communication from PM to VFS. Once VFS has been made non-blocking
507 * towards MFS instances, this hack and the big part of srv_fork() can go.
512 printf("RS: %s created\n", srv_to_string(rp
));
517 /*===========================================================================*
519 *===========================================================================*/
520 PUBLIC
int clone_service(rp
)
523 /* Clone the given system service instance. */
524 struct rproc
*replica_rp
;
525 struct rprocpub
*replica_rpub
;
529 printf("RS: creating a replica for %s\n", srv_to_string(rp
));
532 if((r
= clone_slot(rp
, &replica_rp
)) != OK
) {
536 /* Link the two slots. */
537 rp
->r_next_rp
= replica_rp
;
538 replica_rp
->r_prev_rp
= rp
;
540 /* Create a new replica of the service. */
541 r
= create_service(replica_rp
);
543 rp
->r_next_rp
= NULL
;
547 /* Tell VM about allowed calls, if any. */
548 replica_rpub
= replica_rp
->r_pub
;
549 if(replica_rpub
->vm_call_mask
[0]) {
550 r
= vm_set_priv(replica_rpub
->endpoint
, &replica_rpub
->vm_call_mask
[0]);
552 rp
->r_next_rp
= NULL
;
553 return kill_service(replica_rp
, "vm_set_priv call failed", r
);
560 /*===========================================================================*
562 *===========================================================================*/
563 PUBLIC
int publish_service(rp
)
564 struct rproc
*rp
; /* pointer to service slot */
566 /* Publish a service. */
568 struct rprocpub
*rpub
;
569 struct rs_pci pci_acl
;
573 /* Register label with DS. */
574 r
= ds_publish_label(rpub
->label
, rpub
->endpoint
, DSF_OVERWRITE
);
576 return kill_service(rp
, "ds_publish_label call failed", r
);
579 /* If the service is a driver, map it. */
580 if (rpub
->dev_nr
> 0) {
581 if (mapdriver(rpub
->label
, rpub
->dev_nr
, rpub
->dev_style
,
582 rpub
->dev_flags
) != OK
) {
583 return kill_service(rp
, "couldn't map driver", errno
);
587 /* Tell VM about allowed calls, if any. */
588 if(rpub
->vm_call_mask
[0]) {
589 r
= vm_set_priv(rpub
->endpoint
, &rpub
->vm_call_mask
[0]);
591 return kill_service(rp
, "vm_set_priv call failed", r
);
595 /* If PCI properties are set, inform the PCI driver about the new service. */
596 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
597 pci_acl
= rpub
->pci_acl
;
598 strcpy(pci_acl
.rsp_label
, rpub
->label
);
599 pci_acl
.rsp_endpoint
= rpub
->endpoint
;
601 r
= pci_set_acl(&pci_acl
);
603 return kill_service(rp
, "pci_set_acl call failed", r
);
608 printf("RS: %s published\n", srv_to_string(rp
));
613 /*===========================================================================*
614 * unpublish_service *
615 *===========================================================================*/
616 PUBLIC
int unpublish_service(rp
)
617 struct rproc
*rp
; /* pointer to service slot */
619 /* Unpublish a service. */
620 struct rprocpub
*rpub
;
626 /* Unregister label with DS. */
627 r
= ds_delete_label(rpub
->label
);
628 if (r
!= OK
&& !shutting_down
) {
629 printf("RS: ds_delete_label call failed (error %d)\n", r
);
633 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
635 /* If PCI properties are set, inform the PCI driver. */
636 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
637 r
= pci_del_acl(rpub
->endpoint
);
638 if (r
!= OK
&& !shutting_down
) {
639 printf("RS: pci_del_acl call failed (error %d)\n", r
);
645 printf("RS: %s unpublished\n", srv_to_string(rp
));
650 /*===========================================================================*
652 *===========================================================================*/
653 PUBLIC
int run_service(rp
, init_type
)
657 /* Let a newly created service run. */
659 struct rprocpub
*rpub
;
662 use_copy
= (rpub
->sys_flags
& SF_USE_COPY
);
664 /* Allow the service to run. */
665 if ((s
= sys_privctl(rpub
->endpoint
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
666 return kill_service(rp
, "unable to allow the service to run",s
);
669 /* Initialize service. */
670 if((s
= init_service(rp
, init_type
)) != OK
) {
671 return kill_service(rp
, "unable to initialize service", s
);
675 printf("RS: %s allowed to run\n", srv_to_string(rp
));
680 /*===========================================================================*
682 *===========================================================================*/
683 PUBLIC
int start_service(rp
)
686 /* Start a system service. */
688 struct rprocpub
*rpub
;
692 /* Create and make active. */
693 r
= create_service(rp
);
697 activate_service(rp
, NULL
);
699 /* Publish service properties. */
700 r
= publish_service(rp
);
706 init_type
= SEF_INIT_FRESH
;
707 r
= run_service(rp
, init_type
);
713 printf("RS: %s started with major %d\n", srv_to_string(rp
),
719 /*===========================================================================*
721 *===========================================================================*/
722 PUBLIC
void stop_service(struct rproc
*rp
,int how
)
724 struct rprocpub
*rpub
;
728 /* Try to stop the system service. First send a SIGTERM signal to ask the
729 * system service to terminate. If the service didn't install a signal
730 * handler, it will be killed. If it did and ignores the signal, we'll
731 * find out because we record the time here and send a SIGKILL.
734 printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp
));
736 rp
->r_flags
|= how
; /* what to on exit? */
737 sys_kill(rpub
->endpoint
, SIGTERM
); /* first try friendly */
738 getuptime(&rp
->r_stop_tm
); /* record current time */
741 /*===========================================================================*
743 *===========================================================================*/
744 PUBLIC
int update_service(src_rpp
, dst_rpp
)
745 struct rproc
**src_rpp
;
746 struct rproc
**dst_rpp
;
748 /* Update an existing service. */
750 struct rproc
*src_rp
;
751 struct rproc
*dst_rp
;
752 struct rprocpub
*src_rpub
;
753 struct rprocpub
*dst_rpub
;
759 src_rpub
= src_rp
->r_pub
;
760 dst_rpub
= dst_rp
->r_pub
;
763 printf("RS: %s updating into %s\n",
764 srv_to_string(src_rp
), srv_to_string(dst_rp
));
766 /* Swap the slots of the two processes. */
767 r
= srv_update(src_rpub
->endpoint
, dst_rpub
->endpoint
);
772 /* Swap slots here as well. */
774 endpoint
= src_rpub
->endpoint
;
775 swap_slot(&src_rp
, &dst_rp
);
777 /* Reassign pids and endpoints. */
778 src_rp
->r_pid
= dst_rp
->r_pid
;
779 src_rp
->r_pub
->endpoint
= dst_rp
->r_pub
->endpoint
;
780 rproc_ptr
[_ENDPOINT_P(src_rp
->r_pub
->endpoint
)] = src_rp
;
782 dst_rp
->r_pub
->endpoint
= endpoint
;
783 rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)] = dst_rp
;
785 /* Adjust input pointers. */
789 /* Make the new version active. */
790 activate_service(dst_rp
, src_rp
);
793 printf("RS: %s updated into %s\n",
794 srv_to_string(src_rp
), srv_to_string(dst_rp
));
799 /*===========================================================================*
801 *===========================================================================*/
802 PUBLIC
void activate_service(struct rproc
*rp
, struct rproc
*ex_rp
)
804 /* Activate a service instance and deactivate another one if requested. */
806 if(ex_rp
&& (ex_rp
->r_flags
& RS_ACTIVE
) ) {
807 ex_rp
->r_flags
&= ~RS_ACTIVE
;
809 printf("RS: %s becomes inactive\n", srv_to_string(ex_rp
));
812 if(! (rp
->r_flags
& RS_ACTIVE
) ) {
813 rp
->r_flags
|= RS_ACTIVE
;
815 printf("RS: %s becomes active\n", srv_to_string(rp
));
819 /*===========================================================================*
820 * terminate_service *
821 *===========================================================================*/
822 PUBLIC
void terminate_service(struct rproc
*rp
)
824 /* Handle a termination event for a system service. */
826 struct rprocpub
*rpub
;
833 printf("RS: %s terminated\n", srv_to_string(rp
));
835 /* Deal with failures during initialization. */
836 if(rp
->r_flags
& RS_INITIALIZING
) {
837 printf("RS: service '%s' exited during initialization\n", rpub
->label
);
838 rp
->r_flags
|= RS_EXITING
; /* don't restart. */
839 sys_sysctl_stacktrace(rp
->r_pub
->endpoint
);
841 /* If updating, rollback. */
842 if(rp
->r_flags
& RS_UPDATING
) {
844 struct rproc
*old_rp
, *new_rp
;
845 printf("RS: update failed: state transfer failed. Rolling back...\n");
847 old_rp
= new_rp
->r_old_rp
;
848 new_rp
->r_flags
&= ~RS_INITIALIZING
;
849 update_service(&new_rp
, &old_rp
); /* can't fail */
851 reply(old_rp
->r_pub
->endpoint
, &m
);
852 end_update(ERESTART
);
857 if (rp
->r_flags
& RS_EXITING
) {
858 /* If a core system service is exiting, we are in trouble. */
859 if (rp
->r_pub
->sys_flags
& SF_CORE_SRV
&& !shutting_down
) {
860 panic("core system service died: %s", srv_to_string(rp
));
863 /* See if a late reply has to be sent. */
864 r
= (rp
->r_caller_request
== RS_DOWN
? OK
: EDEADSRCDST
);
867 /* Unpublish the service. */
868 unpublish_service(rp
);
870 /* Cleanup all the instances of the service. */
871 get_service_instances(rp
, &rps
, &nr_rps
);
872 for(i
=0;i
<nr_rps
;i
++) {
873 cleanup_service(rps
[i
]);
876 else if(rp
->r_flags
& RS_REFRESHING
) {
877 /* Restart service. */
881 /* If an update is in progress, end it. The old version
882 * that just exited will continue executing.
884 if(rp
->r_flags
& RS_UPDATING
) {
885 end_update(ERESTART
);
888 /* Determine what to do. If this is the first unexpected
889 * exit, immediately restart this service. Otherwise use
890 * a binary exponential backoff.
892 if (rp
->r_restarts
> 0) {
893 rp
->r_backoff
= 1 << MIN(rp
->r_restarts
,(BACKOFF_BITS
-2));
894 rp
->r_backoff
= MIN(rp
->r_backoff
,MAX_BACKOFF
);
895 if ((rpub
->sys_flags
& SF_USE_COPY
) && rp
->r_backoff
> 1)
900 /* Restart service. */
905 /*===========================================================================*
907 *===========================================================================*/
908 PRIVATE
int run_script(struct rproc
*rp
)
913 char incarnation_str
[20]; /* Enough for a counter? */
914 char *envp
[1] = { NULL
};
915 struct rprocpub
*rpub
;
918 if (rp
->r_flags
& RS_REFRESHING
)
920 else if (rp
->r_flags
& RS_NOPINGREPLY
)
921 reason
= "no-heartbeat";
922 else reason
= "terminated";
923 sprintf(incarnation_str
, "%d", rp
->r_restarts
);
926 printf("RS: %s:\n", srv_to_string(rp
));
927 printf("RS: calling script '%s'\n", rp
->r_script
);
928 printf("RS: reason: '%s'\n", reason
);
929 printf("RS: incarnation: '%s'\n", incarnation_str
);
936 return kill_service(rp
, "unable to fork script", errno
);
938 execle(rp
->r_script
, rp
->r_script
, rpub
->label
, reason
,
939 incarnation_str
, (char*) NULL
, envp
);
940 printf("RS: run_script: execl '%s' failed: %s\n",
941 rp
->r_script
, strerror(errno
));
944 /* Set the privilege structure for the child process. */
945 endpoint
= getnprocnr(pid
);
946 if ((r
= sys_privctl(endpoint
, SYS_PRIV_SET_USER
, NULL
))
948 return kill_service(rp
,"can't set script privileges",r
);
950 /* Allow the script to run. */
951 if ((r
= sys_privctl(endpoint
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
952 return kill_service(rp
,"can't let the script run",r
);
958 /*===========================================================================*
960 *===========================================================================*/
961 PUBLIC
void restart_service(struct rproc
*rp
)
963 /* Restart service via a recovery script or directly. */
964 struct rproc
*replica_rp
;
967 /* See if a late reply has to be sent. */
970 /* Run a recovery script if available. */
971 if (rp
->r_script
[0] != '\0') {
976 /* Restart directly. We need a replica if not already available. */
977 if(rp
->r_next_rp
== NULL
) {
978 /* Create the replica. */
979 r
= clone_service(rp
);
981 kill_service(rp
, "unable to clone service", r
);
985 replica_rp
= rp
->r_next_rp
;
987 /* Update the service into the replica. */
988 r
= update_service(&rp
, &replica_rp
);
990 kill_service(rp
, "unable to update into new replica", r
);
994 /* Let the new replica run. */
995 r
= run_service(replica_rp
, SEF_INIT_RESTART
);
997 kill_service(rp
, "unable to let the replica run", r
);
1001 /* Increase the number of restarts. */
1002 replica_rp
->r_restarts
+= 1;
1005 printf("RS: %s restarted into %s\n",
1006 srv_to_string(rp
), srv_to_string(replica_rp
));
1009 /*===========================================================================*
1010 * inherit_service_defaults *
1011 *===========================================================================*/
1012 PUBLIC
void inherit_service_defaults(def_rp
, rp
)
1013 struct rproc
*def_rp
;
1016 struct rprocpub
*def_rpub
;
1017 struct rprocpub
*rpub
;
1019 def_rpub
= def_rp
->r_pub
;
1022 /* Device settings. These properties cannot change. */
1023 rpub
->dev_flags
= def_rpub
->dev_flags
;
1024 rpub
->dev_nr
= def_rpub
->dev_nr
;
1025 rpub
->dev_style
= def_rpub
->dev_style
;
1026 rpub
->dev_style2
= def_rpub
->dev_style2
;
1029 if(!rpub
->period
&& def_rpub
->period
) {
1030 rpub
->period
= def_rpub
->period
;
1034 /*===========================================================================*
1035 * get_service_instances *
1036 *===========================================================================*/
1037 PUBLIC
void get_service_instances(rp
, rps
, length
)
1039 struct rproc
***rps
;
1042 /* Retrieve all the service instances of a give service. */
1043 static struct rproc
*instances
[5];
1047 instances
[nr_instances
++] = rp
;
1048 if(rp
->r_prev_rp
) instances
[nr_instances
++] = rp
->r_prev_rp
;
1049 if(rp
->r_next_rp
) instances
[nr_instances
++] = rp
->r_next_rp
;
1050 if(rp
->r_old_rp
) instances
[nr_instances
++] = rp
->r_old_rp
;
1051 if(rp
->r_new_rp
) instances
[nr_instances
++] = rp
->r_new_rp
;
1054 *length
= nr_instances
;
1057 /*===========================================================================*
1059 *===========================================================================*/
1060 PUBLIC
void share_exec(rp_dst
, rp_src
)
1061 struct rproc
*rp_dst
, *rp_src
;
1063 struct rprocpub
*rpub_src
;
1064 struct rprocpub
*rpub_dst
;
1066 rpub_src
= rp_src
->r_pub
;
1067 rpub_dst
= rp_dst
->r_pub
;
1070 printf("RS: %s shares exec image with %s\n",
1071 srv_to_string(rp_dst
), srv_to_string(rp_src
));
1073 /* Share exec image from rp_src to rp_dst. */
1074 rp_dst
->r_exec_len
= rp_src
->r_exec_len
;
1075 rp_dst
->r_exec
= rp_src
->r_exec
;
1078 /*===========================================================================*
1080 *===========================================================================*/
1081 PUBLIC
int read_exec(rp
)
1088 e_name
= rp
->r_argv
[0];
1090 printf("RS: service '%s' reads exec image from: %s\n", rp
->r_pub
->label
,
1093 r
= stat(e_name
, &sb
);
1097 fd
= open(e_name
, O_RDONLY
);
1101 rp
->r_exec_len
= sb
.st_size
;
1102 rp
->r_exec
= malloc(rp
->r_exec_len
);
1103 if (rp
->r_exec
== NULL
)
1105 printf("RS: read_exec: unable to allocate %d bytes\n",
1111 r
= read(fd
, rp
->r_exec
, rp
->r_exec_len
);
1114 if (r
== rp
->r_exec_len
)
1117 printf("RS: read_exec: read failed %d, errno %d\n", r
, e
);
1127 /*===========================================================================*
1129 *===========================================================================*/
1130 PUBLIC
void free_exec(rp
)
1133 /* Free an exec image. */
1134 int slot_nr
, has_shared_exec
, is_boot_image_mem
;
1135 struct rproc
*other_rp
;
1137 /* Search for some other slot sharing the same exec image. */
1138 has_shared_exec
= FALSE
;
1139 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1140 other_rp
= &rproc
[slot_nr
]; /* get pointer to slot */
1141 if (other_rp
->r_flags
& RS_IN_USE
&& other_rp
!= rp
1142 && other_rp
->r_exec
== rp
->r_exec
) { /* found! */
1143 has_shared_exec
= TRUE
;
1148 /* If nobody uses our copy of the exec image, we can try to get rid of it. */
1149 if(!has_shared_exec
) {
1150 is_boot_image_mem
= (rp
->r_exec
>= boot_image_buffer
1151 && rp
->r_exec
< boot_image_buffer
+ boot_image_buffer_size
);
1153 /* Free memory only if not part of the boot image buffer. */
1154 if(is_boot_image_mem
) {
1156 printf("RS: %s has exec image in the boot image buffer\n",
1161 printf("RS: %s frees exec image\n", srv_to_string(rp
));
1167 printf("RS: %s no longer sharing exec image with %s\n",
1168 srv_to_string(rp
), srv_to_string(other_rp
));
1174 /*===========================================================================*
1176 *===========================================================================*/
1177 PUBLIC
int init_slot(rp
, rs_start
, source
)
1179 struct rs_start
*rs_start
;
1182 /* Initialize a slot as requested by the client. */
1183 struct rprocpub
*rpub
;
1184 char *label
; /* unique name of command */
1185 int len
; /* length of string */
1188 int basic_kc
[] = { SYS_BASIC_CALLS
, SYS_NULL_C
};
1189 int basic_vmc
[] = { VM_BASIC_CALLS
, SYS_NULL_C
};
1193 /* Obtain command name and parameters. This is a space-separated string
1194 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
1196 if (rs_start
->rss_cmdlen
> MAX_COMMAND_LEN
-1) return(E2BIG
);
1197 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_cmd
,
1198 SELF
, (vir_bytes
) rp
->r_cmd
, rs_start
->rss_cmdlen
);
1199 if (s
!= OK
) return(s
);
1200 rp
->r_cmd
[rs_start
->rss_cmdlen
] = '\0'; /* ensure it is terminated */
1201 if (rp
->r_cmd
[0] != '/') return(EINVAL
); /* insist on absolute path */
1203 /* Build cmd dependencies: argv and program name. */
1206 if(rs_start
->rss_label
.l_len
> 0) {
1207 /* RS_UP caller has supplied a custom label for this service. */
1208 int s
= copy_label(source
, rs_start
->rss_label
.l_addr
,
1209 rs_start
->rss_label
.l_len
, rpub
->label
, sizeof(rpub
->label
));
1213 printf("RS: init_slot: using label (custom) '%s'\n", rpub
->label
);
1215 /* Default label for the service. */
1216 label
= rpub
->proc_name
;
1218 memcpy(rpub
->label
, label
, len
);
1219 rpub
->label
[len
]= '\0';
1221 printf("RS: init_slot: using label (from proc_name) '%s'\n",
1225 if(rs_start
->rss_nr_control
> 0) {
1227 if (rs_start
->rss_nr_control
> RS_NR_CONTROL
)
1229 printf("RS: init_slot: too many control labels\n");
1232 for (i
=0; i
<rs_start
->rss_nr_control
; i
++) {
1233 s
= copy_label(source
, rs_start
->rss_control
[i
].l_addr
,
1234 rs_start
->rss_control
[i
].l_len
, rp
->r_control
[i
],
1235 sizeof(rp
->r_control
[i
]));
1239 rp
->r_nr_control
= rs_start
->rss_nr_control
;
1242 printf("RS: init_slot: control labels:");
1243 for (i
=0; i
<rp
->r_nr_control
; i
++)
1244 printf(" %s", rp
->r_control
[i
]);
1249 rp
->r_script
[0]= '\0';
1250 if (rs_start
->rss_scriptlen
> MAX_SCRIPT_LEN
-1) return(E2BIG
);
1251 if (rs_start
->rss_script
!= NULL
)
1253 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_script
,
1254 SELF
, (vir_bytes
) rp
->r_script
, rs_start
->rss_scriptlen
);
1255 if (s
!= OK
) return(s
);
1256 rp
->r_script
[rs_start
->rss_scriptlen
] = '\0';
1258 rp
->r_uid
= rs_start
->rss_uid
;
1259 rp
->r_nice
= rs_start
->rss_nice
;
1261 if (rs_start
->rss_flags
& RSS_IPC_VALID
)
1263 if (rs_start
->rss_ipclen
+1 > sizeof(rp
->r_ipc_list
))
1265 printf("RS: ipc list too long for '%s'\n", rpub
->label
);
1268 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_ipc
,
1269 SELF
, (vir_bytes
) rp
->r_ipc_list
, rs_start
->rss_ipclen
);
1270 if (s
!= OK
) return(s
);
1271 rp
->r_ipc_list
[rs_start
->rss_ipclen
]= '\0';
1274 rp
->r_ipc_list
[0]= '\0';
1276 /* Set system flags. */
1277 rpub
->sys_flags
= DSRV_SF
;
1279 if (rs_start
->rss_flags
& RSS_COPY
) {
1282 struct rprocpub
*rpub2
;
1285 if(rs_start
->rss_flags
& RSS_REUSE
) {
1288 for(i
= 0; i
< NR_SYS_PROCS
; i
++) {
1290 rpub2
= rproc
[i
].r_pub
;
1291 if(strcmp(rpub
->proc_name
, rpub2
->proc_name
) == 0 &&
1292 (rpub2
->sys_flags
& SF_USE_COPY
)) {
1293 /* We have found the same binary that's
1294 * already been copied */
1305 share_exec(rp
, rp2
);
1310 rpub
->sys_flags
|= SF_USE_COPY
;
1312 if (rs_start
->rss_flags
& RSS_REPLICA
) {
1313 rpub
->sys_flags
|= SF_USE_REPL
;
1316 /* All dynamically created services get the same privilege flags, and
1317 * allowed traps, and signal manager. Other privilege settings can be
1318 * specified at runtime. The privilege id is dynamically allocated by
1321 rp
->r_priv
.s_flags
= DSRV_F
; /* privilege flags */
1322 rp
->r_priv
.s_trap_mask
= DSRV_T
; /* allowed traps */
1323 rp
->r_priv
.s_sig_mgr
= DSRV_SM
; /* signal manager */
1325 /* Copy granted resources */
1326 if (rs_start
->rss_nr_irq
> NR_IRQ
)
1328 printf("RS: init_slot: too many IRQs requested\n");
1331 rp
->r_priv
.s_nr_irq
= rs_start
->rss_nr_irq
;
1332 for (i
= 0; i
<rp
->r_priv
.s_nr_irq
; i
++)
1334 rp
->r_priv
.s_irq_tab
[i
]= rs_start
->rss_irq
[i
];
1336 printf("RS: init_slot: IRQ %d\n", rp
->r_priv
.s_irq_tab
[i
]);
1339 if (rs_start
->rss_nr_io
> NR_IO_RANGE
)
1341 printf("RS: init_slot: too many I/O ranges requested\n");
1344 rp
->r_priv
.s_nr_io_range
= rs_start
->rss_nr_io
;
1345 for (i
= 0; i
<rp
->r_priv
.s_nr_io_range
; i
++)
1347 rp
->r_priv
.s_io_tab
[i
].ior_base
= rs_start
->rss_io
[i
].base
;
1348 rp
->r_priv
.s_io_tab
[i
].ior_limit
=
1349 rs_start
->rss_io
[i
].base
+rs_start
->rss_io
[i
].len
-1;
1351 printf("RS: init_slot: I/O [%x..%x]\n",
1352 rp
->r_priv
.s_io_tab
[i
].ior_base
,
1353 rp
->r_priv
.s_io_tab
[i
].ior_limit
);
1356 if (rs_start
->rss_nr_pci_id
> RS_NR_PCI_DEVICE
)
1358 printf("RS: init_slot: too many PCI device IDs\n");
1361 rpub
->pci_acl
.rsp_nr_device
= rs_start
->rss_nr_pci_id
;
1362 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_device
; i
++)
1364 rpub
->pci_acl
.rsp_device
[i
].vid
= rs_start
->rss_pci_id
[i
].vid
;
1365 rpub
->pci_acl
.rsp_device
[i
].did
= rs_start
->rss_pci_id
[i
].did
;
1367 printf("RS: init_slot: PCI %04x/%04x\n",
1368 rpub
->pci_acl
.rsp_device
[i
].vid
,
1369 rpub
->pci_acl
.rsp_device
[i
].did
);
1371 if (rs_start
->rss_nr_pci_class
> RS_NR_PCI_CLASS
)
1373 printf("RS: init_slot: too many PCI class IDs\n");
1376 rpub
->pci_acl
.rsp_nr_class
= rs_start
->rss_nr_pci_class
;
1377 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_class
; i
++)
1379 rpub
->pci_acl
.rsp_class
[i
].class= rs_start
->rss_pci_class
[i
].class;
1380 rpub
->pci_acl
.rsp_class
[i
].mask
= rs_start
->rss_pci_class
[i
].mask
;
1382 printf("RS: init_slot: PCI class %06x mask %06x\n",
1383 (unsigned int) rpub
->pci_acl
.rsp_class
[i
].class,
1384 (unsigned int) rpub
->pci_acl
.rsp_class
[i
].mask
);
1387 /* Copy kernel call mask. Inherit basic kernel calls. */
1388 memcpy(rp
->r_priv
.s_k_call_mask
, rs_start
->rss_system
,
1389 sizeof(rp
->r_priv
.s_k_call_mask
));
1390 fill_call_mask(basic_kc
, NR_SYS_CALLS
,
1391 rp
->r_priv
.s_k_call_mask
, KERNEL_CALL
, FALSE
);
1393 /* Device driver properties. */
1394 rpub
->dev_flags
= DSRV_DF
;
1395 rpub
->dev_nr
= rs_start
->rss_major
;
1396 rpub
->dev_style
= rs_start
->rss_dev_style
;
1397 if(rpub
->dev_nr
&& !IS_DEV_STYLE(rs_start
->rss_dev_style
)) {
1398 printf("RS: init_slot: bad device style\n");
1401 rpub
->dev_style2
= STYLE_NDEV
;
1403 /* Initialize some fields. */
1404 rpub
->period
= rs_start
->rss_period
;
1405 rp
->r_restarts
= 0; /* no restarts yet */
1406 rp
->r_set_resources
= 1; /* set resources */
1407 rp
->r_old_rp
= NULL
; /* no old version yet */
1408 rp
->r_new_rp
= NULL
; /* no new version yet */
1409 rp
->r_prev_rp
= NULL
; /* no prev replica yet */
1410 rp
->r_next_rp
= NULL
; /* no next replica yet */
1412 /* Copy VM call mask. Inherit basic VM calls. */
1413 memcpy(rpub
->vm_call_mask
, rs_start
->rss_vm
,
1414 sizeof(rpub
->vm_call_mask
));
1415 fill_call_mask(basic_vmc
, NR_VM_CALLS
,
1416 rpub
->vm_call_mask
, VM_RQ_BASE
, FALSE
);
1421 /*===========================================================================*
1423 *===========================================================================*/
1424 PUBLIC
int clone_slot(rp
, clone_rpp
)
1426 struct rproc
**clone_rpp
;
1429 struct rproc
*clone_rp
;
1430 struct rprocpub
*rpub
, *clone_rpub
;
1432 /* Allocate a system service slot for the clone. */
1433 r
= alloc_slot(&clone_rp
);
1435 printf("RS: clone_slot: unable to allocate a new slot: %d\n", r
);
1440 clone_rpub
= clone_rp
->r_pub
;
1444 *clone_rpub
= *rpub
;
1447 clone_rp
->r_flags
&= ~RS_ACTIVE
; /* the clone is not active yet */
1448 clone_rp
->r_pid
= -1; /* no pid yet */
1449 clone_rpub
->endpoint
= -1; /* no endpoint yet */
1450 clone_rp
->r_pub
= clone_rpub
; /* restore pointer to public entry */
1451 build_cmd_dep(clone_rp
); /* rebuild cmd dependencies */
1452 if(clone_rpub
->sys_flags
& SF_USE_COPY
) {
1453 share_exec(clone_rp
, rp
); /* share exec image */
1456 /* Force dynamic privilege id. */
1457 clone_rp
->r_priv
.s_flags
|= DYN_PRIV_ID
;
1459 *clone_rpp
= clone_rp
;
1463 /*===========================================================================*
1464 * swap_slot_pointer *
1465 *===========================================================================*/
1466 PRIVATE
void swap_slot_pointer(struct rproc
**rpp
, struct rproc
*src_rp
,
1467 struct rproc
*dst_rp
)
1469 if(*rpp
== src_rp
) {
1472 else if(*rpp
== dst_rp
) {
1477 /*===========================================================================*
1479 *===========================================================================*/
1480 PUBLIC
void swap_slot(src_rpp
, dst_rpp
)
1481 struct rproc
**src_rpp
;
1482 struct rproc
**dst_rpp
;
1484 /* Swap two service slots. */
1485 struct rproc
*src_rp
;
1486 struct rproc
*dst_rp
;
1487 struct rprocpub
*src_rpub
;
1488 struct rprocpub
*dst_rpub
;
1489 struct rproc orig_src_rproc
, orig_dst_rproc
;
1490 struct rprocpub orig_src_rprocpub
, orig_dst_rprocpub
;
1494 src_rpub
= src_rp
->r_pub
;
1495 dst_rpub
= dst_rp
->r_pub
;
1497 /* Save existing data first. */
1498 orig_src_rproc
= *src_rp
;
1499 orig_src_rprocpub
= *src_rpub
;
1500 orig_dst_rproc
= *dst_rp
;
1501 orig_dst_rprocpub
= *dst_rpub
;
1504 *src_rp
= orig_dst_rproc
;
1505 *src_rpub
= orig_dst_rprocpub
;
1506 *dst_rp
= orig_src_rproc
;
1507 *dst_rpub
= orig_src_rprocpub
;
1509 /* Restore public entries. */
1510 src_rp
->r_pub
= orig_src_rproc
.r_pub
;
1511 dst_rp
->r_pub
= orig_dst_rproc
.r_pub
;
1513 /* Rebuild command dependencies. */
1514 build_cmd_dep(src_rp
);
1515 build_cmd_dep(dst_rp
);
1517 /* Swap local slot pointers. */
1518 swap_slot_pointer(&src_rp
->r_prev_rp
, src_rp
, dst_rp
);
1519 swap_slot_pointer(&src_rp
->r_next_rp
, src_rp
, dst_rp
);
1520 swap_slot_pointer(&src_rp
->r_old_rp
, src_rp
, dst_rp
);
1521 swap_slot_pointer(&src_rp
->r_new_rp
, src_rp
, dst_rp
);
1522 swap_slot_pointer(&dst_rp
->r_prev_rp
, src_rp
, dst_rp
);
1523 swap_slot_pointer(&dst_rp
->r_next_rp
, src_rp
, dst_rp
);
1524 swap_slot_pointer(&dst_rp
->r_old_rp
, src_rp
, dst_rp
);
1525 swap_slot_pointer(&dst_rp
->r_new_rp
, src_rp
, dst_rp
);
1527 /* Swap global slot pointers. */
1528 swap_slot_pointer(&rupdate
.rp
, src_rp
, dst_rp
);
1529 swap_slot_pointer(&rproc_ptr
[_ENDPOINT_P(src_rp
->r_pub
->endpoint
)],
1531 swap_slot_pointer(&rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)],
1534 /* Adjust input pointers. */
1539 /*===========================================================================*
1540 * lookup_slot_by_label *
1541 *===========================================================================*/
1542 PUBLIC
struct rproc
* lookup_slot_by_label(char *label
)
1544 /* Lookup a service slot matching the given label. */
1547 struct rprocpub
*rpub
;
1549 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1550 rp
= &rproc
[slot_nr
];
1551 if (!(rp
->r_flags
& RS_ACTIVE
)) {
1555 if (strcmp(rpub
->label
, label
) == 0) {
1563 /*===========================================================================*
1564 * lookup_slot_by_pid *
1565 *===========================================================================*/
1566 PUBLIC
struct rproc
* lookup_slot_by_pid(pid_t pid
)
1568 /* Lookup a service slot matching the given pid. */
1576 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1577 rp
= &rproc
[slot_nr
];
1578 if (!(rp
->r_flags
& RS_IN_USE
)) {
1581 if (rp
->r_pid
== pid
) {
1589 /*===========================================================================*
1590 * lookup_slot_by_dev_nr *
1591 *===========================================================================*/
1592 PUBLIC
struct rproc
* lookup_slot_by_dev_nr(dev_t dev_nr
)
1594 /* Lookup a service slot matching the given device number. */
1597 struct rprocpub
*rpub
;
1603 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1604 rp
= &rproc
[slot_nr
];
1606 if (!(rp
->r_flags
& RS_IN_USE
)) {
1609 if (rpub
->dev_nr
== dev_nr
) {
1617 /*===========================================================================*
1619 *===========================================================================*/
1620 PUBLIC
int alloc_slot(rpp
)
1623 /* Alloc a new system service slot. */
1626 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1627 *rpp
= &rproc
[slot_nr
]; /* get pointer to slot */
1628 if (!((*rpp
)->r_flags
& RS_IN_USE
)) /* check if available */
1631 if (slot_nr
>= NR_SYS_PROCS
) {
1638 /*===========================================================================*
1640 *===========================================================================*/
1641 PUBLIC
void free_slot(rp
)
1644 /* Free a system service slot. */
1645 struct rprocpub
*rpub
;
1649 /* Send a late reply if there is any pending. */
1652 /* Free memory if necessary. */
1653 if(rpub
->sys_flags
& SF_USE_COPY
) {
1657 /* Mark slot as no longer in use.. */
1660 rpub
->in_use
= FALSE
;
1661 rproc_ptr
[_ENDPOINT_P(rpub
->endpoint
)] = NULL
;
1665 /*===========================================================================*
1667 *===========================================================================*/
1668 PUBLIC
char *get_next_label(ptr
, label
, caller_label
)
1673 /* Get the next label from the list of (IPC) labels.
1678 for (p
= ptr
; p
[0] != '\0'; p
= q
)
1680 /* Skip leading space */
1681 while (p
[0] != '\0' && isspace((unsigned char)p
[0]))
1684 /* Find start of next word */
1686 while (q
[0] != '\0' && !isspace((unsigned char)q
[0]))
1691 if (len
> RS_MAX_LABEL_LEN
)
1694 "rs:get_next_label: bad ipc list entry '%.*s' for %s: too long\n",
1695 len
, p
, caller_label
);
1698 memcpy(label
, p
, len
);
1701 return q
; /* found another */
1704 return NULL
; /* done */
1707 /*===========================================================================*
1709 *===========================================================================*/
1710 PUBLIC
void add_forward_ipc(rp
, privp
)
1714 /* Add IPC send permissions to a process based on that process's IPC
1717 char label
[RS_MAX_LABEL_LEN
+1], *p
;
1718 struct rproc
*tmp_rp
;
1719 struct rprocpub
*tmp_rpub
;
1720 endpoint_t endpoint
;
1724 struct rprocpub
*rpub
;
1729 while ((p
= get_next_label(p
, label
, rpub
->label
)) != NULL
) {
1731 if (strcmp(label
, "SYSTEM") == 0)
1733 else if (strcmp(label
, "USER") == 0)
1734 endpoint
= INIT_PROC_NR
; /* all user procs */
1735 else if (strcmp(label
, "PM") == 0)
1736 endpoint
= PM_PROC_NR
;
1737 else if (strcmp(label
, "VFS") == 0)
1738 endpoint
= FS_PROC_NR
;
1739 else if (strcmp(label
, "RS") == 0)
1740 endpoint
= RS_PROC_NR
;
1741 else if (strcmp(label
, "LOG") == 0)
1742 endpoint
= LOG_PROC_NR
;
1743 else if (strcmp(label
, "TTY") == 0)
1744 endpoint
= TTY_PROC_NR
;
1745 else if (strcmp(label
, "DS") == 0)
1746 endpoint
= DS_PROC_NR
;
1747 else if (strcmp(label
, "VM") == 0)
1748 endpoint
= VM_PROC_NR
;
1751 /* Try to find process */
1752 tmp_rp
= lookup_slot_by_label(label
);
1755 tmp_rpub
= tmp_rp
->r_pub
;
1756 endpoint
= tmp_rpub
->endpoint
;
1759 if ((r
= sys_getpriv(&priv
, endpoint
)) < 0)
1762 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1767 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1772 /*===========================================================================*
1773 * add_backward_ipc *
1774 *===========================================================================*/
1775 PUBLIC
void add_backward_ipc(rp
, privp
)
1779 /* Add IPC send permissions to a process based on other processes' IPC
1780 * lists. This is enough to allow each such two processes to talk to
1781 * each other, as the kernel guarantees send mask symmetry. We need to
1782 * add these permissions now because the current process may not yet
1783 * have existed at the time that the other process was initialized.
1785 char label
[RS_MAX_LABEL_LEN
+1], *p
;
1787 struct rprocpub
*rrpub
;
1790 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
1791 if (!(rrp
->r_flags
& RS_IN_USE
))
1794 /* If an IPC target list was provided for the process being
1795 * checked here, make sure that the label of the new process
1796 * is in that process's list.
1798 if (rrp
->r_ipc_list
[0]) {
1802 p
= rrp
->r_ipc_list
;
1804 while ((p
= get_next_label(p
, label
,
1805 rrpub
->label
)) != NULL
) {
1806 if (!strcmp(rrpub
->label
, label
)) {
1816 priv_id
= rrp
->r_priv
.s_id
;
1818 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1823 /*===========================================================================*
1825 *===========================================================================*/
1826 PUBLIC
void init_privs(rp
, privp
)
1832 /* Clear s_ipc_to */
1833 memset(&privp
->s_ipc_to
, '\0', sizeof(privp
->s_ipc_to
));
1835 if (strlen(rp
->r_ipc_list
) != 0)
1837 add_forward_ipc(rp
, privp
);
1838 add_backward_ipc(rp
, privp
);
1843 for (i
= 0; i
<NR_SYS_PROCS
; i
++)
1845 if (i
!= USER_PRIV_ID
)
1846 set_sys_bit(privp
->s_ipc_to
, i
);