3 * Nov 22, 2009: added basic live update support (Cristiano Giuffrida)
4 * Mar 02, 2009: Extended isolation policies (Jorrit N. Herder)
5 * Jul 22, 2005: Created (Jorrit N. Herder)
12 #include <sys/types.h>
19 #include <minix/sysutil.h>
21 /* Prototypes for internal functions that do the hard work. */
22 FORWARD
_PROTOTYPE( int caller_is_root
, (endpoint_t endpoint
) );
23 FORWARD
_PROTOTYPE( int caller_can_control
, (endpoint_t endpoint
,
25 FORWARD
_PROTOTYPE( int copy_label
, (endpoint_t src_e
,
26 struct rss_label
*src_label
, char *dst_label
, size_t dst_len
) );
27 FORWARD
_PROTOTYPE( int start_service
, (struct rproc
*rp
, int flags
,
29 FORWARD
_PROTOTYPE( void stop_service
, (struct rproc
*rp
,int how
) );
30 FORWARD
_PROTOTYPE( int fork_nb
, (void) );
31 FORWARD
_PROTOTYPE( int read_exec
, (struct rproc
*rp
) );
32 FORWARD
_PROTOTYPE( int share_exec
, (struct rproc
*rp_src
,
33 struct rproc
*rp_dst
) );
34 FORWARD
_PROTOTYPE( void free_slot
, (struct rproc
*rp
) );
35 FORWARD
_PROTOTYPE( void run_script
, (struct rproc
*rp
) );
36 FORWARD
_PROTOTYPE( char *get_next_label
, (char *ptr
, char *label
,
37 char *caller_label
) );
38 FORWARD
_PROTOTYPE( void add_forward_ipc
, (struct rproc
*rp
,
39 struct priv
*privp
) );
40 FORWARD
_PROTOTYPE( void add_backward_ipc
, (struct rproc
*rp
,
41 struct priv
*privp
) );
42 FORWARD
_PROTOTYPE( void init_privs
, (struct rproc
*rp
, struct priv
*privp
) );
43 FORWARD
_PROTOTYPE( void init_pci
, (struct rproc
*rp
, int endpoint
) );
44 FORWARD
_PROTOTYPE( void update_period
, (message
*m_ptr
) );
45 FORWARD
_PROTOTYPE( void end_update
, (clock_t now
) );
47 PRIVATE
int shutting_down
= FALSE
;
49 /*===========================================================================*
51 *===========================================================================*/
52 PRIVATE
int caller_is_root(endpoint
)
53 endpoint_t endpoint
; /* caller endpoint */
57 /* Check if caller has root user ID. */
58 euid
= getnuid(endpoint
);
59 if (rs_verbose
&& euid
!= 0)
61 printf("RS: got unauthorized request from endpoint %d\n", endpoint
);
67 /*===========================================================================*
68 * caller_can_control *
69 *===========================================================================*/
70 PRIVATE
int caller_can_control(endpoint
, label
)
74 int control_allowed
= 0;
75 register struct rproc
*rp
;
76 register struct rprocpub
*rpub
;
80 /* Find name of binary for given label. */
81 for (rp
= BEG_RPROC_ADDR
; rp
< END_RPROC_ADDR
; rp
++) {
83 if (strcmp(rpub
->label
, label
) == 0) {
87 if (rp
== END_RPROC_ADDR
) return 0;
88 progname
= strrchr(rp
->r_argv
[0], '/');
92 progname
= rp
->r_argv
[0];
94 /* Check if label is listed in caller's isolation policy. */
95 for (rp
= BEG_RPROC_ADDR
; rp
< END_RPROC_ADDR
; rp
++) {
97 if (rpub
->endpoint
== endpoint
) {
101 if (rp
== END_RPROC_ADDR
) return 0;
102 if (rp
->r_nr_control
> 0) {
103 for (c
= 0; c
< rp
->r_nr_control
; c
++) {
104 if (strcmp(rp
->r_control
[c
], progname
) == 0)
110 printf("RS: allowing %u control over %s via policy: %s\n",
111 endpoint
, label
, control_allowed
? "yes" : "no");
113 return control_allowed
;
116 /*===========================================================================*
118 *===========================================================================*/
119 PRIVATE
int copy_label(src_e
, src_label
, dst_label
, dst_len
)
121 struct rss_label
*src_label
;
127 len
= MIN(dst_len
-1, src_label
->l_len
);
129 s
= sys_datacopy(src_e
, (vir_bytes
) src_label
->l_addr
,
130 SELF
, (vir_bytes
) dst_label
, len
);
131 if (s
!= OK
) return s
;
138 /*===========================================================================*
140 *===========================================================================*/
141 PUBLIC
int do_up(m_ptr
)
142 message
*m_ptr
; /* request message pointer */
144 /* A request was made to start a new system service.
146 register struct rproc
*rp
; /* system process table */
147 register struct rprocpub
*rpub
; /* public entry */
148 int slot_nr
; /* local table entry */
149 int arg_count
; /* number of arguments */
150 char *cmd_ptr
; /* parse command string */
151 char *label
; /* unique name of command */
152 enum dev_style dev_style
; /* device style */
153 int s
; /* status variable */
154 int len
; /* length of string */
158 struct rproc
*tmp_rp
;
159 struct rprocpub
*tmp_rpub
;
160 struct rs_start rs_start
;
162 /* This call requires special privileges. */
163 if (!caller_is_root(m_ptr
->m_source
)) return(EPERM
);
165 /* See if there is a free entry in the table with system processes. */
166 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
167 rp
= &rproc
[slot_nr
]; /* get pointer to slot */
168 if (!(rp
->r_flags
& RS_IN_USE
)) /* check if available */
171 if (slot_nr
>= NR_SYS_PROCS
)
173 printf("RS: do_up: system process table full\n");
178 /* Ok, there is space. Get the request structure. */
179 s
= sys_datacopy(m_ptr
->m_source
, (vir_bytes
) m_ptr
->RS_CMD_ADDR
,
180 SELF
, (vir_bytes
) &rs_start
, sizeof(rs_start
));
181 if (s
!= OK
) return(s
);
183 /* Obtain command name and parameters. This is a space-separated string
184 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
186 if (rs_start
.rss_cmdlen
> MAX_COMMAND_LEN
-1) return(E2BIG
);
187 s
=sys_datacopy(m_ptr
->m_source
, (vir_bytes
) rs_start
.rss_cmd
,
188 SELF
, (vir_bytes
) rp
->r_cmd
, rs_start
.rss_cmdlen
);
189 if (s
!= OK
) return(s
);
190 rp
->r_cmd
[rs_start
.rss_cmdlen
] = '\0'; /* ensure it is terminated */
191 if (rp
->r_cmd
[0] != '/') return(EINVAL
); /* insist on absolute path */
193 /* Build argument vector to be passed to execute call. The format of the
194 * arguments vector is: path, arguments, NULL.
196 arg_count
= 0; /* initialize arg count */
197 rp
->r_argv
[arg_count
++] = rp
->r_cmd
; /* start with path */
198 cmd_ptr
= rp
->r_cmd
; /* do some parsing */
199 while(*cmd_ptr
!= '\0') { /* stop at end of string */
200 if (*cmd_ptr
== ' ') { /* next argument */
201 *cmd_ptr
= '\0'; /* terminate previous */
202 while (*++cmd_ptr
== ' ') ; /* skip spaces */
203 if (*cmd_ptr
== '\0') break; /* no arg following */
204 if (arg_count
>MAX_NR_ARGS
+1) break; /* arg vector full */
205 rp
->r_argv
[arg_count
++] = cmd_ptr
; /* add to arg vector */
207 cmd_ptr
++; /* continue parsing */
209 rp
->r_argv
[arg_count
] = NULL
; /* end with NULL pointer */
210 rp
->r_argc
= arg_count
;
212 /* Process name for the service. */
213 cmd_ptr
= strrchr(rp
->r_argv
[0], '/');
217 cmd_ptr
= rp
->r_argv
[0];
218 len
= strlen(cmd_ptr
);
219 if (len
> RS_MAX_LABEL_LEN
-1)
220 len
= RS_MAX_LABEL_LEN
-1; /* truncate name */
221 memcpy(rpub
->proc_name
, cmd_ptr
, len
);
222 rpub
->proc_name
[len
]= '\0';
224 printf("RS: do_up: using proc_name (from binary %s) '%s'\n",
225 rp
->r_argv
[0], rpub
->proc_name
);
227 if(rs_start
.rss_label
.l_len
> 0) {
228 /* RS_UP caller has supplied a custom label for this service. */
229 int s
= copy_label(m_ptr
->m_source
, &rs_start
.rss_label
,
230 rpub
->label
, sizeof(rpub
->label
));
234 printf("RS: do_up: using label (custom) '%s'\n", rpub
->label
);
236 /* Default label for the service. */
237 label
= rpub
->proc_name
;
239 memcpy(rpub
->label
, label
, len
);
240 rpub
->label
[len
]= '\0';
242 printf("RS: do_up: using label (from proc_name) '%s'\n",
246 if(rs_start
.rss_nr_control
> 0) {
248 if (rs_start
.rss_nr_control
> RS_NR_CONTROL
)
250 printf("RS: do_up: too many control labels\n");
253 for (i
=0; i
<rs_start
.rss_nr_control
; i
++) {
254 s
= copy_label(m_ptr
->m_source
, &rs_start
.rss_control
[i
],
255 rp
->r_control
[i
], sizeof(rp
->r_control
[i
]));
259 rp
->r_nr_control
= rs_start
.rss_nr_control
;
262 printf("RS: do_up: control labels:");
263 for (i
=0; i
<rp
->r_nr_control
; i
++)
264 printf(" %s", rp
->r_control
[i
]);
269 /* Check for duplicates */
270 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
271 tmp_rp
= &rproc
[slot_nr
]; /* get pointer to slot */
272 if (!(tmp_rp
->r_flags
& RS_IN_USE
)) /* check if available */
275 continue; /* Our slot */
276 tmp_rpub
= tmp_rp
->r_pub
;
277 if (strcmp(tmp_rpub
->label
, rpub
->label
) == 0)
279 printf("RS: found duplicate label '%s': slot %d\n",
280 rpub
->label
, slot_nr
);
285 rp
->r_script
[0]= '\0';
286 if (rs_start
.rss_scriptlen
> MAX_SCRIPT_LEN
-1) return(E2BIG
);
287 if (rs_start
.rss_script
!= NULL
)
289 s
=sys_datacopy(m_ptr
->m_source
, (vir_bytes
) rs_start
.rss_script
,
290 SELF
, (vir_bytes
) rp
->r_script
, rs_start
.rss_scriptlen
);
291 if (s
!= OK
) return(s
);
292 rp
->r_script
[rs_start
.rss_scriptlen
] = '\0';
294 rp
->r_uid
= rs_start
.rss_uid
;
295 rp
->r_nice
= rs_start
.rss_nice
;
297 if (rs_start
.rss_flags
& RSS_IPC_VALID
)
299 if (rs_start
.rss_ipclen
+1 > sizeof(rp
->r_ipc_list
))
301 printf("rs: ipc list too long for '%s'\n", rpub
->label
);
304 s
=sys_datacopy(m_ptr
->m_source
, (vir_bytes
) rs_start
.rss_ipc
,
305 SELF
, (vir_bytes
) rp
->r_ipc_list
, rs_start
.rss_ipclen
);
306 if (s
!= OK
) return(s
);
307 rp
->r_ipc_list
[rs_start
.rss_ipclen
]= '\0';
310 rp
->r_ipc_list
[0]= '\0';
312 rpub
->sys_flags
= DSRV_SF
;
314 if (rs_start
.rss_flags
& RSS_COPY
) {
317 struct rprocpub
*rpub2
;
320 if(rs_start
.rss_flags
& RSS_REUSE
) {
323 for(i
= 0; i
< NR_SYS_PROCS
; i
++) {
325 rpub2
= rproc
[i
].r_pub
;
326 if(strcmp(rpub
->proc_name
, rpub2
->proc_name
) == 0 &&
327 (rpub2
->sys_flags
& SF_USE_COPY
)) {
328 /* We have found the same binary that's
329 * already been copied */
339 s
= share_exec(rp
, rp2
);
344 rpub
->sys_flags
|= SF_USE_COPY
;
347 /* All dynamically created services get the same privilege flags, and
348 * allowed traps. Other privilege settings can be specified at runtime.
349 * The privilege id is dynamically allocated by the kernel.
351 rp
->r_priv
.s_flags
= DSRV_F
; /* privilege flags */
352 rp
->r_priv
.s_trap_mask
= DSRV_T
; /* allowed traps */
354 /* Copy granted resources */
355 if (rs_start
.rss_nr_irq
> NR_IRQ
)
357 printf("RS: do_up: too many IRQs requested\n");
360 rp
->r_priv
.s_nr_irq
= rs_start
.rss_nr_irq
;
361 for (i
= 0; i
<rp
->r_priv
.s_nr_irq
; i
++)
363 rp
->r_priv
.s_irq_tab
[i
]= rs_start
.rss_irq
[i
];
365 printf("RS: do_up: IRQ %d\n", rp
->r_priv
.s_irq_tab
[i
]);
368 if (rs_start
.rss_nr_io
> NR_IO_RANGE
)
370 printf("RS: do_up: too many I/O ranges requested\n");
373 rp
->r_priv
.s_nr_io_range
= rs_start
.rss_nr_io
;
374 for (i
= 0; i
<rp
->r_priv
.s_nr_io_range
; i
++)
376 rp
->r_priv
.s_io_tab
[i
].ior_base
= rs_start
.rss_io
[i
].base
;
377 rp
->r_priv
.s_io_tab
[i
].ior_limit
=
378 rs_start
.rss_io
[i
].base
+rs_start
.rss_io
[i
].len
-1;
380 printf("RS: do_up: I/O [%x..%x]\n",
381 rp
->r_priv
.s_io_tab
[i
].ior_base
,
382 rp
->r_priv
.s_io_tab
[i
].ior_limit
);
385 if (rs_start
.rss_nr_pci_id
> RS_NR_PCI_DEVICE
)
387 printf("RS: do_up: too many PCI device IDs\n");
390 rpub
->pci_acl
.rsp_nr_device
= rs_start
.rss_nr_pci_id
;
391 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_device
; i
++)
393 rpub
->pci_acl
.rsp_device
[i
].vid
= rs_start
.rss_pci_id
[i
].vid
;
394 rpub
->pci_acl
.rsp_device
[i
].did
= rs_start
.rss_pci_id
[i
].did
;
396 printf("RS: do_up: PCI %04x/%04x\n",
397 rpub
->pci_acl
.rsp_device
[i
].vid
,
398 rpub
->pci_acl
.rsp_device
[i
].did
);
400 if (rs_start
.rss_nr_pci_class
> RS_NR_PCI_CLASS
)
402 printf("RS: do_up: too many PCI class IDs\n");
405 rpub
->pci_acl
.rsp_nr_class
= rs_start
.rss_nr_pci_class
;
406 for (i
= 0; i
<rpub
->pci_acl
.rsp_nr_class
; i
++)
408 rpub
->pci_acl
.rsp_class
[i
].class= rs_start
.rss_pci_class
[i
].class;
409 rpub
->pci_acl
.rsp_class
[i
].mask
= rs_start
.rss_pci_class
[i
].mask
;
411 printf("RS: do_up: PCI class %06x mask %06x\n",
412 rpub
->pci_acl
.rsp_class
[i
].class,
413 rpub
->pci_acl
.rsp_class
[i
].mask
);
416 /* Copy 'system' call number bits */
417 if (sizeof(rs_start
.rss_system
[0]) == sizeof(rp
->r_call_mask
[0]) &&
418 sizeof(rs_start
.rss_system
) == sizeof(rp
->r_call_mask
))
420 for (i
= 0; i
<RS_SYS_CALL_MASK_SIZE
; i
++)
421 rp
->r_call_mask
[i
]= rs_start
.rss_system
[i
];
426 "RS: do_up: internal inconsistency: bad size of r_call_mask\n");
427 memset(rp
->r_call_mask
, '\0', sizeof(rp
->r_call_mask
));
430 /* Initialize some fields. */
431 rpub
->period
= rs_start
.rss_period
;
432 rpub
->dev_nr
= rs_start
.rss_major
;
433 rpub
->dev_style
= STYLE_DEV
;
434 rp
->r_restarts
= -1; /* will be incremented */
435 rp
->r_set_resources
= 1; /* set resources */
437 if (sizeof(rpub
->vm_call_mask
) == sizeof(rs_start
.rss_vm
) &&
438 sizeof(rpub
->vm_call_mask
[0]) == sizeof(rs_start
.rss_vm
[0]))
440 int basic_vmc
[] = { VM_BASIC_CALLS
, SYS_NULL_C
};
441 memcpy(rpub
->vm_call_mask
, rs_start
.rss_vm
,
442 sizeof(rpub
->vm_call_mask
));
443 fill_call_mask(basic_vmc
, NR_VM_CALLS
,
444 rpub
->vm_call_mask
, VM_RQ_BASE
, FALSE
);
448 printf("RS: internal inconsistency: bad size of vm_call_mask\n");
449 memset(rpub
->vm_call_mask
, '\0', sizeof(rpub
->vm_call_mask
));
452 /* All information was gathered. Now try to start the system service. */
453 r
= start_service(rp
, 0, &ep
);
454 m_ptr
->RS_ENDPOINT
= ep
;
459 /*===========================================================================*
461 *===========================================================================*/
462 PUBLIC
int do_down(message
*m_ptr
)
464 register struct rproc
*rp
;
465 register struct rprocpub
*rpub
;
468 char label
[RS_MAX_LABEL_LEN
];
470 /* This call requires special privileges. */
471 if (!caller_is_root(m_ptr
->m_source
)) return(EPERM
);
473 len
= m_ptr
->RS_CMD_LEN
;
474 if (len
>= sizeof(label
))
475 return EINVAL
; /* Too long */
477 s
= sys_datacopy(m_ptr
->m_source
, (vir_bytes
) m_ptr
->RS_CMD_ADDR
,
478 SELF
, (vir_bytes
) label
, len
);
479 if (s
!= OK
) return(s
);
482 for (rp
=BEG_RPROC_ADDR
; rp
<END_RPROC_ADDR
; rp
++) {
484 if (rp
->r_flags
& RS_IN_USE
&& strcmp(rpub
->label
, label
) == 0) {
485 /* Core system services should never go down. */
486 if (rpub
->sys_flags
& SF_CORE_SRV
) return(EPERM
);
489 printf("RS: stopping '%s' (%d)\n", label
, rp
->r_pid
);
490 stop_service(rp
,RS_EXITING
);
493 /* Process is already gone, release slot. */
498 /* Late reply - send a reply when process dies. */
499 rp
->r_flags
|= RS_LATEREPLY
;
500 rp
->r_caller
= m_ptr
->m_source
;
504 if(rs_verbose
) printf("RS: do_down: '%s' not found\n", label
);
509 /*===========================================================================*
511 *===========================================================================*/
512 PUBLIC
int do_restart(message
*m_ptr
)
514 register struct rproc
*rp
;
515 register struct rprocpub
*rpub
;
518 char label
[RS_MAX_LABEL_LEN
];
521 len
= m_ptr
->RS_CMD_LEN
;
522 if (len
>= sizeof(label
))
523 return EINVAL
; /* Too long */
525 s
= sys_datacopy(m_ptr
->m_source
, (vir_bytes
) m_ptr
->RS_CMD_ADDR
,
526 SELF
, (vir_bytes
) label
, len
);
527 if (s
!= OK
) return(s
);
530 /* This call requires special privileges. */
531 if (! (caller_can_control(m_ptr
->m_source
, label
) ||
532 caller_is_root(m_ptr
->m_source
))) {
536 for (rp
=BEG_RPROC_ADDR
; rp
<END_RPROC_ADDR
; rp
++) {
538 if ((rp
->r_flags
& RS_IN_USE
) && strcmp(rpub
->label
, label
) == 0) {
539 if(rs_verbose
) printf("RS: restarting '%s' (%d)\n", label
, rp
->r_pid
);
543 printf("RS: do_restart: '%s' is (still) running, pid = %d\n",
547 rp
->r_flags
&= ~(RS_REFRESHING
|RS_NOPINGREPLY
);
548 r
= start_service(rp
, 0, &ep
);
549 if (r
!= OK
) printf("do_restart: start_service failed: %d\n", r
);
550 m_ptr
->RS_ENDPOINT
= ep
;
555 printf("RS: do_restart: '%s' not found\n", label
);
562 /*===========================================================================*
564 *===========================================================================*/
565 PUBLIC
int do_refresh(message
*m_ptr
)
567 register struct rproc
*rp
;
568 register struct rprocpub
*rpub
;
571 char label
[RS_MAX_LABEL_LEN
];
573 len
= m_ptr
->RS_CMD_LEN
;
574 if (len
>= sizeof(label
))
575 return EINVAL
; /* Too long */
577 s
= sys_datacopy(m_ptr
->m_source
, (vir_bytes
) m_ptr
->RS_CMD_ADDR
,
578 SELF
, (vir_bytes
) label
, len
);
579 if (s
!= OK
) return(s
);
582 /* This call requires special privileges. */
583 if (! (caller_can_control(m_ptr
->m_source
, label
) ||
584 caller_is_root(m_ptr
->m_source
))) {
588 for (rp
=BEG_RPROC_ADDR
; rp
<END_RPROC_ADDR
; rp
++) {
590 if (rp
->r_flags
& RS_IN_USE
&& strcmp(rpub
->label
, label
) == 0) {
591 /* Only system processes not including RS can refresh. */
592 if(!(rp
->r_priv
.s_flags
& SYS_PROC
) || rpub
->endpoint
== RS_PROC_NR
) {
597 printf("RS: refreshing %s (%d)\n", rpub
->label
, rp
->r_pid
);
599 stop_service(rp
,RS_REFRESHING
);
604 printf("RS: do_refresh: '%s' not found\n", label
);
610 /*===========================================================================*
612 *===========================================================================*/
613 PUBLIC
int do_shutdown(message
*m_ptr
)
615 /* This call requires special privileges. */
616 if (m_ptr
!= NULL
&& !caller_is_root(m_ptr
->m_source
)) return(EPERM
);
618 /* Set flag so that RS server knows services shouldn't be restarted. */
619 shutting_down
= TRUE
;
624 /*===========================================================================*
626 *===========================================================================*/
627 PUBLIC
int do_init_ready(message
*m_ptr
)
631 struct rprocpub
*rpub
;
634 who_p
= _ENDPOINT_P(m_ptr
->m_source
);
635 rp
= rproc_ptr
[who_p
];
637 result
= m_ptr
->RS_INIT_RESULT
;
639 /* Make sure the originating service was requested to initialize. */
640 if(! (rp
->r_flags
& RS_INITIALIZING
) ) {
642 printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
648 /* Mark the slot as no longer initializing. */
649 rp
->r_flags
&= ~RS_INITIALIZING
;
651 getuptime(&rp
->r_alive_tm
);
653 /* Check if something went wrong and the service failed to init.
654 * In that case, kill it and make sure it won't be restarted.
658 printf("RS: initialization failed for service %d: %d\n",
659 rpub
->endpoint
, result
);
660 rp
->r_flags
|= RS_EXITING
;
661 kill(rp
->r_pid
, SIGKILL
);
665 printf("RS: initialization succeeded for service %d\n",
672 /*===========================================================================*
674 *===========================================================================*/
675 PUBLIC
int do_update(message
*m_ptr
)
677 register struct rproc
*rp
;
678 register struct rprocpub
*rpub
;
681 char label
[RS_MAX_LABEL_LEN
];
685 /* Retrieve label. */
686 len
= m_ptr
->RS_CMD_LEN
;
687 if (len
>= sizeof(label
))
688 return EINVAL
; /* Too long */
689 s
= sys_datacopy(m_ptr
->m_source
, (vir_bytes
) m_ptr
->RS_CMD_ADDR
,
690 SELF
, (vir_bytes
) label
, len
);
691 if (s
!= OK
) return(s
);
694 /* This call requires special privileges. */
695 if (! (caller_can_control(m_ptr
->m_source
, label
) ||
696 caller_is_root(m_ptr
->m_source
))) {
700 /* Retrieve live update state. */
701 lu_state
= m_ptr
->RS_LU_STATE
;
702 if(lu_state
== SEF_LU_STATE_NULL
) {
706 /* Retrieve prepare max time. */
707 prepare_maxtime
= m_ptr
->RS_LU_PREPARE_MAXTIME
;
708 if(prepare_maxtime
) {
709 if(prepare_maxtime
< 0 || prepare_maxtime
> RS_MAX_PREPARE_MAXTIME
) {
714 prepare_maxtime
= RS_DEFAULT_PREPARE_MAXTIME
;
717 /* Make sure we are not already updating. */
718 if(rupdate
.flags
& RS_UPDATING
) {
720 printf("RS: do_update: an update is already in progress");
725 /* Try to start the update process. */
726 for (rp
=BEG_RPROC_ADDR
; rp
<END_RPROC_ADDR
; rp
++) {
728 if (rp
->r_flags
& RS_IN_USE
&& strcmp(rpub
->label
, label
) == 0) {
729 /* Only system processes not including RS can update. */
730 if(!(rp
->r_priv
.s_flags
& SYS_PROC
) || rpub
->endpoint
== RS_PROC_NR
) {
735 printf("RS: updating %s (%d)\n", rpub
->label
, rp
->r_pid
);
738 rp
->r_flags
|= RS_UPDATING
;
739 rupdate
.flags
|= RS_UPDATING
;
740 getuptime(&rupdate
.prepare_tm
);
741 rupdate
.prepare_maxtime
= prepare_maxtime
;
744 m_ptr
->m_type
= RS_LU_PREPARE
;
745 asynsend(rpub
->endpoint
, m_ptr
); /* request to update */
751 printf("RS: do_update: '%s' not found\n", label
);
757 /*===========================================================================*
759 *===========================================================================*/
760 PUBLIC
int do_upd_ready(message
*m_ptr
)
762 register struct rproc
*rp
;
764 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
767 who_p
= _ENDPOINT_P(m_ptr
->m_source
);
768 rp
= rproc_ptr
[who_p
];
769 result
= m_ptr
->RS_LU_RESULT
;
771 /* Make sure the originating service was requested to prepare for update. */
772 if(! (rp
->r_flags
& RS_UPDATING
) ) {
774 printf("RS: do_upd_ready: got unexpected update ready msg from %d\n",
780 /* Check if something went wrong and the service failed to prepare
781 * for the update. In that case, end the update process.
787 printf("RS: update failed: %s\n",
788 "service does not support live update");
792 printf("RS: update failed: %s\n",
793 "service does not support the required state");
797 printf("RS: update failed: %s\n",
798 "service is not able to prepare for the update now");
802 printf("RS: update failed: %s\n",
803 "a generic error occurred while preparing for the update");
807 printf("RS: update failed: %s (%d)\n",
808 "an unknown error occurred while preparing for the update\n",
816 /* Kill the process now and mark it for refresh, the new version will
817 * be automatically restarted.
819 rp
->r_flags
&= ~RS_EXITING
;
820 rp
->r_flags
|= RS_REFRESHING
;
821 kill(rp
->r_pid
, SIGKILL
);
826 /*===========================================================================*
828 *===========================================================================*/
829 PRIVATE
void update_period(message
*m_ptr
)
831 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
832 short has_update_timed_out
;
834 struct rprocpub
*rpub
;
836 rpub
= rupdate
.rp
->r_pub
;
838 /* See if a timeout has occurred. */
839 has_update_timed_out
= (now
- rupdate
.prepare_tm
> rupdate
.prepare_maxtime
);
841 /* If an update timed out, end the update process and notify the service. */
842 if(has_update_timed_out
) {
844 printf("RS: update failed: maximum prepare time reached\n");
846 /* Prepare cancel request. */
847 m
.m_type
= RS_LU_PREPARE
;
848 m
.RS_LU_STATE
= SEF_LU_STATE_NULL
;
849 asynsend(rpub
->endpoint
, &m
);
853 /*===========================================================================*
855 *===========================================================================*/
856 PRIVATE
void end_update(clock_t now
)
858 /* End the update process and mark the affected service as no longer under
859 * update. Eventual late ready to update message (if any) will simply be
860 * ignored and the service can continue executing.
861 * We reset the check timestamp, so that if the service has a period a status
862 * request will be forced in the next period.
864 rupdate
.flags
&= ~RS_UPDATING
;
865 rupdate
.rp
->r_flags
&= ~RS_UPDATING
;
866 rupdate
.rp
->r_check_tm
= 0;
869 /*===========================================================================*
871 *===========================================================================*/
872 PUBLIC
void do_exit(message
*m_ptr
)
874 register struct rproc
*rp
;
875 register struct rprocpub
*rpub
;
877 int exit_status
, r
, slot_nr
;
879 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
882 printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");
884 /* See which child exited and what the exit status is. This is done in a
885 * loop because multiple children may have exited, all reported by one
886 * SIGCHLD signal. The WNOHANG options is used to prevent blocking if,
887 * somehow, no exited child can be found.
889 while ( (exit_pid
= waitpid(-1, &exit_status
, WNOHANG
)) != 0 ) {
893 printf("RS: pid %d, ", exit_pid
);
895 if (WIFSIGNALED(exit_status
)) {
897 printf("killed, signal number %d\n", WTERMSIG(exit_status
));
900 else if (WIFEXITED(exit_status
)) {
902 printf("normal exit, status %d\n", WEXITSTATUS(exit_status
));
907 /* Read from the exec pipe */
910 r
= read(exec_pipe
[0], &slot_nr
, sizeof(slot_nr
));
915 if (r
!= sizeof(slot_nr
))
917 panic("do_exit: unaligned read from exec pipe: %d", r
);
919 printf("do_exit: got slot %d\n", slot_nr
);
920 if (slot_nr
< 0 || slot_nr
>= NR_SYS_PROCS
)
922 panic("do_exit: bad slot number from exec pipe: %d", slot_nr
);
925 rp
->r_flags
|= RS_EXITING
;
928 /* Search the system process table to see who exited.
929 * This should always succeed.
931 for (rp
=BEG_RPROC_ADDR
; rp
<END_RPROC_ADDR
; rp
++) {
933 if ((rp
->r_flags
& RS_IN_USE
) && rp
->r_pid
== exit_pid
) {
935 proc
= _ENDPOINT_P(rpub
->endpoint
);
937 rproc_ptr
[proc
] = NULL
; /* invalidate */
940 /* If PCI properties are set, inform the PCI driver. */
941 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
942 pci_del_acl(rpub
->endpoint
);
945 if ((rp
->r_flags
& RS_EXITING
) || shutting_down
) {
946 /* No reply sent to RS_DOWN yet. */
947 if(rp
->r_flags
& RS_LATEREPLY
) {
950 send(rp
->r_caller
, &rsm
);
956 else if(rp
->r_flags
& RS_REFRESHING
) {
957 short is_updating
= rp
->r_flags
& RS_UPDATING
;
960 if (rp
->r_script
[0] != '\0')
963 start_service(rp
, 0, &ep
); /* direct restart */
965 m_ptr
->RS_ENDPOINT
= ep
;
968 /* If updating, end the update process. */
971 printf("RS: update succeeded\n");
975 /* Determine what to do. If this is the first unexpected
976 * exit, immediately restart this service. Otherwise use
977 * a binary exponential backoff.
982 if (WIFSIGNALED(exit_status
)) {
983 switch(WTERMSIG(exit_status
))
985 case SIGKILL
: rp
->r_flags
|= RS_KILLED
; break;
986 default: rp
->r_flags
|= RS_SIGNALED
; break;
990 rp
->r_flags
|= RS_CRASHED
;
992 if (rp
->r_script
[0] != '\0') {
994 printf("RS: running restart script for %s\n",
997 } else if (rp
->r_restarts
> 0) {
998 printf("RS: restarting %s, restarts %d\n",
999 rp
->r_cmd
, rp
->r_backoff
);
1000 rp
->r_backoff
= 1 << MIN(rp
->r_restarts
,(BACKOFF_BITS
-2));
1001 rp
->r_backoff
= MIN(rp
->r_backoff
,MAX_BACKOFF
);
1002 if ((rpub
->sys_flags
& SF_USE_COPY
) && rp
->r_backoff
> 1)
1006 printf("RS: restarting %s\n", rp
->r_cmd
);
1007 start_service(rp
, 0, &ep
); /* direct restart */
1009 m_ptr
->RS_ENDPOINT
= ep
;
1010 /* Do this even if no I/O happens with the ioctl, in
1011 * order to disambiguate requests with DEV_IOCTL_S.
1021 /*===========================================================================*
1023 *===========================================================================*/
1024 PUBLIC
void do_period(m_ptr
)
1027 register struct rproc
*rp
;
1028 register struct rprocpub
*rpub
;
1029 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
1034 /* If an update is in progress, check its status. */
1035 if(rupdate
.flags
& RS_UPDATING
) {
1036 update_period(m_ptr
);
1039 /* Search system services table. Only check slots that are in use and not
1042 for (rp
=BEG_RPROC_ADDR
; rp
<END_RPROC_ADDR
; rp
++) {
1044 if ((rp
->r_flags
& RS_IN_USE
) && !(rp
->r_flags
& RS_UPDATING
)) {
1046 /* Compute period. */
1047 period
= rpub
->period
;
1048 if(rp
->r_flags
& RS_INITIALIZING
) {
1052 /* If the service is to be revived (because it repeatedly exited,
1053 * and was not directly restarted), the binary backoff field is
1054 * greater than zero.
1056 if (rp
->r_backoff
> 0) {
1058 if (rp
->r_backoff
== 0) {
1059 start_service(rp
, 0, &ep
);
1060 m_ptr
->RS_ENDPOINT
= ep
;
1064 /* If the service was signaled with a SIGTERM and fails to respond,
1065 * kill the system service with a SIGKILL signal.
1067 else if (rp
->r_stop_tm
> 0 && now
- rp
->r_stop_tm
> 2*RS_DELTA_T
1069 kill(rp
->r_pid
, SIGKILL
); /* terminate */
1072 /* There seems to be no special conditions. If the service has a
1073 * period assigned check its status.
1075 else if (period
> 0) {
1077 /* Check if an answer to a status request is still pending. If
1078 * the service didn't respond within time, kill it to simulate
1079 * a crash. The failure will be detected and the service will
1080 * be restarted automatically.
1082 if (rp
->r_alive_tm
< rp
->r_check_tm
) {
1083 if (now
- rp
->r_alive_tm
> 2*period
&&
1084 rp
->r_pid
> 0 && !(rp
->r_flags
& RS_NOPINGREPLY
)) {
1086 printf("RS: service %d reported late\n",
1088 rp
->r_flags
|= RS_NOPINGREPLY
;
1089 if(rp
->r_flags
& RS_INITIALIZING
) {
1090 rp
->r_flags
|= RS_EXITING
; /* don't restart */
1092 kill(rp
->r_pid
, SIGKILL
); /* simulate crash */
1096 /* No answer pending. Check if a period expired since the last
1097 * check and, if so request the system service's status.
1099 else if (now
- rp
->r_check_tm
> rpub
->period
) {
1102 printf("RS: status request sent to %d\n", rpub
->endpoint
);
1104 notify(rpub
->endpoint
); /* request status */
1105 rp
->r_check_tm
= now
; /* mark time */
1111 /* Reschedule a synchronous alarm for the next period. */
1112 if (OK
!= (s
=sys_setalarm(RS_DELTA_T
, 0)))
1113 panic("couldn't set alarm: %d", s
);
1117 /*===========================================================================*
1119 *===========================================================================*/
1120 PRIVATE
int start_service(rp
, flags
, endpoint
)
1123 endpoint_t
*endpoint
;
1125 /* Try to execute the given system service. Fork a new process. The child
1126 * process will be inhibited from running by the NO_PRIV flag. Only let the
1127 * child run once its privileges have been set by the parent.
1129 int child_proc_nr_e
, child_proc_nr_n
; /* child process slot */
1130 pid_t child_pid
; /* child's process id */
1132 int s
, use_copy
, slot_nr
, init_type
;
1133 bitchunk_t
*vm_mask
;
1135 char * null_env
= NULL
;
1136 struct rprocpub
*rpub
;
1139 use_copy
= (rpub
->sys_flags
& SF_USE_COPY
);
1141 /* See if we are not using a copy but we do need one to start the service. */
1142 if(!use_copy
&& (rpub
->sys_flags
& SF_NEED_COPY
)) {
1143 printf("RS: unable to start service %s without an in-memory copy\n",
1149 /* Now fork and branch for parent and child process (and check for error). */
1151 if(rs_verbose
) printf("RS: fork_nb..\n");
1152 child_pid
= fork_nb();
1154 if(rs_verbose
) printf("RS: fork regular..\n");
1158 switch(child_pid
) { /* see fork(2) */
1159 case -1: /* fork failed */
1160 printf("RS: warning, fork() failed: %d\n", errno
); /* shouldn't happen */
1161 return(errno
); /* return error */
1163 case 0: /* child process */
1164 /* Try to execute the binary that has an absolute path. If this fails,
1165 * e.g., because the root file system cannot be read, try to strip off
1166 * the path, and see if the command is in RS' current working dir.
1168 nice(rp
->r_nice
); /* Nice before setuid, to allow negative
1172 cpf_reload(); /* Tell kernel about grant table */
1175 execve(rp
->r_argv
[0], rp
->r_argv
, &null_env
); /* POSIX execute */
1176 file_only
= strrchr(rp
->r_argv
[0], '/') + 1;
1177 execve(file_only
, rp
->r_argv
, &null_env
); /* POSIX execute */
1179 printf("RS: exec failed for %s: %d\n", rp
->r_argv
[0], errno
);
1181 s
= write(exec_pipe
[1], &slot_nr
, sizeof(slot_nr
));
1182 if (s
!= sizeof(slot_nr
))
1183 printf("RS: write to exec pipe failed: %d/%d\n", s
, errno
);
1184 exit(1); /* terminate child */
1186 default: /* parent process */
1188 if(rs_verbose
) printf("RS: parent forked, pid %d..\n", child_pid
);
1190 child_proc_nr_e
= getnprocnr(child_pid
); /* get child slot */
1192 if(rs_verbose
) printf("RS: forked into %d..\n", child_proc_nr_e
);
1194 break; /* continue below */
1197 /* Regardless of any following failures, there is now a child process.
1198 * Update the system process table that is maintained by the RS server.
1200 child_proc_nr_n
= _ENDPOINT_P(child_proc_nr_e
);
1201 rp
->r_flags
= RS_IN_USE
| flags
; /* mark slot in use */
1202 rp
->r_restarts
+= 1; /* raise nr of restarts */
1203 rpub
->endpoint
= child_proc_nr_e
; /* set child details */
1204 rp
->r_pid
= child_pid
;
1205 rp
->r_check_tm
= 0; /* not checked yet */
1206 getuptime(&rp
->r_alive_tm
); /* currently alive */
1207 rp
->r_stop_tm
= 0; /* not exiting yet */
1208 rp
->r_backoff
= 0; /* not to be restarted */
1209 rproc_ptr
[child_proc_nr_n
] = rp
; /* mapping for fast access */
1210 rpub
->in_use
= TRUE
; /* public entry is now in use */
1212 /* If any of the calls below fail, the RS_EXITING flag is set. This implies
1213 * that the process will be removed from RS's process table once it has
1214 * terminated. The assumption is that it is not useful to try to restart the
1215 * process later in these failure cases.
1220 extern char **environ
;
1222 /* Copy the executable image into the child process. If this call
1223 * fails, the child process may or may not be killed already. If it is
1224 * not killed, it's blocked because of NO_PRIV. Kill it now either way.
1226 s
= dev_execve(child_proc_nr_e
, rp
->r_exec
, rp
->r_exec_len
, rp
->r_argv
,
1229 printf("RS: dev_execve call failed: %d\n", s
);
1230 kill(child_pid
, SIGKILL
);
1231 rp
->r_flags
|= RS_EXITING
; /* don't try again */
1236 /* Set resources when asked to. */
1237 if (rp
->r_set_resources
)
1239 /* Initialize privilege structure. */
1240 init_privs(rp
, &rp
->r_priv
);
1242 /* Tell VM about allowed calls. */
1243 vm_mask
= &rpub
->vm_call_mask
[0];
1244 if ((s
= vm_set_priv(child_proc_nr_e
, vm_mask
)) < 0) {
1245 printf("RS: vm_set_priv call failed: %d\n", s
);
1246 kill(child_pid
, SIGKILL
);
1247 rp
->r_flags
|= RS_EXITING
;
1252 /* Set and synch the privilege structure for the new service. */
1253 if ((s
= sys_privctl(child_proc_nr_e
, SYS_PRIV_SET_SYS
, &rp
->r_priv
)) != OK
1254 || (s
= sys_getpriv(&rp
->r_priv
, child_proc_nr_e
)) != OK
) {
1255 printf("RS: unable to set privileges: %d\n", s
);
1256 kill(child_pid
, SIGKILL
); /* kill the service */
1257 rp
->r_flags
|= RS_EXITING
; /* expect exit */
1258 return(s
); /* return error */
1261 /* If PCI properties are set, inform the PCI driver about the new service. */
1262 if(rpub
->pci_acl
.rsp_nr_device
|| rpub
->pci_acl
.rsp_nr_class
) {
1263 init_pci(rp
, child_proc_nr_e
);
1266 /* Publish the new system service. */
1267 s
= publish_service(rp
);
1269 printf("RS: warning: publish_service failed: %d\n", s
);
1272 /* Allow the service to run.
1273 * XXX: We should let the service run/init only after publishing information
1274 * about the new system service, but this is not currently possible due to
1275 * the blocking nature of mapdriver() that expects the service to be running.
1276 * The current solution is not race-free. This hack can go once service
1277 * publishing is made fully asynchronous in RS.
1279 if ((s
= sys_privctl(child_proc_nr_e
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
1280 printf("RS: unable to allow the service to run: %d\n", s
);
1281 kill(child_pid
, SIGKILL
); /* kill the service */
1282 rp
->r_flags
|= RS_EXITING
; /* expect exit */
1283 return(s
); /* return error */
1286 /* Initialize service. */
1287 init_type
= rp
->r_restarts
> 0 ? SEF_INIT_RESTART
: SEF_INIT_FRESH
;
1288 if((s
= init_service(rp
, init_type
)) != OK
) {
1289 panic("unable to initialize service: %d", s
);
1292 /* The purpose of non-blocking forks is to avoid involving VFS in the forking
1293 * process, because VFS may be blocked on a sendrec() to a MFS that is
1294 * waiting for a endpoint update for a dead driver. We have just published
1295 * that update, but VFS may still be blocked. As a result, VFS may not yet
1296 * have received PM's fork message. Hence, if we call mapdriver()
1297 * immediately, VFS may not know about the process and thus refuse to add the
1298 * driver entry. The following temporary hack works around this by forcing
1299 * blocking communication from PM to VFS. Once VFS has been made non-blocking
1300 * towards MFS instances, this hack and the entire fork_nb() call can go.
1305 /* Map the new service. */
1306 if (rpub
->dev_nr
> 0) { /* set driver map */
1307 if ((s
=mapdriver(rpub
->label
,
1308 rpub
->dev_nr
, rpub
->dev_style
, !!use_copy
/* force */)) < 0) {
1309 printf("RS: couldn't map driver (continuing): %d\n", errno
);
1314 printf("RS: started '%s', major %d, pid %d, endpoint %d, proc %d\n",
1315 rp
->r_cmd
, rpub
->dev_nr
, child_pid
,
1316 child_proc_nr_e
, child_proc_nr_n
);
1318 /* The system service now has been successfully started. The only thing
1319 * that can go wrong now, is that execution fails at the child. If that's
1320 * the case, the child will exit.
1322 if(endpoint
) *endpoint
= child_proc_nr_e
; /* send back child endpoint */
1327 /*===========================================================================*
1329 *===========================================================================*/
1330 PRIVATE
void stop_service(struct rproc
*rp
,int how
)
1332 /* Try to stop the system service. First send a SIGTERM signal to ask the
1333 * system service to terminate. If the service didn't install a signal
1334 * handler, it will be killed. If it did and ignores the signal, we'll
1335 * find out because we record the time here and send a SIGKILL.
1337 if(rs_verbose
) printf("RS tries to stop %s (pid %d)\n", rp
->r_cmd
, rp
->r_pid
);
1339 rp
->r_flags
|= how
; /* what to on exit? */
1340 if(rp
->r_pid
> 0) kill(rp
->r_pid
, SIGTERM
); /* first try friendly */
1341 else if(rs_verbose
) printf("RS: no process to kill\n");
1342 getuptime(&rp
->r_stop_tm
); /* record current time */
1346 /*===========================================================================*
1348 *===========================================================================*/
1349 PUBLIC
int do_getsysinfo(m_ptr
)
1352 vir_bytes src_addr
, dst_addr
;
1357 /* This call requires special privileges. */
1358 if (!caller_is_root(m_ptr
->m_source
)) return(EPERM
);
1360 switch(m_ptr
->m1_i1
) {
1362 src_addr
= (vir_bytes
) rproc
;
1363 len
= sizeof(struct rproc
) * NR_SYS_PROCS
;
1365 case SI_PROCPUB_TAB
:
1366 src_addr
= (vir_bytes
) rprocpub
;
1367 len
= sizeof(struct rprocpub
) * NR_SYS_PROCS
;
1373 dst_proc
= m_ptr
->m_source
;
1374 dst_addr
= (vir_bytes
) m_ptr
->m1_p1
;
1375 if (OK
!= (s
=sys_datacopy(SELF
, src_addr
, dst_proc
, dst_addr
, len
)))
1380 /*===========================================================================*
1382 *===========================================================================*/
1383 PRIVATE pid_t
fork_nb()
1387 return(_syscall(PM_PROC_NR
, FORK_NB
, &m
));
1390 /*===========================================================================*
1392 *===========================================================================*/
1393 PRIVATE
int share_exec(rp_dst
, rp_src
)
1394 struct rproc
*rp_dst
, *rp_src
;
1396 struct rprocpub
*rpub_src
;
1397 struct rprocpub
*rpub_dst
;
1399 rpub_src
= rp_src
->r_pub
;
1400 rpub_dst
= rp_dst
->r_pub
;
1403 printf("RS: share_exec: sharing exec image from %s to %s\n",
1404 rpub_src
->label
, rpub_dst
->label
);
1407 /* Share exec image from rp_src to rp_dst. */
1408 rp_dst
->r_exec_len
= rp_src
->r_exec_len
;
1409 rp_dst
->r_exec
= rp_src
->r_exec
;
1414 /*===========================================================================*
1416 *===========================================================================*/
1417 PRIVATE
int read_exec(rp
)
1424 e_name
= rp
->r_argv
[0];
1426 printf("RS: read_exec: copying exec image from: %s\n", e_name
);
1429 r
= stat(e_name
, &sb
);
1433 fd
= open(e_name
, O_RDONLY
);
1437 rp
->r_exec_len
= sb
.st_size
;
1438 rp
->r_exec
= malloc(rp
->r_exec_len
);
1439 if (rp
->r_exec
== NULL
)
1441 printf("RS: read_exec: unable to allocate %d bytes\n",
1447 r
= read(fd
, rp
->r_exec
, rp
->r_exec_len
);
1450 if (r
== rp
->r_exec_len
)
1453 printf("RS: read_exec: read failed %d, errno %d\n", r
, e
);
1464 /*===========================================================================*
1466 *===========================================================================*/
1467 PRIVATE
void free_slot(rp
)
1470 int slot_nr
, has_shared_exec
;
1471 struct rprocpub
*rpub
;
1472 struct rproc
*other_rp
;
1476 /* Free memory if necessary. */
1477 if(rpub
->sys_flags
& SF_USE_COPY
) {
1478 /* Search for some other slot sharing the same exec image. */
1479 has_shared_exec
= FALSE
;
1480 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
; slot_nr
++) {
1481 other_rp
= &rproc
[slot_nr
]; /* get pointer to slot */
1482 if (other_rp
->r_flags
& RS_IN_USE
&& other_rp
!= rp
1483 && other_rp
->r_exec
== rp
->r_exec
) { /* found! */
1484 has_shared_exec
= TRUE
;
1488 /* If nobody uses our copy of the exec image, we can get rid of it. */
1489 if(!has_shared_exec
) {
1491 printf("RS: free_slot: free exec image from %s\n",
1500 /* Mark slot as no longer in use.. */
1502 rpub
->in_use
= FALSE
;
1503 rproc_ptr
[_ENDPOINT_P(rpub
->endpoint
)] = NULL
;
1506 /*===========================================================================*
1508 *===========================================================================*/
1509 PRIVATE
void run_script(rp
)
1515 char incarnation_str
[20]; /* Enough for a counter? */
1516 char *envp
[1] = { NULL
};
1517 struct rprocpub
*rpub
;
1520 if (rp
->r_flags
& RS_REFRESHING
)
1522 else if (rp
->r_flags
& RS_NOPINGREPLY
)
1523 reason
= "no-heartbeat";
1524 else if (rp
->r_flags
& RS_KILLED
)
1526 else if (rp
->r_flags
& RS_CRASHED
)
1528 else if (rp
->r_flags
& RS_SIGNALED
)
1533 "RS: run_script: can't find reason for termination of '%s'\n",
1537 sprintf(incarnation_str
, "%d", rp
->r_restarts
);
1540 printf("RS: calling script '%s'\n", rp
->r_script
);
1541 printf("RS: sevice name: '%s'\n", rpub
->label
);
1542 printf("RS: reason: '%s'\n", reason
);
1543 printf("RS: incarnation: '%s'\n", incarnation_str
);
1550 printf("RS: run_script: fork failed: %s\n", strerror(errno
));
1553 execle(rp
->r_script
, rp
->r_script
, rpub
->label
, reason
,
1554 incarnation_str
, NULL
, envp
);
1555 printf("RS: run_script: execl '%s' failed: %s\n",
1556 rp
->r_script
, strerror(errno
));
1559 /* Set the privilege structure for the child process. */
1560 endpoint
= getnprocnr(pid
);
1561 if ((r
= sys_privctl(endpoint
, SYS_PRIV_SET_USER
, NULL
))
1563 printf("RS: run_script: can't set privileges: %d\n",r
);
1565 /* Allow the service to run. */
1566 if ((r
= sys_privctl(endpoint
, SYS_PRIV_ALLOW
, NULL
)) != OK
) {
1567 printf("RS: run_script: process can't run: %d\n",r
);
1569 /* Do not wait for the child */
1575 /*===========================================================================*
1577 *===========================================================================*/
1578 PRIVATE
char *get_next_label(ptr
, label
, caller_label
)
1583 /* Get the next label from the list of (IPC) labels.
1588 for (p
= ptr
; p
[0] != '\0'; p
= q
)
1590 /* Skip leading space */
1591 while (p
[0] != '\0' && isspace((unsigned char)p
[0]))
1594 /* Find start of next word */
1596 while (q
[0] != '\0' && !isspace((unsigned char)q
[0]))
1601 if (len
> RS_MAX_LABEL_LEN
)
1604 "rs:get_next_label: bad ipc list entry '.*s' for %s: too long\n",
1605 len
, p
, caller_label
);
1608 memcpy(label
, p
, len
);
1611 return q
; /* found another */
1614 return NULL
; /* done */
1617 /*===========================================================================*
1619 *===========================================================================*/
1620 PRIVATE
void add_forward_ipc(rp
, privp
)
1624 /* Add IPC send permissions to a process based on that process's IPC
1627 char label
[RS_MAX_LABEL_LEN
+1], *p
;
1628 struct rproc
*tmp_rp
;
1629 struct rprocpub
*tmp_rpub
;
1630 endpoint_t endpoint
;
1632 int slot_nr
, priv_id
;
1634 struct rprocpub
*rpub
;
1639 while ((p
= get_next_label(p
, label
, rpub
->label
)) != NULL
) {
1641 if (strcmp(label
, "SYSTEM") == 0)
1643 else if (strcmp(label
, "USER") == 0)
1644 endpoint
= INIT_PROC_NR
; /* all user procs */
1645 else if (strcmp(label
, "PM") == 0)
1646 endpoint
= PM_PROC_NR
;
1647 else if (strcmp(label
, "VFS") == 0)
1648 endpoint
= FS_PROC_NR
;
1649 else if (strcmp(label
, "RS") == 0)
1650 endpoint
= RS_PROC_NR
;
1651 else if (strcmp(label
, "LOG") == 0)
1652 endpoint
= LOG_PROC_NR
;
1653 else if (strcmp(label
, "TTY") == 0)
1654 endpoint
= TTY_PROC_NR
;
1655 else if (strcmp(label
, "DS") == 0)
1656 endpoint
= DS_PROC_NR
;
1657 else if (strcmp(label
, "VM") == 0)
1658 endpoint
= VM_PROC_NR
;
1661 /* Try to find process */
1662 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
;
1665 tmp_rp
= &rproc
[slot_nr
];
1666 if (!(tmp_rp
->r_flags
& RS_IN_USE
))
1668 tmp_rpub
= tmp_rp
->r_pub
;
1669 if (strcmp(tmp_rpub
->label
, label
) == 0)
1672 if (slot_nr
>= NR_SYS_PROCS
)
1676 "add_forward_ipc: unable to find '%s'\n", label
);
1679 endpoint
= tmp_rpub
->endpoint
;
1682 if ((r
= sys_getpriv(&priv
, endpoint
)) < 0)
1685 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1690 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1695 /*===========================================================================*
1696 * add_backward_ipc *
1697 *===========================================================================*/
1698 PRIVATE
void add_backward_ipc(rp
, privp
)
1702 /* Add IPC send permissions to a process based on other processes' IPC
1703 * lists. This is enough to allow each such two processes to talk to
1704 * each other, as the kernel guarantees send mask symmetry. We need to
1705 * add these permissions now because the current process may not yet
1706 * have existed at the time that the other process was initialized.
1708 char label
[RS_MAX_LABEL_LEN
+1], *p
;
1710 struct rprocpub
*rrpub
;
1713 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
1714 if (!(rrp
->r_flags
& RS_IN_USE
))
1717 /* If an IPC target list was provided for the process being
1718 * checked here, make sure that the label of the new process
1719 * is in that process's list.
1721 if (rrp
->r_ipc_list
[0]) {
1725 p
= rrp
->r_ipc_list
;
1727 while ((p
= get_next_label(p
, label
,
1728 rrpub
->label
)) != NULL
) {
1729 if (!strcmp(rrpub
->label
, label
)) {
1739 priv_id
= rrp
->r_priv
.s_id
;
1741 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1746 /*===========================================================================*
1748 *===========================================================================*/
1749 PRIVATE
void init_privs(rp
, privp
)
1753 int i
, src_bits_per_word
, dst_bits_per_word
, src_word
, dst_word
,
1757 /* Clear s_k_call_mask */
1758 memset(privp
->s_k_call_mask
, '\0', sizeof(privp
->s_k_call_mask
));
1760 src_bits_per_word
= 8*sizeof(rp
->r_call_mask
[0]);
1761 dst_bits_per_word
= 8*sizeof(privp
->s_k_call_mask
[0]);
1762 for (src_word
= 0; src_word
< RS_SYS_CALL_MASK_SIZE
; src_word
++)
1764 for (src_bit
= 0; src_bit
< src_bits_per_word
; src_bit
++)
1766 mask
= (1UL << src_bit
);
1767 if (!(rp
->r_call_mask
[src_word
] & mask
))
1769 call_nr
= src_word
*src_bits_per_word
+src_bit
;
1772 printf("RS: init_privs: system call %d\n", call_nr
);
1774 dst_word
= call_nr
/ dst_bits_per_word
;
1775 mask
= (1UL << (call_nr
% dst_bits_per_word
));
1776 if (dst_word
>= SYS_CALL_MASK_SIZE
)
1779 "RS: init_privs: call number %d doesn't fit\n",
1782 privp
->s_k_call_mask
[dst_word
] |= mask
;
1786 /* Clear s_ipc_to */
1787 memset(&privp
->s_ipc_to
, '\0', sizeof(privp
->s_ipc_to
));
1789 if (strlen(rp
->r_ipc_list
) != 0)
1791 add_forward_ipc(rp
, privp
);
1792 add_backward_ipc(rp
, privp
);
1797 for (i
= 0; i
<NR_SYS_PROCS
; i
++)
1799 if (i
!= USER_PRIV_ID
)
1800 set_sys_bit(privp
->s_ipc_to
, i
);
1805 /*===========================================================================*
1807 *===========================================================================*/
1808 PRIVATE
void init_pci(rp
, endpoint
)
1812 /* Inform the PCI driver about the new service. */
1815 struct rs_pci rs_pci
;
1816 struct rprocpub
*rpub
;
1819 rs_pci
= rpub
->pci_acl
;
1820 strcpy(rs_pci
.rsp_label
, rpub
->label
);
1821 rs_pci
.rsp_endpoint
= endpoint
;
1824 printf("RS: init_pci: calling pci_set_acl\n");
1826 r
= pci_set_acl(&rs_pci
);
1829 printf("RS: init_pci: after pci_set_acl\n");
1833 printf("RS: init_pci: pci_set_acl failed: %s\n",
1839 /*===========================================================================*
1841 *===========================================================================*/
1842 PUBLIC
int do_lookup(m_ptr
)
1845 static char namebuf
[100];
1848 struct rprocpub
*rrpub
;
1850 len
= m_ptr
->RS_NAME_LEN
;
1852 if(len
< 2 || len
>= sizeof(namebuf
)) {
1853 printf("RS: len too weird (%d)\n", len
);
1857 if((r
=sys_vircopy(m_ptr
->m_source
, D
, (vir_bytes
) m_ptr
->RS_NAME
,
1858 SELF
, D
, (vir_bytes
) namebuf
, len
)) != OK
) {
1859 printf("RS: name copy failed\n");
1864 namebuf
[len
] = '\0';
1866 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
1867 if (!(rrp
->r_flags
& RS_IN_USE
))
1870 if (!strcmp(rrpub
->label
, namebuf
)) {
1871 m_ptr
->RS_ENDPOINT
= rrpub
->endpoint
;