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.
This commit is contained in:
Philip Homburg 2008-02-21 16:20:22 +00:00
parent 19db2b646e
commit ca8291c815
4 changed files with 184 additions and 122 deletions

View file

@ -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);
}

View file

@ -4,6 +4,7 @@
*/
#include "inc.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
@ -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");
for (p= rp->r_ipc_list; p[0] != '\0'; p= q)
{
/* Skip leading space */
while (p[0] != '\0' && isspace((unsigned char)p[0]))
p++;
/* 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;
}
/* 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';
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);
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(RS_PROC_NR);
if (priv_id < 0)
{
printf(
"init_privs: unable to get priv_id for RS: %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_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
{

View file

@ -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. */

View file

@ -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. */