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:
parent
19db2b646e
commit
ca8291c815
4 changed files with 184 additions and 122 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in a new issue