Report and detect exec failures using a pipe.

XXX Hardcoded values for s_ipc_to and s_ipc_sendrec.
This commit is contained in:
Philip Homburg 2007-04-23 14:47:04 +00:00
parent 727ce18aa8
commit b613f5cb4b

View file

@ -33,8 +33,6 @@ FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
PRIVATE int shutting_down = FALSE;
#define EXEC_FAILED 49 /* recognizable status */
extern int rs_verbose;
/*===========================================================================*
@ -166,9 +164,14 @@ message *m_ptr; /* request message pointer */
/* See if there is a free entry in the table with system processes. */
for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
rp = &rproc[slot_nr]; /* get pointer to slot */
if (! rp->r_flags & RS_IN_USE) /* check if available */
if (!(rp->r_flags & RS_IN_USE)) /* check if available */
break;
}
if (slot_nr >= NR_SYS_PROCS)
{
printf("rs`do_start: driver table full\n");
return ENOMEM;
}
/* Obtain command name and parameters. This is a space-separated string
* that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
@ -422,7 +425,7 @@ PUBLIC int do_restart(message *m_ptr)
label[len]= '\0';
for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
if ((rp->r_flags & RS_IN_USE) && strcmp(rp->r_label, label) == 0) {
if(rs_verbose) printf("RS: restarting '%s' (%d)\n", label, rp->r_pid);
if (rp->r_pid >= 0)
{
@ -433,6 +436,7 @@ PUBLIC int do_restart(message *m_ptr)
}
rp->r_flags &= ~(RS_EXITING|RS_REFRESHING|RS_NOPINGREPLY);
r = start_service(rp, 0, &ep);
if (r != OK) printf("do_restart: start_service failed: %d\n", r);
m_ptr->RS_ENDPOINT = ep;
return(r);
}
@ -495,7 +499,7 @@ PUBLIC void do_exit(message *m_ptr)
{
register struct rproc *rp;
pid_t exit_pid;
int exit_status, r;
int exit_status, r, slot_nr;
endpoint_t ep;
if(rs_verbose)
@ -518,6 +522,32 @@ PUBLIC void do_exit(message *m_ptr)
}
}
/* Read from the exec pipe */
for (;;)
{
r= read(exec_pipe[0], &slot_nr, sizeof(slot_nr));
if (r == -1)
{
if (errno == -EAGAIN) /* Negative error defines */
break; /* No data */
panic("RS", "do_exit: read from exec pipe failed",
errno);
}
if (r != sizeof(slot_nr))
{
panic("RS", "do_exit: unaligned read from exec pipe",
r);
}
printf("do_exit: got slot %d\n", slot_nr);
if (slot_nr < 0 || slot_nr >= NR_SYS_PROCS)
{
panic("RS", "do_exit: bad slot number from exec pipe",
slot_nr);
}
rp= &rproc[slot_nr];
rp->r_flags |= RS_EXECFAILED;
}
/* Search the system process table to see who exited.
* This should always succeed.
*/
@ -529,6 +559,8 @@ PUBLIC void do_exit(message *m_ptr)
rproc_ptr[proc] = NULL; /* invalidate */
rp->r_pid= -1;
pci_del_acl(rp->r_proc_nr_e); /* Ignore errors */
if ((rp->r_flags & RS_EXITING) || shutting_down) {
/* No reply sent to RS_DOWN yet. */
if(rp->r_flags & RS_LATEREPLY) {
@ -556,8 +588,7 @@ PUBLIC void do_exit(message *m_ptr)
m_ptr->RS_ENDPOINT = ep;
}
}
else if (WIFEXITED(exit_status) &&
WEXITSTATUS(exit_status) == EXEC_FAILED) {
else if (rp->r_flags & RS_EXECFAILED) {
rp->r_flags = 0; /* release slot */
}
else {
@ -574,7 +605,7 @@ rp->r_restarts= 0;
switch(WTERMSIG(exit_status))
{
case SIGKILL: rp->r_flags |= RS_KILLED; break;
default: rp->r_flags |= RS_CRASHED; break;
default: rp->r_flags |= RS_SIGNALED; break;
}
}
else
@ -692,7 +723,7 @@ endpoint_t *endpoint;
int child_proc_nr_e, child_proc_nr_n; /* child process slot */
pid_t child_pid; /* child's process id */
char *file_only;
int s, use_copy;
int s, use_copy, slot_nr;
struct priv *privp;
message m;
@ -718,6 +749,7 @@ endpoint_t *endpoint;
* nice values.
*/
setuid(rp->r_uid);
cpf_reload(); /* Tell kernel about grant table */
if (!use_copy)
{
execve(rp->r_argv[0], rp->r_argv, NULL); /* POSIX execute */
@ -725,7 +757,11 @@ endpoint_t *endpoint;
execve(file_only, rp->r_argv, NULL); /* POSIX execute */
}
printf("RS: exec failed for %s: %d\n", rp->r_argv[0], errno);
exit(EXEC_FAILED); /* terminate child */
slot_nr= rp-rproc;
s= write(exec_pipe[1], &slot_nr, sizeof(slot_nr));
if (s != sizeof(slot_nr))
printf("RS: write to exec pipe failed: %d/%d\n", s, errno);
exit(1); /* terminate child */
default: /* parent process */
child_proc_nr_e = getnprocnr(child_pid); /* get child slot */
@ -914,6 +950,8 @@ struct rproc *rp;
reason= "killed";
else if (rp->r_flags & RS_CRASHED)
reason= "crashed";
else if (rp->r_flags & RS_SIGNALED)
reason= "signaled";
else
{
printf(
@ -969,8 +1007,9 @@ struct rproc *rp;
struct priv *privp;
{
int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
src_bit, call_nr;
src_bit, call_nr, chunk, bit, priv_id, slot_nr;
unsigned long mask;
struct rproc *tmp_rp;
/* Clear s_k_call_mask */
memset(privp->s_k_call_mask, '\0', sizeof(privp->s_k_call_mask));
@ -998,6 +1037,144 @@ struct priv *privp;
privp->s_k_call_mask[dst_word] |= mask;
}
}
/* Clear s_ipc_to and s_ipc_sendrec */
memset(&privp->s_ipc_to, '\0', sizeof(privp->s_ipc_to));
memset(&privp->s_ipc_sendrec, '\0', sizeof(privp->s_ipc_sendrec));
if (strcmp(rp->r_label, "dp8390") == 0)
{
printf("init_privs: special code for dp8390\n");
/* Try to find inet */
for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++)
{
tmp_rp = &rproc[slot_nr];
if (!(tmp_rp->r_flags & RS_IN_USE))
continue;
if (strcmp(tmp_rp->r_label, "inet") == 0)
break;
}
if (slot_nr >= NR_SYS_PROCS)
{
printf("init_privs: unable to find inet\n");
return;
}
priv_id= sys_getprivid(tmp_rp->r_proc_nr_e);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for inet: %d\n",
priv_id);
return;
}
chunk= (priv_id / (sizeof(bitchunk_t)*8));
bit= (priv_id % (sizeof(bitchunk_t)*8));
privp->s_ipc_to.chunk[chunk] |= (1 << bit);
priv_id= sys_getprivid(RS_PROC_NR);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for RS: %d\n",
priv_id);
return;
}
chunk= (priv_id / (sizeof(bitchunk_t)*8));
bit= (priv_id % (sizeof(bitchunk_t)*8));
privp->s_ipc_to.chunk[chunk] |= (1 << bit);
priv_id= sys_getprivid(SYSTEM);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for SYSTEM: %d\n",
priv_id);
return;
}
chunk= (priv_id / (sizeof(bitchunk_t)*8));
bit= (priv_id % (sizeof(bitchunk_t)*8));
privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
priv_id= sys_getprivid(PM_PROC_NR);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for PM: %d\n",
priv_id);
return;
}
chunk= (priv_id / (sizeof(bitchunk_t)*8));
bit= (priv_id % (sizeof(bitchunk_t)*8));
privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
priv_id= sys_getprivid(LOG_PROC_NR);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for LOG: %d\n",
priv_id);
return;
}
chunk= (priv_id / (sizeof(bitchunk_t)*8));
bit= (priv_id % (sizeof(bitchunk_t)*8));
privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
priv_id= sys_getprivid(TTY_PROC_NR);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for TTY: %d\n",
priv_id);
return;
}
chunk= (priv_id / (sizeof(bitchunk_t)*8));
bit= (priv_id % (sizeof(bitchunk_t)*8));
privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
/* Try to find PCI */
for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++)
{
tmp_rp = &rproc[slot_nr];
if (!(tmp_rp->r_flags & RS_IN_USE))
continue;
if (strcmp(tmp_rp->r_label, "pci") == 0)
break;
}
if (slot_nr >= NR_SYS_PROCS)
{
printf("init_privs: unable to find PCI\n");
return;
}
priv_id= sys_getprivid(tmp_rp->r_proc_nr_e);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for PCI: %d\n",
priv_id);
return;
}
chunk= (priv_id / (sizeof(bitchunk_t)*8));
bit= (priv_id % (sizeof(bitchunk_t)*8));
privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
}
else
{
for (i= 0; i<sizeof(privp->s_ipc_to)*8; i++)
{
chunk= (i / (sizeof(bitchunk_t)*8));
bit= (i % (sizeof(bitchunk_t)*8));
privp->s_ipc_to.chunk[chunk] |= (1 << bit);
}
for (i= 0; i<sizeof(privp->s_ipc_sendrec)*8; i++)
{
chunk= (i / (sizeof(bitchunk_t)*8));
bit= (i % (sizeof(bitchunk_t)*8));
privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit);
}
}
}