From: Philip Homburg Date: Mon, 23 Apr 2007 14:47:04 +0000 (+0000) Subject: Report and detect exec failures using a pipe. X-Git-Tag: v3.1.4~404 X-Git-Url: http://zhaoyanbai.com/repos/zlib_tech.html?a=commitdiff_plain;h=b613f5cb4b7d324149dc585ad57ab31de81057fe;p=minix.git Report and detect exec failures using a pipe. XXX Hardcoded values for s_ipc_to and s_ipc_sendrec. --- diff --git a/servers/rs/manager.c b/servers/rs/manager.c index 42449205b..fce3fcaf8 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -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; rpr_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; is_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; is_ipc_sendrec)*8; i++) + { + chunk= (i / (sizeof(bitchunk_t)*8)); + bit= (i % (sizeof(bitchunk_t)*8)); + privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit); + } + } }