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
);
464 rp
->r_flags
|= RS_EXITING
;
465 terminate_service(rp
);
469 /* Copy the executable image into the child process. If this call
470 * fails, the child process may or may not be killed already. If it is
471 * not killed, it's blocked because of NO_PRIV. Kill it now either way.
472 * If no copy exists, allocate one and free it right after exec completes.
476 printf("RS: %s uses an in-memory copy\n",
480 if ((s
= read_exec(rp
)) != OK
) {
481 return kill_service(rp
, "read_exec failed", s
);
485 printf("RS: execing child with srv_execve()...\n");
486 s
= srv_execve(child_proc_nr_e
, rp
->r_exec
, rp
->r_exec_len
, rp
->r_argv
,
490 return kill_service(rp
, "srv_execve failed", s
);
496 /* The purpose of non-blocking forks is to avoid involving VFS in the forking
497 * process, because VFS may be blocked on a sendrec() to a MFS that is
498 * waiting for a endpoint update for a dead driver. We have just published
499 * that update, but VFS may still be blocked. As a result, VFS may not yet
500 * have received PM's fork message. Hence, if we call mapdriver()
501 * immediately, VFS may not know about the process and thus refuse to add the
502 * driver entry. The following temporary hack works around this by forcing
503 * blocking communication from PM to VFS. Once VFS has been made non-blocking
504 * towards MFS instances, this hack and the big part of srv_fork() can go.
509 printf("RS: %s created\n", srv_to_string(rp
));
514 /*===========================================================================*
516 *===========================================================================*/
517 PUBLIC
int clone_service(rp
)
520 /* Clone the given system service instance. */
521 struct rproc
*replica_rp
;
525 printf("RS: creating a replica for %s\n", srv_to_string(rp
));
528 if((r
= clone_slot(rp
, &replica_rp
)) != OK
) {
532 /* Link the two slots. */
533 rp
->r_next_rp
= replica_rp
;
534 replica_rp
->r_prev_rp
= rp
;
536 /* Create a new replica of the service. */
537 r
= create_service(replica_rp
);
539 rp
->r_next_rp
= NULL
;
546 /*===========================================================================*
548 *===========================================================================*/
549 PUBLIC
int publish_service(rp
)
550 struct rproc
*rp
; /* pointer to service slot */
552 /* Publish a service. */
554 struct rprocpub
*rpub
;
555 struct rs_pci pci_acl
;
559 /* Register label with DS. */
560 r
= ds_publish_label(rpub
->label
, rpub
->endpoint
, DSF_OVERWRITE
);
562 return kill_service(rp
, "ds_publish_label call failed", r
);
565 /* If the service is a driver, map it. */
566 if (rpub
->dev_nr
> 0) {
567 if (mapdriver(rpub
->label
, rpub
->dev_nr
, rpub
->dev_style
,
568 rpub
->dev_flags
) != OK
) {
569 return kill_service(rp
, "couldn't map driver", errno
);
573 /* Tell VM about allowed calls, if any. */
574 if(rpub
->vm_call_mask
[0]) {
575 r
= vm_set_priv(rpub
->endpoint
, &rpub
->vm_call_mask
[0]);
577 return kill_service(rp
, "vm_set_priv call failed", r
);
581 /* If PCI properties are set, inform the PCI driver about the new service. */
582 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
583 pci_acl
= rpub
->pci_acl
;
584 strcpy(pci_acl
.rsp_label
, rpub
->label
);
585 pci_acl
.rsp_endpoint
= rpub
->endpoint
;
587 r
= pci_set_acl(&pci_acl
);
589 return kill_service(rp
, "pci_set_acl call failed", r
);
594 printf("RS: %s published\n", srv_to_string(rp
));
599 /*===========================================================================*
600 * unpublish_service *
601 *===========================================================================*/
602 PUBLIC
int unpublish_service(rp
)
603 struct rproc
*rp
; /* pointer to service slot */
605 /* Unpublish a service. */
606 struct rprocpub
*rpub
;
612 /* Unregister label with DS. */
613 r
= ds_delete_label(rpub
->label
);
614 if (r
!= OK
&& !shutting_down
) {
615 printf("RS: ds_delete_label call failed (error %d)\n", r
);
619 /* No need to inform VFS and VM, cleanup is done on exit automatically. */
621 /* If PCI properties are set, inform the PCI driver. */
622 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
623 r
= pci_del_acl(rpub
->endpoint
);
624 if (r
!= OK
&& !shutting_down
) {
625 printf("RS: pci_del_acl call failed (error %d)\n", r
);
631 printf("RS: %s unpublished\n", srv_to_string(rp
));
636 /*===========================================================================*
638 *===========================================================================*/
639 PUBLIC
int run_service(rp
, init_type
)
643 /* Let a newly created service run. */
645 struct rprocpub
*rpub
;
648 use_copy
= (rpub
->sys_flags
& SF_USE_COPY
);
650 /* Allow the service to run. */
651 if ((s
= sys_privctl(rpub
->endpoint
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
652 return kill_service(rp
, "unable to allow the service to run",s
);
655 /* Initialize service. */
656 if((s
= init_service(rp
, init_type
)) != OK
) {
657 return kill_service(rp
, "unable to initialize service", s
);
661 printf("RS: %s allowed to run\n", srv_to_string(rp
));
666 /*===========================================================================*
668 *===========================================================================*/
669 PUBLIC
int start_service(rp
)
672 /* Start a system service. */
674 struct rprocpub
*rpub
;
678 /* Create and make active. */
679 r
= create_service(rp
);
680 activate_service(rp
, NULL
);
685 /* Publish service properties. */
686 r
= publish_service(rp
);
692 init_type
= SEF_INIT_FRESH
;
693 r
= run_service(rp
, init_type
);
699 printf("RS: %s started with major %d\n", srv_to_string(rp
),
705 /*===========================================================================*
707 *===========================================================================*/
708 PUBLIC
void stop_service(struct rproc
*rp
,int how
)
710 struct rprocpub
*rpub
;
714 /* Try to stop the system service. First send a SIGTERM signal to ask the
715 * system service to terminate. If the service didn't install a signal
716 * handler, it will be killed. If it did and ignores the signal, we'll
717 * find out because we record the time here and send a SIGKILL.
720 printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp
));
722 rp
->r_flags
|= how
; /* what to on exit? */
723 sys_kill(rpub
->endpoint
, SIGTERM
); /* first try friendly */
724 getuptime(&rp
->r_stop_tm
); /* record current time */
727 /*===========================================================================*
729 *===========================================================================*/
730 PUBLIC
int update_service(src_rpp
, dst_rpp
)
731 struct rproc
**src_rpp
;
732 struct rproc
**dst_rpp
;
734 /* Update an existing service. */
736 struct rproc
*src_rp
;
737 struct rproc
*dst_rp
;
738 struct rprocpub
*src_rpub
;
739 struct rprocpub
*dst_rpub
;
745 src_rpub
= src_rp
->r_pub
;
746 dst_rpub
= dst_rp
->r_pub
;
749 printf("RS: %s updating into %s\n",
750 srv_to_string(src_rp
), srv_to_string(dst_rp
));
752 /* Swap the slots of the two processes. */
753 r
= srv_update(src_rpub
->endpoint
, dst_rpub
->endpoint
);
758 /* Swap slots here as well. */
760 endpoint
= src_rpub
->endpoint
;
761 swap_slot(&src_rp
, &dst_rp
);
763 /* Reassign pids and endpoints. */
764 src_rp
->r_pid
= dst_rp
->r_pid
;
765 src_rp
->r_pub
->endpoint
= dst_rp
->r_pub
->endpoint
;
766 rproc_ptr
[_ENDPOINT_P(src_rp
->r_pub
->endpoint
)] = src_rp
;
768 dst_rp
->r_pub
->endpoint
= endpoint
;
769 rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)] = dst_rp
;
771 /* Adjust input pointers. */
775 /* Make the new version active. */
776 activate_service(dst_rp
, src_rp
);
779 printf("RS: %s updated into %s\n",
780 srv_to_string(src_rp
), srv_to_string(dst_rp
));
785 /*===========================================================================*
787 *===========================================================================*/
788 PUBLIC
void activate_service(struct rproc
*rp
, struct rproc
*ex_rp
)
790 /* Activate a service instance and deactivate another one if requested. */
792 if(ex_rp
&& (ex_rp
->r_flags
& RS_ACTIVE
) ) {
793 ex_rp
->r_flags
&= ~RS_ACTIVE
;
795 printf("RS: %s becomes inactive\n", srv_to_string(ex_rp
));
798 if(! (rp
->r_flags
& RS_ACTIVE
) ) {
799 rp
->r_flags
|= RS_ACTIVE
;
801 printf("RS: %s becomes active\n", srv_to_string(rp
));
805 /*===========================================================================*
806 * terminate_service *
807 *===========================================================================*/
808 PUBLIC
void terminate_service(struct rproc
*rp
)
810 /* Handle a termination event for a system service. */
812 struct rprocpub
*rpub
;
819 printf("RS: %s terminated\n", srv_to_string(rp
));
821 /* Deal with failures during initialization. */
822 if(rp
->r_flags
& RS_INITIALIZING
) {
823 printf("RS: service '%s' exited during initialization\n", rpub
->label
);
824 rp
->r_flags
|= RS_EXITING
; /* don't restart. */
825 sys_sysctl_stacktrace(rp
->r_pub
->endpoint
);
827 /* If updating, rollback. */
828 if(rp
->r_flags
& RS_UPDATING
) {
830 struct rproc
*old_rp
, *new_rp
;
831 printf("RS: update failed: state transfer failed. Rolling back...\n");
833 old_rp
= new_rp
->r_old_rp
;
834 new_rp
->r_flags
&= ~RS_INITIALIZING
;
835 update_service(&new_rp
, &old_rp
); /* can't fail */
837 reply(old_rp
->r_pub
->endpoint
, &m
);
838 end_update(ERESTART
);
843 if (rp
->r_flags
& RS_EXITING
) {
844 /* If a core system service is exiting, we are in trouble. */
845 if (rp
->r_pub
->sys_flags
& SF_CORE_SRV
&& !shutting_down
) {
846 panic("core system service died: %s", srv_to_string(rp
));
849 /* See if a late reply has to be sent. */
850 r
= (rp
->r_caller_request
== RS_DOWN
? OK
: EDEADSRCDST
);
853 /* Unpublish the service. */
854 unpublish_service(rp
);
856 /* Cleanup all the instances of the service. */
857 get_service_instances(rp
, &rps
, &nr_rps
);
858 for(i
=0;i
<nr_rps
;i
++) {
859 cleanup_service(rps
[i
]);
862 else if(rp
->r_flags
& RS_REFRESHING
) {
863 /* Restart service. */
867 /* If an update is in progress, end it. The old version
868 * that just exited will continue executing.
870 if(rp
->r_flags
& RS_UPDATING
) {
871 end_update(ERESTART
);
874 /* Determine what to do. If this is the first unexpected
875 * exit, immediately restart this service. Otherwise use
876 * a binary exponential backoff.
878 if (rp
->r_restarts
> 0) {
879 rp
->r_backoff
= 1 << MIN(rp
->r_restarts
,(BACKOFF_BITS
-2));
880 rp
->r_backoff
= MIN(rp
->r_backoff
,MAX_BACKOFF
);
881 if ((rpub
->sys_flags
& SF_USE_COPY
) && rp
->r_backoff
> 1)
886 /* Restart service. */
891 /*===========================================================================*
893 *===========================================================================*/
894 PRIVATE
int run_script(struct rproc
*rp
)
899 char incarnation_str
[20]; /* Enough for a counter? */
900 char *envp
[1] = { NULL
};
901 struct rprocpub
*rpub
;
904 if (rp
->r_flags
& RS_REFRESHING
)
906 else if (rp
->r_flags
& RS_NOPINGREPLY
)
907 reason
= "no-heartbeat";
908 else reason
= "terminated";
909 sprintf(incarnation_str
, "%d", rp
->r_restarts
);
912 printf("RS: %s:\n", srv_to_string(rp
));
913 printf("RS: calling script '%s'\n", rp
->r_script
);
914 printf("RS: reason: '%s'\n", reason
);
915 printf("RS: incarnation: '%s'\n", incarnation_str
);
922 return kill_service(rp
, "unable to fork script", errno
);
924 execle(rp
->r_script
, rp
->r_script
, rpub
->label
, reason
,
925 incarnation_str
, (char*) NULL
, envp
);
926 printf("RS: run_script: execl '%s' failed: %s\n",
927 rp
->r_script
, strerror(errno
));
930 /* Set the privilege structure for the child process. */
931 endpoint
= getnprocnr(pid
);
932 if ((r
= sys_privctl(endpoint
, SYS_PRIV_SET_USER
, NULL
))
934 return kill_service(rp
,"can't set script privileges",r
);
936 /* Allow the script to run. */
937 if ((r
= sys_privctl(endpoint
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
938 return kill_service(rp
,"can't let the script run",r
);
944 /*===========================================================================*
946 *===========================================================================*/
947 PUBLIC
void restart_service(struct rproc
*rp
)
949 /* Restart service via a recovery script or directly. */
950 struct rproc
*replica_rp
;
953 /* See if a late reply has to be sent. */
956 /* Run a recovery script if available. */
957 if (rp
->r_script
[0] != '\0') {
962 /* Restart directly. We need a replica if not already available. */
963 if(rp
->r_next_rp
== NULL
) {
964 /* Create the replica. */
965 r
= clone_service(rp
);
967 kill_service(rp
, "unable to clone service", r
);
971 replica_rp
= rp
->r_next_rp
;
973 /* Update the service into the replica. */
974 r
= update_service(&rp
, &replica_rp
);
976 kill_service(rp
, "unable to update into new replica", r
);
980 /* Let the new replica run. */
981 r
= run_service(replica_rp
, SEF_INIT_RESTART
);
983 kill_service(rp
, "unable to let the replica run", r
);
987 /* Increase the number of restarts. */
988 replica_rp
->r_restarts
+= 1;
991 printf("RS: %s restarted into %s\n",
992 srv_to_string(rp
), srv_to_string(replica_rp
));
995 /*===========================================================================*
996 * inherit_service_defaults *
997 *===========================================================================*/
998 PUBLIC
void inherit_service_defaults(def_rp
, rp
)
999 struct rproc
*def_rp
;
1002 struct rprocpub
*def_rpub
;
1003 struct rprocpub
*rpub
;
1005 def_rpub
= def_rp
->r_pub
;
1008 /* Device settings. These properties cannot change. */
1009 rpub
->dev_flags
= def_rpub
->dev_flags
;
1010 rpub
->dev_nr
= def_rpub
->dev_nr
;
1011 rpub
->dev_style
= def_rpub
->dev_style
;
1012 rpub
->dev_style2
= def_rpub
->dev_style2
;
1015 if(!rpub
->period
&& def_rpub
->period
) {
1016 rpub
->period
= def_rpub
->period
;
1020 /*===========================================================================*
1021 * get_service_instances *
1022 *===========================================================================*/
1023 PUBLIC
void get_service_instances(rp
, rps
, length
)
1025 struct rproc
***rps
;
1028 /* Retrieve all the service instances of a give service. */
1029 static struct rproc
*instances
[5];
1033 instances
[nr_instances
++] = rp
;
1034 if(rp
->r_prev_rp
) instances
[nr_instances
++] = rp
->r_prev_rp
;
1035 if(rp
->r_next_rp
) instances
[nr_instances
++] = rp
->r_next_rp
;
1036 if(rp
->r_old_rp
) instances
[nr_instances
++] = rp
->r_old_rp
;
1037 if(rp
->r_new_rp
) instances
[nr_instances
++] = rp
->r_new_rp
;
1040 *length
= nr_instances
;
1043 /*===========================================================================*
1045 *===========================================================================*/
1046 PUBLIC
void share_exec(rp_dst
, rp_src
)
1047 struct rproc
*rp_dst
, *rp_src
;
1049 struct rprocpub
*rpub_src
;
1050 struct rprocpub
*rpub_dst
;
1052 rpub_src
= rp_src
->r_pub
;
1053 rpub_dst
= rp_dst
->r_pub
;
1056 printf("RS: %s shares exec image with %s\n",
1057 srv_to_string(rp_dst
), srv_to_string(rp_src
));
1059 /* Share exec image from rp_src to rp_dst. */
1060 rp_dst
->r_exec_len
= rp_src
->r_exec_len
;
1061 rp_dst
->r_exec
= rp_src
->r_exec
;
1064 /*===========================================================================*
1066 *===========================================================================*/
1067 PUBLIC
int read_exec(rp
)
1074 e_name
= rp
->r_argv
[0];
1076 printf("RS: service '%s' reads exec image from: %s\n", rp
->r_pub
->label
,
1079 r
= stat(e_name
, &sb
);
1083 fd
= open(e_name
, O_RDONLY
);
1087 rp
->r_exec_len
= sb
.st_size
;
1088 rp
->r_exec
= malloc(rp
->r_exec_len
);
1089 if (rp
->r_exec
== NULL
)
1091 printf("RS: read_exec: unable to allocate %d bytes\n",
1097 r
= read(fd
, rp
->r_exec
, rp
->r_exec_len
);
1100 if (r
== rp
->r_exec_len
)
1103 printf("RS: read_exec: read failed %d, errno %d\n", r
, e
);
1113 /*===========================================================================*
1115 *===========================================================================*/
1116 PUBLIC
void free_exec(rp
)
1119 /* Free an exec image. */
1120 int slot_nr
, has_shared_exec
, is_boot_image_mem
;
1121 struct rproc
*other_rp
;
1123 /* Search for some other slot sharing the same exec image. */
1124 has_shared_exec
= FALSE
;
1125 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1126 other_rp
= &rproc
[slot_nr
]; /* get pointer to slot */
1127 if (other_rp
->r_flags
& RS_IN_USE
&& other_rp
!= rp
1128 && other_rp
->r_exec
== rp
->r_exec
) { /* found! */
1129 has_shared_exec
= TRUE
;
1134 /* If nobody uses our copy of the exec image, we can try to get rid of it. */
1135 if(!has_shared_exec
) {
1136 is_boot_image_mem
= (rp
->r_exec
>= boot_image_buffer
1137 && rp
->r_exec
< boot_image_buffer
+ boot_image_buffer_size
);
1139 /* Free memory only if not part of the boot image buffer. */
1140 if(is_boot_image_mem
) {
1142 printf("RS: %s has exec image in the boot image buffer\n",
1147 printf("RS: %s frees exec image\n", srv_to_string(rp
));
1153 printf("RS: %s no longer sharing exec image with %s\n",
1154 srv_to_string(rp
), srv_to_string(other_rp
));
1160 /*===========================================================================*
1162 *===========================================================================*/
1163 PUBLIC
int init_slot(rp
, rs_start
, source
)
1165 struct rs_start
*rs_start
;
1168 /* Initialize a slot as requested by the client. */
1169 struct rprocpub
*rpub
;
1170 char *label
; /* unique name of command */
1171 int len
; /* length of string */
1174 int basic_kc
[] = { SYS_BASIC_CALLS
, SYS_NULL_C
};
1175 int basic_vmc
[] = { VM_BASIC_CALLS
, SYS_NULL_C
};
1179 /* Obtain command name and parameters. This is a space-separated string
1180 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
1182 if (rs_start
->rss_cmdlen
> MAX_COMMAND_LEN
-1) return(E2BIG
);
1183 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_cmd
,
1184 SELF
, (vir_bytes
) rp
->r_cmd
, rs_start
->rss_cmdlen
);
1185 if (s
!= OK
) return(s
);
1186 rp
->r_cmd
[rs_start
->rss_cmdlen
] = '\0'; /* ensure it is terminated */
1187 if (rp
->r_cmd
[0] != '/') return(EINVAL
); /* insist on absolute path */
1189 /* Build cmd dependencies: argv and program name. */
1192 if(rs_start
->rss_label
.l_len
> 0) {
1193 /* RS_UP caller has supplied a custom label for this service. */
1194 int s
= copy_label(source
, rs_start
->rss_label
.l_addr
,
1195 rs_start
->rss_label
.l_len
, rpub
->label
, sizeof(rpub
->label
));
1199 printf("RS: init_slot: using label (custom) '%s'\n", rpub
->label
);
1201 /* Default label for the service. */
1202 label
= rpub
->proc_name
;
1204 memcpy(rpub
->label
, label
, len
);
1205 rpub
->label
[len
]= '\0';
1207 printf("RS: init_slot: using label (from proc_name) '%s'\n",
1211 if(rs_start
->rss_nr_control
> 0) {
1213 if (rs_start
->rss_nr_control
> RS_NR_CONTROL
)
1215 printf("RS: init_slot: too many control labels\n");
1218 for (i
=0; i
<rs_start
->rss_nr_control
; i
++) {
1219 s
= copy_label(source
, rs_start
->rss_control
[i
].l_addr
,
1220 rs_start
->rss_control
[i
].l_len
, rp
->r_control
[i
],
1221 sizeof(rp
->r_control
[i
]));
1225 rp
->r_nr_control
= rs_start
->rss_nr_control
;
1228 printf("RS: init_slot: control labels:");
1229 for (i
=0; i
<rp
->r_nr_control
; i
++)
1230 printf(" %s", rp
->r_control
[i
]);
1235 rp
->r_script
[0]= '\0';
1236 if (rs_start
->rss_scriptlen
> MAX_SCRIPT_LEN
-1) return(E2BIG
);
1237 if (rs_start
->rss_script
!= NULL
)
1239 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_script
,
1240 SELF
, (vir_bytes
) rp
->r_script
, rs_start
->rss_scriptlen
);
1241 if (s
!= OK
) return(s
);
1242 rp
->r_script
[rs_start
->rss_scriptlen
] = '\0';
1244 rp
->r_uid
= rs_start
->rss_uid
;
1245 rp
->r_nice
= rs_start
->rss_nice
;
1247 if (rs_start
->rss_flags
& RSS_IPC_VALID
)
1249 if (rs_start
->rss_ipclen
+1 > sizeof(rp
->r_ipc_list
))
1251 printf("RS: ipc list too long for '%s'\n", rpub
->label
);
1254 s
=sys_datacopy(source
, (vir_bytes
) rs_start
->rss_ipc
,
1255 SELF
, (vir_bytes
) rp
->r_ipc_list
, rs_start
->rss_ipclen
);
1256 if (s
!= OK
) return(s
);
1257 rp
->r_ipc_list
[rs_start
->rss_ipclen
]= '\0';
1260 rp
->r_ipc_list
[0]= '\0';
1262 /* Set system flags. */
1263 rpub
->sys_flags
= DSRV_SF
;
1265 if (rs_start
->rss_flags
& RSS_COPY
) {
1268 struct rprocpub
*rpub2
;
1271 if(rs_start
->rss_flags
& RSS_REUSE
) {
1274 for(i
= 0; i
< NR_SYS_PROCS
; i
++) {
1276 rpub2
= rproc
[i
].r_pub
;
1277 if(strcmp(rpub
->proc_name
, rpub2
->proc_name
) == 0 &&
1278 (rpub2
->sys_flags
& SF_USE_COPY
)) {
1279 /* We have found the same binary that's
1280 * already been copied */
1291 share_exec(rp
, rp2
);
1296 rpub
->sys_flags
|= SF_USE_COPY
;
1298 if (rs_start
->rss_flags
& RSS_REPLICA
) {
1299 rpub
->sys_flags
|= SF_USE_REPL
;
1302 /* All dynamically created services get the same privilege flags, and
1303 * allowed traps, and signal manager. Other privilege settings can be
1304 * specified at runtime. The privilege id is dynamically allocated by
1307 rp
->r_priv
.s_flags
= DSRV_F
; /* privilege flags */
1308 rp
->r_priv
.s_trap_mask
= DSRV_T
; /* allowed traps */
1309 rp
->r_priv
.s_sig_mgr
= DSRV_SM
; /* signal manager */
1311 /* Copy granted resources */
1312 if (rs_start
->rss_nr_irq
> NR_IRQ
)
1314 printf("RS: init_slot: too many IRQs requested\n");
1317 rp
->r_priv
.s_nr_irq
= rs_start
->rss_nr_irq
;
1318 for (i
= 0; i
<rp
->r_priv
.s_nr_irq
; i
++)
1320 rp
->r_priv
.s_irq_tab
[i
]= rs_start
->rss_irq
[i
];
1322 printf("RS: init_slot: IRQ %d\n", rp
->r_priv
.s_irq_tab
[i
]);
1325 if (rs_start
->rss_nr_io
> NR_IO_RANGE
)
1327 printf("RS: init_slot: too many I/O ranges requested\n");
1330 rp
->r_priv
.s_nr_io_range
= rs_start
->rss_nr_io
;
1331 for (i
= 0; i
<rp
->r_priv
.s_nr_io_range
; i
++)
1333 rp
->r_priv
.s_io_tab
[i
].ior_base
= rs_start
->rss_io
[i
].base
;
1334 rp
->r_priv
.s_io_tab
[i
].ior_limit
=
1335 rs_start
->rss_io
[i
].base
+rs_start
->rss_io
[i
].len
-1;
1337 printf("RS: init_slot: I/O [%x..%x]\n",
1338 rp
->r_priv
.s_io_tab
[i
].ior_base
,
1339 rp
->r_priv
.s_io_tab
[i
].ior_limit
);
1342 if (rs_start
->rss_nr_pci_id
> RS_NR_PCI_DEVICE
)
1344 printf("RS: init_slot: too many PCI device IDs\n");
1347 rpub
->pci_acl
.rsp_nr_device
= rs_start
->rss_nr_pci_id
;
1348 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_device
; i
++)
1350 rpub
->pci_acl
.rsp_device
[i
].vid
= rs_start
->rss_pci_id
[i
].vid
;
1351 rpub
->pci_acl
.rsp_device
[i
].did
= rs_start
->rss_pci_id
[i
].did
;
1353 printf("RS: init_slot: PCI %04x/%04x\n",
1354 rpub
->pci_acl
.rsp_device
[i
].vid
,
1355 rpub
->pci_acl
.rsp_device
[i
].did
);
1357 if (rs_start
->rss_nr_pci_class
> RS_NR_PCI_CLASS
)
1359 printf("RS: init_slot: too many PCI class IDs\n");
1362 rpub
->pci_acl
.rsp_nr_class
= rs_start
->rss_nr_pci_class
;
1363 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_class
; i
++)
1365 rpub
->pci_acl
.rsp_class
[i
].class= rs_start
->rss_pci_class
[i
].class;
1366 rpub
->pci_acl
.rsp_class
[i
].mask
= rs_start
->rss_pci_class
[i
].mask
;
1368 printf("RS: init_slot: PCI class %06x mask %06x\n",
1369 (unsigned int) rpub
->pci_acl
.rsp_class
[i
].class,
1370 (unsigned int) rpub
->pci_acl
.rsp_class
[i
].mask
);
1373 /* Copy kernel call mask. Inherit basic kernel calls. */
1374 memcpy(rp
->r_priv
.s_k_call_mask
, rs_start
->rss_system
,
1375 sizeof(rp
->r_priv
.s_k_call_mask
));
1376 fill_call_mask(basic_kc
, NR_SYS_CALLS
,
1377 rp
->r_priv
.s_k_call_mask
, KERNEL_CALL
, FALSE
);
1379 /* Device driver properties. */
1380 rpub
->dev_flags
= DSRV_DF
;
1381 rpub
->dev_nr
= rs_start
->rss_major
;
1382 rpub
->dev_style
= rs_start
->rss_dev_style
;
1383 if(rpub
->dev_nr
&& !IS_DEV_STYLE(rs_start
->rss_dev_style
)) {
1384 printf("RS: init_slot: bad device style\n");
1387 rpub
->dev_style2
= STYLE_NDEV
;
1389 /* Initialize some fields. */
1390 rpub
->period
= rs_start
->rss_period
;
1391 rp
->r_restarts
= 0; /* no restarts yet */
1392 rp
->r_set_resources
= 1; /* set resources */
1393 rp
->r_old_rp
= NULL
; /* no old version yet */
1394 rp
->r_new_rp
= NULL
; /* no new version yet */
1395 rp
->r_prev_rp
= NULL
; /* no prev replica yet */
1396 rp
->r_next_rp
= NULL
; /* no next replica yet */
1398 /* Copy VM call mask. Inherit basic VM calls. */
1399 memcpy(rpub
->vm_call_mask
, rs_start
->rss_vm
,
1400 sizeof(rpub
->vm_call_mask
));
1401 fill_call_mask(basic_vmc
, NR_VM_CALLS
,
1402 rpub
->vm_call_mask
, VM_RQ_BASE
, FALSE
);
1407 /*===========================================================================*
1409 *===========================================================================*/
1410 PUBLIC
int clone_slot(rp
, clone_rpp
)
1412 struct rproc
**clone_rpp
;
1415 struct rproc
*clone_rp
;
1416 struct rprocpub
*rpub
, *clone_rpub
;
1418 /* Allocate a system service slot for the clone. */
1419 r
= alloc_slot(&clone_rp
);
1421 printf("RS: clone_slot: unable to allocate a new slot: %d\n", r
);
1426 clone_rpub
= clone_rp
->r_pub
;
1430 *clone_rpub
= *rpub
;
1433 clone_rp
->r_flags
&= ~RS_ACTIVE
; /* the clone is not active yet */
1434 clone_rp
->r_pid
= -1; /* no pid yet */
1435 clone_rpub
->endpoint
= -1; /* no endpoint yet */
1436 clone_rp
->r_pub
= clone_rpub
; /* restore pointer to public entry */
1437 build_cmd_dep(clone_rp
); /* rebuild cmd dependencies */
1438 if(clone_rpub
->sys_flags
& SF_USE_COPY
) {
1439 share_exec(clone_rp
, rp
); /* share exec image */
1442 /* Force dynamic privilege id. */
1443 clone_rp
->r_priv
.s_flags
|= DYN_PRIV_ID
;
1445 *clone_rpp
= clone_rp
;
1449 /*===========================================================================*
1450 * swap_slot_pointer *
1451 *===========================================================================*/
1452 PRIVATE
void swap_slot_pointer(struct rproc
**rpp
, struct rproc
*src_rp
,
1453 struct rproc
*dst_rp
)
1455 if(*rpp
== src_rp
) {
1458 else if(*rpp
== dst_rp
) {
1463 /*===========================================================================*
1465 *===========================================================================*/
1466 PUBLIC
void swap_slot(src_rpp
, dst_rpp
)
1467 struct rproc
**src_rpp
;
1468 struct rproc
**dst_rpp
;
1470 /* Swap two service slots. */
1471 struct rproc
*src_rp
;
1472 struct rproc
*dst_rp
;
1473 struct rprocpub
*src_rpub
;
1474 struct rprocpub
*dst_rpub
;
1475 struct rproc orig_src_rproc
, orig_dst_rproc
;
1476 struct rprocpub orig_src_rprocpub
, orig_dst_rprocpub
;
1480 src_rpub
= src_rp
->r_pub
;
1481 dst_rpub
= dst_rp
->r_pub
;
1483 /* Save existing data first. */
1484 orig_src_rproc
= *src_rp
;
1485 orig_src_rprocpub
= *src_rpub
;
1486 orig_dst_rproc
= *dst_rp
;
1487 orig_dst_rprocpub
= *dst_rpub
;
1490 *src_rp
= orig_dst_rproc
;
1491 *src_rpub
= orig_dst_rprocpub
;
1492 *dst_rp
= orig_src_rproc
;
1493 *dst_rpub
= orig_src_rprocpub
;
1495 /* Restore public entries. */
1496 src_rp
->r_pub
= orig_src_rproc
.r_pub
;
1497 dst_rp
->r_pub
= orig_dst_rproc
.r_pub
;
1499 /* Rebuild command dependencies. */
1500 build_cmd_dep(src_rp
);
1501 build_cmd_dep(dst_rp
);
1503 /* Swap local slot pointers. */
1504 swap_slot_pointer(&src_rp
->r_prev_rp
, src_rp
, dst_rp
);
1505 swap_slot_pointer(&src_rp
->r_next_rp
, src_rp
, dst_rp
);
1506 swap_slot_pointer(&src_rp
->r_old_rp
, src_rp
, dst_rp
);
1507 swap_slot_pointer(&src_rp
->r_new_rp
, src_rp
, dst_rp
);
1508 swap_slot_pointer(&dst_rp
->r_prev_rp
, src_rp
, dst_rp
);
1509 swap_slot_pointer(&dst_rp
->r_next_rp
, src_rp
, dst_rp
);
1510 swap_slot_pointer(&dst_rp
->r_old_rp
, src_rp
, dst_rp
);
1511 swap_slot_pointer(&dst_rp
->r_new_rp
, src_rp
, dst_rp
);
1513 /* Swap global slot pointers. */
1514 swap_slot_pointer(&rupdate
.rp
, src_rp
, dst_rp
);
1515 swap_slot_pointer(&rproc_ptr
[_ENDPOINT_P(src_rp
->r_pub
->endpoint
)],
1517 swap_slot_pointer(&rproc_ptr
[_ENDPOINT_P(dst_rp
->r_pub
->endpoint
)],
1520 /* Adjust input pointers. */
1525 /*===========================================================================*
1526 * lookup_slot_by_label *
1527 *===========================================================================*/
1528 PUBLIC
struct rproc
* lookup_slot_by_label(char *label
)
1530 /* Lookup a service slot matching the given label. */
1533 struct rprocpub
*rpub
;
1535 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1536 rp
= &rproc
[slot_nr
];
1537 if (!(rp
->r_flags
& RS_ACTIVE
)) {
1541 if (strcmp(rpub
->label
, label
) == 0) {
1549 /*===========================================================================*
1550 * lookup_slot_by_pid *
1551 *===========================================================================*/
1552 PUBLIC
struct rproc
* lookup_slot_by_pid(pid_t pid
)
1554 /* Lookup a service slot matching the given pid. */
1562 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1563 rp
= &rproc
[slot_nr
];
1564 if (!(rp
->r_flags
& RS_IN_USE
)) {
1567 if (rp
->r_pid
== pid
) {
1575 /*===========================================================================*
1576 * lookup_slot_by_dev_nr *
1577 *===========================================================================*/
1578 PUBLIC
struct rproc
* lookup_slot_by_dev_nr(dev_t dev_nr
)
1580 /* Lookup a service slot matching the given device number. */
1583 struct rprocpub
*rpub
;
1589 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1590 rp
= &rproc
[slot_nr
];
1592 if (!(rp
->r_flags
& RS_IN_USE
)) {
1595 if (rpub
->dev_nr
== dev_nr
) {
1603 /*===========================================================================*
1605 *===========================================================================*/
1606 PUBLIC
int alloc_slot(rpp
)
1609 /* Alloc a new system service slot. */
1612 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1613 *rpp
= &rproc
[slot_nr
]; /* get pointer to slot */
1614 if (!((*rpp
)->r_flags
& RS_IN_USE
)) /* check if available */
1617 if (slot_nr
>= NR_SYS_PROCS
) {
1624 /*===========================================================================*
1626 *===========================================================================*/
1627 PUBLIC
void free_slot(rp
)
1630 /* Free a system service slot. */
1631 struct rprocpub
*rpub
;
1635 /* Send a late reply if there is any pending. */
1638 /* Free memory if necessary. */
1639 if(rpub
->sys_flags
& SF_USE_COPY
) {
1643 /* Mark slot as no longer in use.. */
1646 rpub
->in_use
= FALSE
;
1647 rproc_ptr
[_ENDPOINT_P(rpub
->endpoint
)] = NULL
;
1651 /*===========================================================================*
1653 *===========================================================================*/
1654 PUBLIC
char *get_next_label(ptr
, label
, caller_label
)
1659 /* Get the next label from the list of (IPC) labels.
1664 for (p
= ptr
; p
[0] != '\0'; p
= q
)
1666 /* Skip leading space */
1667 while (p
[0] != '\0' && isspace((unsigned char)p
[0]))
1670 /* Find start of next word */
1672 while (q
[0] != '\0' && !isspace((unsigned char)q
[0]))
1677 if (len
> RS_MAX_LABEL_LEN
)
1680 "rs:get_next_label: bad ipc list entry '%.*s' for %s: too long\n",
1681 len
, p
, caller_label
);
1684 memcpy(label
, p
, len
);
1687 return q
; /* found another */
1690 return NULL
; /* done */
1693 /*===========================================================================*
1695 *===========================================================================*/
1696 PUBLIC
void add_forward_ipc(rp
, privp
)
1700 /* Add IPC send permissions to a process based on that process's IPC
1703 char label
[RS_MAX_LABEL_LEN
+1], *p
;
1704 struct rproc
*tmp_rp
;
1705 struct rprocpub
*tmp_rpub
;
1706 endpoint_t endpoint
;
1710 struct rprocpub
*rpub
;
1715 while ((p
= get_next_label(p
, label
, rpub
->label
)) != NULL
) {
1717 if (strcmp(label
, "SYSTEM") == 0)
1719 else if (strcmp(label
, "USER") == 0)
1720 endpoint
= INIT_PROC_NR
; /* all user procs */
1721 else if (strcmp(label
, "PM") == 0)
1722 endpoint
= PM_PROC_NR
;
1723 else if (strcmp(label
, "VFS") == 0)
1724 endpoint
= FS_PROC_NR
;
1725 else if (strcmp(label
, "RS") == 0)
1726 endpoint
= RS_PROC_NR
;
1727 else if (strcmp(label
, "LOG") == 0)
1728 endpoint
= LOG_PROC_NR
;
1729 else if (strcmp(label
, "TTY") == 0)
1730 endpoint
= TTY_PROC_NR
;
1731 else if (strcmp(label
, "DS") == 0)
1732 endpoint
= DS_PROC_NR
;
1733 else if (strcmp(label
, "VM") == 0)
1734 endpoint
= VM_PROC_NR
;
1737 /* Try to find process */
1738 tmp_rp
= lookup_slot_by_label(label
);
1741 tmp_rpub
= tmp_rp
->r_pub
;
1742 endpoint
= tmp_rpub
->endpoint
;
1745 if ((r
= sys_getpriv(&priv
, endpoint
)) < 0)
1748 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1753 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1758 /*===========================================================================*
1759 * add_backward_ipc *
1760 *===========================================================================*/
1761 PUBLIC
void add_backward_ipc(rp
, privp
)
1765 /* Add IPC send permissions to a process based on other processes' IPC
1766 * lists. This is enough to allow each such two processes to talk to
1767 * each other, as the kernel guarantees send mask symmetry. We need to
1768 * add these permissions now because the current process may not yet
1769 * have existed at the time that the other process was initialized.
1771 char label
[RS_MAX_LABEL_LEN
+1], *p
;
1773 struct rprocpub
*rrpub
;
1776 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
1777 if (!(rrp
->r_flags
& RS_IN_USE
))
1780 /* If an IPC target list was provided for the process being
1781 * checked here, make sure that the label of the new process
1782 * is in that process's list.
1784 if (rrp
->r_ipc_list
[0]) {
1788 p
= rrp
->r_ipc_list
;
1790 while ((p
= get_next_label(p
, label
,
1791 rrpub
->label
)) != NULL
) {
1792 if (!strcmp(rrpub
->label
, label
)) {
1802 priv_id
= rrp
->r_priv
.s_id
;
1804 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1809 /*===========================================================================*
1811 *===========================================================================*/
1812 PUBLIC
void init_privs(rp
, privp
)
1818 /* Clear s_ipc_to */
1819 memset(&privp
->s_ipc_to
, '\0', sizeof(privp
->s_ipc_to
));
1821 if (strlen(rp
->r_ipc_list
) != 0)
1823 add_forward_ipc(rp
, privp
);
1824 add_backward_ipc(rp
, privp
);
1829 for (i
= 0; i
<NR_SYS_PROCS
; i
++)
1831 if (i
!= USER_PRIV_ID
)
1832 set_sys_bit(privp
->s_ipc_to
, i
);