forked from M-Labs/artiq
runtime: validate pointers received from kernel CPU
This commit is contained in:
parent
8a796a6818
commit
87ae250baa
|
@ -105,114 +105,6 @@ enum {
|
||||||
REMOTEMSG_TYPE_RPC_REQUEST,
|
REMOTEMSG_TYPE_RPC_REQUEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int add_base_rpc_value(char base_type, void *value, char *buffer_out, int available_space)
|
|
||||||
{
|
|
||||||
switch(base_type) {
|
|
||||||
case 'n':
|
|
||||||
return 0;
|
|
||||||
case 'b':
|
|
||||||
if(available_space < 1)
|
|
||||||
return -1;
|
|
||||||
if(*(char *)value)
|
|
||||||
buffer_out[0] = 1;
|
|
||||||
else
|
|
||||||
buffer_out[0] = 0;
|
|
||||||
return 1;
|
|
||||||
case 'i':
|
|
||||||
if(available_space < 4)
|
|
||||||
return -1;
|
|
||||||
memcpy(buffer_out, value, 4);
|
|
||||||
return 4;
|
|
||||||
case 'I':
|
|
||||||
case 'f':
|
|
||||||
if(available_space < 8)
|
|
||||||
return -1;
|
|
||||||
memcpy(buffer_out, value, 8);
|
|
||||||
return 8;
|
|
||||||
case 'F':
|
|
||||||
if(available_space < 16)
|
|
||||||
return -1;
|
|
||||||
memcpy(buffer_out, value, 16);
|
|
||||||
return 16;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int add_rpc_value(int bi, int type_tag, void *value)
|
|
||||||
{
|
|
||||||
char base_type;
|
|
||||||
int obi, r;
|
|
||||||
|
|
||||||
obi = bi;
|
|
||||||
base_type = type_tag;
|
|
||||||
|
|
||||||
if((bi + 1) > BUFFER_OUT_SIZE)
|
|
||||||
return -1;
|
|
||||||
buffer_out[bi++] = base_type;
|
|
||||||
|
|
||||||
if(base_type == 'l') {
|
|
||||||
char elt_type;
|
|
||||||
int len;
|
|
||||||
int i, p;
|
|
||||||
|
|
||||||
elt_type = type_tag >> 8;
|
|
||||||
if((bi + 1) > BUFFER_OUT_SIZE)
|
|
||||||
return -1;
|
|
||||||
buffer_out[bi++] = elt_type;
|
|
||||||
|
|
||||||
len = *(int *)value;
|
|
||||||
if((bi + 4) > BUFFER_OUT_SIZE)
|
|
||||||
return -1;
|
|
||||||
memcpy(&buffer_out[bi], &len, 4);
|
|
||||||
bi += 4;
|
|
||||||
|
|
||||||
p = 4;
|
|
||||||
for(i=0;i<len;i++) {
|
|
||||||
r = add_base_rpc_value(elt_type, (char *)value + p,
|
|
||||||
&buffer_out[bi], BUFFER_OUT_SIZE - bi);
|
|
||||||
if(r < 0)
|
|
||||||
return r;
|
|
||||||
bi += r;
|
|
||||||
p += r;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r = add_base_rpc_value(base_type, value,
|
|
||||||
&buffer_out[bi], BUFFER_OUT_SIZE - bi);
|
|
||||||
if(r < 0)
|
|
||||||
return r;
|
|
||||||
bi += r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bi - obi;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_rpc_request(int rpc_num, va_list args)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
int bi = 8;
|
|
||||||
int type_tag;
|
|
||||||
|
|
||||||
buffer_out[bi++] = REMOTEMSG_TYPE_RPC_REQUEST;
|
|
||||||
|
|
||||||
memcpy(&buffer_out[bi], &rpc_num, 4);
|
|
||||||
bi += 4;
|
|
||||||
|
|
||||||
while((type_tag = va_arg(args, int))) {
|
|
||||||
r = add_rpc_value(bi, type_tag,
|
|
||||||
type_tag == 'n' ? NULL : va_arg(args, void *));
|
|
||||||
if(r < 0)
|
|
||||||
return 0;
|
|
||||||
bi += r;
|
|
||||||
}
|
|
||||||
if((bi + 1) > BUFFER_OUT_SIZE)
|
|
||||||
return 0;
|
|
||||||
buffer_out[bi++] = 0;
|
|
||||||
|
|
||||||
submit_output(bi);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int process_input(void)
|
static int process_input(void)
|
||||||
{
|
{
|
||||||
switch(buffer_in[8]) {
|
switch(buffer_in[8]) {
|
||||||
|
@ -366,8 +258,130 @@ int session_input(void *data, int len)
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <generated/mem.h>
|
static int add_base_rpc_value(char base_type, void *value, char *buffer_out, int available_space)
|
||||||
#define KERNELCPU_MAILBOX MMPTR(MAILBOX_BASE)
|
{
|
||||||
|
switch(base_type) {
|
||||||
|
case 'n':
|
||||||
|
return 0;
|
||||||
|
case 'b':
|
||||||
|
if(available_space < 1)
|
||||||
|
return -1;
|
||||||
|
if(*(char *)value)
|
||||||
|
buffer_out[0] = 1;
|
||||||
|
else
|
||||||
|
buffer_out[0] = 0;
|
||||||
|
return 1;
|
||||||
|
case 'i':
|
||||||
|
if(available_space < 4)
|
||||||
|
return -1;
|
||||||
|
memcpy(buffer_out, value, 4);
|
||||||
|
return 4;
|
||||||
|
case 'I':
|
||||||
|
case 'f':
|
||||||
|
if(available_space < 8)
|
||||||
|
return -1;
|
||||||
|
memcpy(buffer_out, value, 8);
|
||||||
|
return 8;
|
||||||
|
case 'F':
|
||||||
|
if(available_space < 16)
|
||||||
|
return -1;
|
||||||
|
memcpy(buffer_out, value, 16);
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_rpc_value(int bi, int type_tag, void *value)
|
||||||
|
{
|
||||||
|
char base_type;
|
||||||
|
int obi, r;
|
||||||
|
|
||||||
|
obi = bi;
|
||||||
|
base_type = type_tag;
|
||||||
|
|
||||||
|
if((bi + 1) > BUFFER_OUT_SIZE)
|
||||||
|
return -1;
|
||||||
|
buffer_out[bi++] = base_type;
|
||||||
|
|
||||||
|
if(base_type == 'l') {
|
||||||
|
char elt_type;
|
||||||
|
int len;
|
||||||
|
int i, p;
|
||||||
|
|
||||||
|
elt_type = type_tag >> 8;
|
||||||
|
if((bi + 1) > BUFFER_OUT_SIZE)
|
||||||
|
return -1;
|
||||||
|
buffer_out[bi++] = elt_type;
|
||||||
|
|
||||||
|
len = *(int *)value;
|
||||||
|
if((bi + 4) > BUFFER_OUT_SIZE)
|
||||||
|
return -1;
|
||||||
|
memcpy(&buffer_out[bi], &len, 4);
|
||||||
|
bi += 4;
|
||||||
|
|
||||||
|
p = 4;
|
||||||
|
for(i=0;i<len;i++) {
|
||||||
|
r = add_base_rpc_value(elt_type, (char *)value + p,
|
||||||
|
&buffer_out[bi], BUFFER_OUT_SIZE - bi);
|
||||||
|
if(r < 0)
|
||||||
|
return r;
|
||||||
|
bi += r;
|
||||||
|
p += r;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = add_base_rpc_value(base_type, value,
|
||||||
|
&buffer_out[bi], BUFFER_OUT_SIZE - bi);
|
||||||
|
if(r < 0)
|
||||||
|
return r;
|
||||||
|
bi += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bi - obi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int validate_kpointer(void *p)
|
||||||
|
{
|
||||||
|
unsigned int v = (unsigned int)p;
|
||||||
|
if((v < 0x40400000) || (v > (0x4fffffff - 1024*1024))) {
|
||||||
|
log("Received invalid pointer from kernel CPU: 0x%08x", v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_rpc_request(int rpc_num, va_list args)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int bi = 8;
|
||||||
|
int type_tag;
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
buffer_out[bi++] = REMOTEMSG_TYPE_RPC_REQUEST;
|
||||||
|
|
||||||
|
memcpy(&buffer_out[bi], &rpc_num, 4);
|
||||||
|
bi += 4;
|
||||||
|
|
||||||
|
while((type_tag = va_arg(args, int))) {
|
||||||
|
if(type_tag == 'n')
|
||||||
|
v = NULL;
|
||||||
|
else {
|
||||||
|
v = va_arg(args, void *);
|
||||||
|
if(!validate_kpointer(v))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
r = add_rpc_value(bi, type_tag, v);
|
||||||
|
if(r < 0)
|
||||||
|
return 0;
|
||||||
|
bi += r;
|
||||||
|
}
|
||||||
|
if((bi + 1) > BUFFER_OUT_SIZE)
|
||||||
|
return 0;
|
||||||
|
buffer_out[bi++] = 0;
|
||||||
|
|
||||||
|
submit_output(bi);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* assumes output buffer is empty when called */
|
/* assumes output buffer is empty when called */
|
||||||
static int process_kmsg(struct msg_base *umsg)
|
static int process_kmsg(struct msg_base *umsg)
|
||||||
|
@ -376,6 +390,8 @@ static int process_kmsg(struct msg_base *umsg)
|
||||||
log("Received message from kernel CPU while not in running state");
|
log("Received message from kernel CPU while not in running state");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(!validate_kpointer(umsg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch(umsg->type) {
|
switch(umsg->type) {
|
||||||
case MESSAGE_TYPE_FINISHED:
|
case MESSAGE_TYPE_FINISHED:
|
||||||
|
|
Loading…
Reference in New Issue