From: Philip Homburg Date: Thu, 21 Feb 2008 16:20:22 +0000 (+0000) Subject: Support for restricting limiting IPC to a set of endpoints. Not enabled by X-Git-Tag: v3.1.4~286 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=ca8291c815446103107bf883bcee2dd4f79ff6d1;p=minix.git Support for restricting limiting IPC to a set of endpoints. Not enabled by default, pass -i to service. Do not reply to bogus request types. Reply using sendnb. --- diff --git a/servers/rs/main.c b/servers/rs/main.c index 74eff80e4..c201d0eb6 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -81,13 +81,21 @@ PUBLIC int main(void) /* If this is not a notification message, it is a normal request. * Handle the request and send a reply to the caller. */ - else { + else { + if (call_nr < RS_RQ_BASE || call_nr >= RS_RQ_BASE+0x100) + { + /* Ignore invalid requests. Do not try to reply. */ + printf("RS: got invalid request %d from endpoint %d\n", + call_nr, m.m_source); + continue; + } + /* Only root can make calls to rs */ euid= getpeuid(m.m_source); if (euid != 0) { - printf("RS: got unauthorized request from endpoint %d\n", - m.m_source); + printf("RS: got unauthorized request %d from endpoint %d\n", + call_nr, m.m_source); m.m_type = EPERM; reply(who_e, &m); continue; @@ -203,12 +211,11 @@ PRIVATE void reply(who, m_out) int who; /* replyee */ message *m_out; /* reply message */ { - /*message m_out;*/ /* reply message */ int s; /* send status */ - /*m_out.m_type = result;*/ /* build reply message */ - if (OK != (s=send(who, m_out))) /* send the message */ - panic("RS", "unable to send reply", s); + s = sendnb(who, m_out); /* send the message */ + if (s != OK) + printf("RS: unable to send reply to %d: %d\n", who, s); } diff --git a/servers/rs/manager.c b/servers/rs/manager.c index 457bafdef..0b7495734 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -4,6 +4,7 @@ */ #include "inc.h" +#include #include #include #include @@ -260,6 +261,21 @@ message *m_ptr; /* request message pointer */ rp->r_uid= rs_start.rss_uid; rp->r_nice= rs_start.rss_nice; + if (rs_start.rss_flags & RF_IPC_VALID) + { + if (rs_start.rss_ipclen+1 > sizeof(rp->r_ipc_list)) + { + printf("rs: ipc list too long for '%s'\n", rp->r_label); + return EINVAL; + } + s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_ipc, + SELF, (vir_bytes) rp->r_ipc_list, rs_start.rss_ipclen); + if (s != OK) return(s); + rp->r_ipc_list[rs_start.rss_ipclen]= '\0'; + } + else + rp->r_ipc_list[0]= '\0'; + rp->r_exec= NULL; if (rs_start.rss_flags & RF_COPY) { @@ -806,11 +822,13 @@ endpoint_t *endpoint; if (rp->r_dev_nr > 0) { /* set driver map */ if ((s=mapdriver5(rp->r_label, strlen(rp->r_label), rp->r_dev_nr, rp->r_dev_style, !!use_copy /* force */)) < 0) { - report("RS", "couldn't map driver", errno); + report("RS", "couldn't map driver (continuing)", errno); +#if 0 rp->r_flags |= RS_EXITING; /* expect exit */ if(child_pid > 0) kill(child_pid, SIGKILL); /* kill driver */ else report("RS", "didn't kill pid", child_pid); return(s); /* return error */ +#endif } } @@ -970,7 +988,7 @@ struct rproc *rp; sprintf(incarnation_str, "%d", rp->r_restarts); if(rs_verbose) { - printf("RS: should call script '%s'\n", rp->r_script); + printf("RS: calling script '%s'\n", rp->r_script); printf("RS: sevice name: '%s'\n", rp->r_label); printf("RS: reason: '%s'\n", reason); printf("RS: incarnation: '%s'\n", incarnation_str); @@ -1016,8 +1034,12 @@ struct priv *privp; { int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word, src_bit, call_nr, chunk, bit, priv_id, slot_nr; + endpoint_t proc_nr_e; + size_t len; unsigned long mask; + char *p, *q; struct rproc *tmp_rp; + char label[MAX_LABEL_LEN+1]; /* Clear s_k_call_mask */ memset(privp->s_k_call_mask, '\0', sizeof(privp->s_k_call_mask)); @@ -1050,123 +1072,80 @@ struct priv *privp; 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) + if (strlen(rp->r_ipc_list) != 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) + for (p= rp->r_ipc_list; p[0] != '\0'; p= q) { - 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; - } + /* Skip leading space */ + while (p[0] != '\0' && isspace((unsigned char)p[0])) + p++; + + /* Find start of next word */ + q= p; + while (q[0] != '\0' && !isspace((unsigned char)q[0])) + q++; + if (q == p) + continue; + len= q-p; + if (len+1 > sizeof(label)) + { + printf( + "rs:init_privs: bad ipc list entry '.*s' for %s: too long\n", + len, p, rp->r_label); + continue; + } + memcpy(label, p, len); + label[len]= '\0'; + + if (strcmp(label, "SYSTEM") == 0) + proc_nr_e= SYSTEM; + else if (strcmp(label, "PM") == 0) + proc_nr_e= PM_PROC_NR; + else if (strcmp(label, "VFS") == 0) + proc_nr_e= FS_PROC_NR; + else if (strcmp(label, "RS") == 0) + proc_nr_e= RS_PROC_NR; + else if (strcmp(label, "LOG") == 0) + proc_nr_e= LOG_PROC_NR; + else if (strcmp(label, "TTY") == 0) + proc_nr_e= TTY_PROC_NR; + else if (strcmp(label, "DS") == 0) + proc_nr_e= DS_PROC_NR; + else + { + /* Try to find process */ + 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, label) == 0) + break; + } + if (slot_nr >= NR_SYS_PROCS) + { + printf( + "init_privs: unable to find '%s'\n", + label); + continue; + } + proc_nr_e= tmp_rp->r_proc_nr_e; + } - 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; + priv_id= sys_getprivid(proc_nr_e); + if (priv_id < 0) + { + printf( + "init_privs: unable to get priv_id for '%s': %d\n", + label, priv_id); + continue; + } + chunk= (priv_id / (sizeof(bitchunk_t)*8)); + bit= (priv_id % (sizeof(bitchunk_t)*8)); + privp->s_ipc_to.chunk[chunk] |= (1 << bit); + privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit); } - chunk= (priv_id / (sizeof(bitchunk_t)*8)); - bit= (priv_id % (sizeof(bitchunk_t)*8)); - privp->s_ipc_sendrec.chunk[chunk] |= (1 << bit); } else { diff --git a/servers/rs/manager.h b/servers/rs/manager.h index 642bbc2e1..817f6d4e5 100644 --- a/servers/rs/manager.h +++ b/servers/rs/manager.h @@ -15,6 +15,9 @@ #define MAX_NR_PCI_ID 4 /* maximum number of PCI device IDs */ #define MAX_NR_PCI_CLASS 4 /* maximum number of PCI class IDs */ #define MAX_NR_SYSTEM 2 /* should match RSS_NR_SYSTEM */ +#define MAX_IPC_LIST 256 /* Max size of list for IPC target + * process names + */ /* Definition of the system process table. This table only has entries for * the servers and drivers, and thus is not directly indexed by slot number. @@ -57,6 +60,7 @@ extern struct rproc { struct { u32_t class; u32_t mask; } r_pci_class[MAX_NR_PCI_CLASS]; u32_t r_call_mask[MAX_NR_SYSTEM]; + char r_ipc_list[MAX_IPC_LIST]; } rproc[NR_SYS_PROCS]; /* Mapping for fast access to the system process table. */ diff --git a/servers/rs/service.c b/servers/rs/service.c index 79dd9fd74..acab09dda 100644 --- a/servers/rs/service.c +++ b/servers/rs/service.c @@ -87,6 +87,7 @@ PRIVATE int req_major; PRIVATE long req_period; PRIVATE char *req_script; PRIVATE char *req_label; +PRIVATE char *req_ipc; PRIVATE char *req_config = PATH_CONFIG; PRIVATE int req_printep; PRIVATE int class_recurs; /* Nesting level of class statements */ @@ -133,9 +134,10 @@ PRIVATE int parse_arguments(int argc, char **argv) int req_nr; int c, i; int c_flag; + int i_flag=0; c_flag= 0; - while (c= getopt(argc, argv, "c?"), c != -1) + while (c= getopt(argc, argv, "ci?"), c != -1) { switch(c) { @@ -145,6 +147,9 @@ PRIVATE int parse_arguments(int argc, char **argv) case 'c': c_flag= 1; break; + case 'i': + i_flag= 1; + break; default: fprintf(stderr, "%s: getopt failed: %c\n", argv[ARG_NAME], c); @@ -184,6 +189,8 @@ PRIVATE int parse_arguments(int argc, char **argv) rs_start.rss_flags= 0; if (c_flag) rs_start.rss_flags |= RF_COPY; + if (i_flag) + rs_start.rss_flags |= RF_IPC_VALID; if (do_run) { @@ -308,6 +315,7 @@ PRIVATE void fatal(char *fmt, ...) #define KW_DEVICE "device" #define KW_CLASS "class" #define KW_SYSTEM "system" +#define KW_IPC "ipc" FORWARD void do_driver(config_t *cpe, config_t *config); @@ -673,9 +681,57 @@ struct { "SETGRANT", SYS_SETGRANT }, { "READBIOS", SYS_READBIOS }, { "VM_MAP", SYS_VM_MAP }, + { "MAPDMAx", SYS_MAPDMAx }, { NULL, 0 } }; +PRIVATE void do_ipc(config_t *cpe) +{ + char *list; + size_t listsize, wordlen; + + list= NULL; + listsize= 1; + list= malloc(listsize); + if (list == NULL) + fatal("do_ipc: unable to malloc %d bytes", listsize); + list[0]= '\0'; + + /* Process a list of process names that are allowed to be + * contacted + */ + for (; cpe; cpe= cpe->next) + { + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_ipc: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_ipc: unexpected string at %s:%d", + cpe->file, cpe->line); + } + + wordlen= strlen(cpe->word); + + listsize += 1 + wordlen; + list= realloc(list, listsize); + if (list == NULL) + { + fatal("do_ipc: unable to realloc %d bytes", + listsize); + } + strcat(list, " "); + strcat(list, cpe->word); + } + printf("do_ipc: got list '%s'\n", list); + + if (req_ipc) + fatal("do_ipc: req_ipc is set"); + req_ipc= list; +} + PRIVATE void do_system(config_t *cpe) { int i, call_nr, word, bits_per_word; @@ -802,6 +858,11 @@ PRIVATE void do_driver(config_t *cpe, config_t *config) do_system(cpe->next); continue; } + if (strcmp(cpe->word, KW_IPC) == 0) + { + do_ipc(cpe->next); + continue; + } } } @@ -941,6 +1002,17 @@ PUBLIC int main(int argc, char **argv) do_config(progname, req_config); } + if (req_ipc) + { + rs_start.rss_ipc= req_ipc+1; /* Skip initial space */ + rs_start.rss_ipclen= strlen(rs_start.rss_ipc); + } + else + { + rs_start.rss_ipc= NULL; + rs_start.rss_ipclen= 0; + } + m.RS_CMD_ADDR = (char *) &rs_start; /* Build request message and send the request. */