chore: Assorted cleanup

main
Sean McBride 5 years ago
parent 862143f37a
commit 0c85cd4102

@ -2,13 +2,13 @@
#define SRFT_HTTP_API_H
#include <http.h>
int http_request_body_get_sb(struct sandbox *s, char **body);
int http_request_parse_sb(struct sandbox *s, size_t l);
int http_request_body_get_sb(struct sandbox *sandbox, char **body);
int http_request_parse_sb(struct sandbox *sandbox, size_t l);
int http_response_header_set_sb(struct sandbox *s, char *h, int len);
int http_response_body_set_sb(struct sandbox *s, char *body, int len);
int http_response_status_set_sb(struct sandbox *s, char *status, int len);
int http_response_vector_sb(struct sandbox *s);
int http_response_header_set_sb(struct sandbox *sandbox, char *h, int len);
int http_response_body_set_sb(struct sandbox *sandbox, char *body, int len);
int http_response_status_set_sb(struct sandbox *sandbox, char *status, int len);
int http_response_vector_sb(struct sandbox *sandbox);
void http_init(void);

@ -37,7 +37,7 @@ struct sandbox {
void *linear_start; // after sandbox struct
u32 linear_size; // from after sandbox struct
u32 linear_max_size;
u32 sb_size;
u32 sandbox_size;
void *stack_start; // guess we need a mechanism for stack allocation.
u32 stack_size; // and to set the size of it.
@ -62,9 +62,9 @@ struct sandbox {
int csock;
uv_tcp_t cuv;
uv_shutdown_t cuvsr;
http_parser hp;
struct http_request rqi;
struct http_response rsi;
http_parser http_parser;
struct http_request http_request;
struct http_response http_response;
char * read_buf;
ssize_t read_len, read_size;
@ -86,18 +86,28 @@ typedef struct sandbox_request sbox_request_t;
DEQUE_PROTOTYPE(sandbox, sbox_request_t *);
static inline int sandbox_deque_push(sbox_request_t *sandbox_request);
// a runtime resource, malloc on this!
struct sandbox *sandbox_alloc(struct module *module, char *args, int sock, const struct sockaddr *addr, u64 start_time);
// should free stack and heap resources.. also any I/O handles.
void sandbox_free(struct sandbox *sbox);
void sandbox_free(struct sandbox *sandbox);
extern __thread struct sandbox *current_sandbox;
// next_sandbox only used in SIGUSR1
extern __thread arch_context_t *next_context;
typedef struct sandbox sandbox_t;
void sandbox_run(sbox_request_t *s);
/**
* Allocates a new Sandbox Request and places it on the Global Deque
* @param module the module we want to request
* @param args the arguments that we'll pass to the serverless function
* @param sock
* @param addr
* @param start_time the timestamp of when we receives the request from the network (in cycles)
* @return the new sandbox request
**/
static inline sbox_request_t *
sbox_request_alloc(
struct module *module,
@ -106,59 +116,72 @@ sbox_request_alloc(
const struct sockaddr *addr,
u64 start_time)
{
// sandbox_alloc seems to be
sbox_request_t *s = malloc(sizeof(sbox_request_t));
assert(s);
s->module = module;
s->args = args;
s->sock = sock;
s->addr = (struct sockaddr *)addr;
s->start_time = start_time;
sandbox_run(s);
return s;
sbox_request_t *sandbox_request = malloc(sizeof(sbox_request_t));
assert(sandbox_request);
sandbox_request->module = module;
sandbox_request->args = args;
sandbox_request->sock = sock;
sandbox_request->addr = (struct sockaddr *)addr;
sandbox_request->start_time = start_time;
debuglog("[%p: %s]\n", sandbox_request, sandbox_request->module->name);
sandbox_deque_push(sandbox_request);
return sandbox_request;
}
/**
* Getter for the current sandbox executing on this thread
* @returns the current sandbox executing on this thread
**/
static inline struct sandbox *
sandbox_current(void)
{
return current_sandbox;
}
/**
* Setter for the current sandbox executing on this thread
* @param sandbox the sandbox we are setting this thread to run
**/
static inline void
sandbox_current_set(struct sandbox *sbox)
sandbox_current_set(struct sandbox *sandbox)
{
// FIXME: critical-section.
current_sandbox = sbox;
if (sbox == NULL) return;
current_sandbox = sandbox;
if (sandbox == NULL) return;
sandbox_lmbase = sbox->linear_start;
sandbox_lmbound = sbox->linear_size;
// Thread Local State about the Current Sandbox
sandbox_lmbase = sandbox->linear_start;
sandbox_lmbound = sandbox->linear_size;
// TODO: module table or sandbox table?
module_indirect_table = sbox->module->indirect_table;
module_indirect_table = sandbox->module->indirect_table;
}
/**
* @brief Safety checks around linear memory base and bounds and the Wasm function indirect table
* Check that the current_sandbox struct matches the rest of the thread local state about the executing sandbox
* This includes lmbase, lmbound, and module_indirect_table
*/
static inline void
sandbox_current_check(void)
{
struct sandbox *c = sandbox_current();
assert(c && c->linear_start == sandbox_lmbase && c->linear_size == sandbox_lmbound);
assert(c->module->indirect_table == module_indirect_table);
struct sandbox *sandbox = sandbox_current();
assert(sandbox && sandbox->linear_start == sandbox_lmbase && sandbox->linear_size == sandbox_lmbound);
assert(sandbox->module->indirect_table == module_indirect_table);
}
/**
* @return the module of the current sandbox
* Given a sandbox, returns the module that sandbox is executing
* @param sandbox the sandbox whose module we want
* @return the module of the provided sandbox
*/
static inline struct module *
sandbox_module(struct sandbox *s)
sandbox_module(struct sandbox *sandbox)
{
if (!s) return NULL;
return s->module;
if (!sandbox) return NULL;
return sandbox->module;
}
extern void sandbox_local_end(struct sandbox *s);
extern void sandbox_local_end(struct sandbox *sandbox);
/**
* @brief Switches to the next sandbox, placing the current sandbox of the completion queue if in RETURNED state
@ -181,16 +204,16 @@ sandbox_switch(struct sandbox *next_sandbox)
}
/**
* Getter for the arguments of the current sandbox
* @return the arguments of the current sandbox
*/
static inline char *
sandbox_args(void)
{
struct sandbox *c = sandbox_current();
return (char *)c->args;
struct sandbox *sandbox = sandbox_current();
return (char *)sandbox->args;
}
// void sandbox_run(struct sandbox *s);
void * sandbox_run_func(void *data);
struct sandbox *sandbox_schedule(int interrupt);
void sandbox_block(void);
@ -207,36 +230,41 @@ void sandbox_exit(void);
extern struct deque_sandbox *global_deque;
extern pthread_mutex_t global_deque_mutex;
/**
* Pushes a sandbox request to the global deque
* @para
**/
static inline int
sandbox_deque_push(sbox_request_t *s)
sandbox_deque_push(sbox_request_t *sandbox_request)
{
int ret;
int return_code;
#if NCORES == 1
pthread_mutex_lock(&global_deque_mutex);
#endif
ret = deque_push_sandbox(global_deque, &s);
return_code = deque_push_sandbox(global_deque, &sandbox_request);
#if NCORES == 1
pthread_mutex_unlock(&global_deque_mutex);
#endif
return ret;
return return_code;
}
static inline int
sandbox_deque_pop(sbox_request_t **s)
sandbox_deque_pop(sbox_request_t **sandbox_request)
{
int ret;
int return_code;
#if NCORES == 1
pthread_mutex_lock(&global_deque_mutex);
#endif
ret = deque_pop_sandbox(global_deque, s);
return_code = deque_pop_sandbox(global_deque, sandbox_request);
#if NCORES == 1
pthread_mutex_unlock(&global_deque_mutex);
#endif
return ret;
return return_code;
}
/**
@ -245,75 +273,96 @@ sandbox_deque_pop(sbox_request_t **s)
static inline sbox_request_t *
sandbox_deque_steal(void)
{
sbox_request_t *s = NULL;
sbox_request_t *sandbox_request = NULL;
#if NCORES == 1
sandbox_deque_pop(&s);
sandbox_deque_pop(&sandbox_request);
#else
// TODO: check! is there a sandboxing thread on same core as udp-server thread?
int r = deque_steal_sandbox(global_deque, &s);
if (r) s = NULL;
int r = deque_steal_sandbox(global_deque, &sandbox_request);
if (r) sandbox_request = NULL;
#endif
return s;
return sandbox_request;
}
static inline int
io_handle_preopen(void)
{
struct sandbox *s = sandbox_current();
struct sandbox *sandbox = sandbox_current();
int i;
for (i = 0; i < SBOX_MAX_OPEN; i++) {
if (s->handles[i].fd < 0) break;
if (sandbox->handles[i].fd < 0) break;
}
if (i == SBOX_MAX_OPEN) return -1;
s->handles[i].fd = SBOX_PREOPEN_MAGIC;
memset(&s->handles[i].uvh, 0, sizeof(union uv_any_handle));
sandbox->handles[i].fd = SBOX_PREOPEN_MAGIC;
memset(&sandbox->handles[i].uvh, 0, sizeof(union uv_any_handle));
return i;
}
static inline int
io_handle_open(int fd)
{
struct sandbox *s = sandbox_current();
struct sandbox *sandbox = sandbox_current();
if (fd < 0) return fd;
int i = io_handle_preopen();
s->handles[i].fd = fd; // well, per sandbox.. so synchronization necessary!
sandbox->handles[i].fd = fd; // well, per sandbox.. so synchronization necessary!
return i;
}
/**
* Sets the file descriptor of the sandbox's ith io_handle
* Returns error condition if the fd to set does not contain sandbox preopen magin
* @param idx index of the sandbox handles we want to set
* @param fd the file descripter we want to set it to
* @returns the idx that was set or -1 in case of error
**/
static inline int
io_handle_preopen_set(int idx, int fd)
{
struct sandbox *s = sandbox_current();
struct sandbox *sandbox = sandbox_current();
if (idx >= SBOX_MAX_OPEN || idx < 0) return -1;
if (fd < 0 || s->handles[idx].fd != SBOX_PREOPEN_MAGIC) return -1;
s->handles[idx].fd = fd;
if (fd < 0 || sandbox->handles[idx].fd != SBOX_PREOPEN_MAGIC) return -1;
sandbox->handles[idx].fd = fd;
return idx;
}
/**
* Get the file descriptor of the sandbox's ith io_handle
* @param idx index into the sandbox's handles table
* @returns any libuv handle
**/
static inline int
io_handle_fd(int idx)
{
struct sandbox *s = sandbox_current();
struct sandbox *sandbox = sandbox_current();
if (idx >= SBOX_MAX_OPEN || idx < 0) return -1;
return s->handles[idx].fd;
return sandbox->handles[idx].fd;
}
/**
* Close the sandbox's ith io_handle
* @param idx index of the handle to close
**/
static inline void
io_handle_close(int idx)
{
struct sandbox *s = sandbox_current();
struct sandbox *sandbox = sandbox_current();
if (idx >= SBOX_MAX_OPEN || idx < 0) return;
s->handles[idx].fd = -1;
sandbox->handles[idx].fd = -1;
}
/**
* Get the Libuv handle located at idx of the sandbox ith io_handle
* @param idx index of the handle containing uvh???
* @returns any libuv handle
**/
static inline union uv_any_handle *
io_handle_uv_get(int idx)
{
struct sandbox *s = sandbox_current();
struct sandbox *sandbox = sandbox_current();
if (idx >= SBOX_MAX_OPEN || idx < 0) return NULL;
return &s->handles[idx].uvh;
return &sandbox->handles[idx].uvh;
}
#endif /* SFRT_SANDBOX_H */

@ -5,180 +5,225 @@
http_parser_settings settings;
/**
* Sets the HTTP Request's message_begin and last_was_value flags to true
* @param parser
**/
static inline int
http_on_msg_begin(http_parser *parser)
{
struct sandbox * s = parser->data;
struct http_request *r = &s->rqi;
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
r->message_begin = 1;
r->last_was_value = 1; // should always start with a header..
http_request->message_begin = 1;
http_request->last_was_value = 1; // should always start with a header..
return 0;
}
/**
* Sets the HTTP Request's message_end flag to true
* @param parser
**/
static inline int
http_on_msg_end(http_parser *parser)
{
struct sandbox * s = parser->data;
struct http_request *r = &s->rqi;
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
r->message_end = 1;
http_request->message_end = 1;
return 0;
}
/**
* Sets the HTTP Request's header_end flag to true
* @param parser
**/
static inline int
http_on_header_end(http_parser *parser)
{
struct sandbox * s = parser->data;
struct http_request *r = &s->rqi;
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
r->header_end = 1;
http_request->header_end = 1;
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_url(http_parser *parser, const char *at, size_t length)
{
struct sandbox * s = parser->data;
struct http_request *r = &s->rqi;
struct sandbox * sandbox = parser->data;
assert(strncmp(s->module->name, (at + 1), length - 1) == 0);
assert(strncmp(sandbox->module->name, (at + 1), length - 1) == 0);
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_header_field(http_parser *parser, const char *at, size_t length)
{
struct sandbox * s = parser->data;
struct http_request *r = &s->rqi;
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
if (r->last_was_value) r->nheaders++;
assert(r->nheaders <= HTTP_HEADERS_MAX);
if (http_request->last_was_value) http_request->nheaders++;
assert(http_request->nheaders <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADER_MAXSZ);
r->last_was_value = 0;
r->headers[r->nheaders - 1].key = (char *)at; // it is from the sandbox's req_resp_data, should persist.
http_request->last_was_value = 0;
http_request->headers[http_request->nheaders - 1].key = (char *)at; // it is from the sandbox's req_resp_data, should persist.
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_header_value(http_parser *parser, const char *at, size_t length)
{
struct sandbox * s = parser->data;
struct http_request *r = &s->rqi;
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
r->last_was_value = 1;
assert(r->nheaders <= HTTP_HEADERS_MAX);
http_request->last_was_value = 1;
assert(http_request->nheaders <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADERVAL_MAXSZ);
r->headers[r->nheaders - 1].val = (char *)at; // it is from the sandbox's req_resp_data, should persist.
http_request->headers[http_request->nheaders - 1].val = (char *)at; // it is from the sandbox's req_resp_data, should persist.
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_body(http_parser *parser, const char *at, size_t length)
{
struct sandbox * s = parser->data;
struct http_request *r = &s->rqi;
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
assert(r->bodylen + length <= s->module->max_request_size);
if (!r->body)
r->body = (char *)at;
assert(http_request->bodylen + length <= sandbox->module->max_request_size);
if (!http_request->body)
http_request->body = (char *)at;
else
assert(r->body + r->bodylen == at);
assert(http_request->body + http_request->bodylen == at);
r->bodylen += length;
http_request->bodylen += length;
return 0;
}
/**
* Gets the HTTP Request body from a Sandbox
* @param sandbox the sandbox we want the body from
* @param b pointer that we'll assign to the http_request body
* @returns the length of the http_request's body
**/
int
http_request_body_get_sb(struct sandbox *s, char **b)
http_request_body_get_sb(struct sandbox *sandbox, char **b)
{
struct http_request *r = &s->rqi;
struct http_request *http_request = &sandbox->http_request;
*b = r->body;
return r->bodylen;
*b = http_request->body;
return http_request->bodylen;
}
int
http_response_header_set_sb(struct sandbox *c, char *key, int len)
http_response_header_set_sb(struct sandbox *sandbox, char *key, int len)
{
// by now, req_resp_data should only be containing response!
struct http_response *r = &c->rsi;
struct http_response *http_response = &sandbox->http_response;
assert(r->nheaders < HTTP_HEADERS_MAX);
r->nheaders++;
r->headers[r->nheaders - 1].hdr = key;
r->headers[r->nheaders - 1].len = len;
assert(http_response->nheaders < HTTP_HEADERS_MAX);
http_response->nheaders++;
http_response->headers[http_response->nheaders - 1].hdr = key;
http_response->headers[http_response->nheaders - 1].len = len;
return 0;
}
int
http_response_body_set_sb(struct sandbox *c, char *body, int len)
http_response_body_set_sb(struct sandbox *sandbox, char *body, int len)
{
struct http_response *r = &c->rsi;
struct http_response *http_response = &sandbox->http_response;
assert(len <= c->module->max_response_size);
r->body = body;
r->bodylen = len;
assert(len <= sandbox->module->max_response_size);
http_response->body = body;
http_response->bodylen = len;
return 0;
}
int
http_response_status_set_sb(struct sandbox *c, char *status, int len)
http_response_status_set_sb(struct sandbox *sandbox, char *status, int len)
{
struct http_response *r = &c->rsi;
struct http_response *http_response = &sandbox->http_response;
r->status = status;
r->stlen = len;
http_response->status = status;
http_response->stlen = len;
return 0;
}
int
http_response_vector_sb(struct sandbox *c)
http_response_vector_sb(struct sandbox *sandbox)
{
int nb = 0;
struct http_response *r = &c->rsi;
struct http_response *http_response = &sandbox->http_response;
#ifdef USE_HTTP_UVIO
r->bufs[nb] = uv_buf_init(r->status, r->stlen);
http_response->bufs[nb] = uv_buf_init(http_response->status, http_response->stlen);
nb++;
for (int i = 0; i < r->nheaders; i++) {
r->bufs[nb] = uv_buf_init(r->headers[i].hdr, r->headers[i].len);
for (int i = 0; i < http_response->nheaders; i++) {
http_response->bufs[nb] = uv_buf_init(http_response->headers[i].hdr, http_response->headers[i].len);
nb++;
}
if (r->body) {
r->bufs[nb] = uv_buf_init(r->body, r->bodylen);
if (http_response->body) {
http_response->bufs[nb] = uv_buf_init(http_response->body, http_response->bodylen);
nb++;
r->bufs[nb] = uv_buf_init(r->status + r->stlen - 2, 2); // for crlf
http_response->bufs[nb] = uv_buf_init(http_response->status + http_response->stlen - 2, 2); // for crlf
nb++;
}
#else
r->bufs[nb].iov_base = r->status;
r->bufs[nb].iov_len = r->stlen;
http_response->bufs[nb].iov_base = http_response->status;
http_response->bufs[nb].iov_len = http_response->stlen;
nb++;
for (int i = 0; i < r->nheaders; i++) {
r->bufs[nb].iov_base = r->headers[i].hdr;
r->bufs[nb].iov_len = r->headers[i].len;
for (int i = 0; i < http_response->nheaders; i++) {
http_response->bufs[nb].iov_base = http_response->headers[i].hdr;
http_response->bufs[nb].iov_len = http_response->headers[i].len;
nb++;
}
if (r->body) {
r->bufs[nb].iov_base = r->body;
r->bufs[nb].iov_len = r->bodylen;
if (http_response->body) {
http_response->bufs[nb].iov_base = http_response->body;
http_response->bufs[nb].iov_len = http_response->bodylen;
nb++;
r->bufs[nb].iov_base = r->status + r->stlen - 2;
r->bufs[nb].iov_len = 2;
http_response->bufs[nb].iov_base = http_response->status + http_response->stlen - 2;
http_response->bufs[nb].iov_len = 2;
nb++;
}
#endif
@ -187,9 +232,9 @@ http_response_vector_sb(struct sandbox *c)
}
int
http_request_parse_sb(struct sandbox *s, size_t l)
http_request_parse_sb(struct sandbox *sandbox, size_t l)
{
http_parser_execute(&s->hp, &settings, s->req_resp_data + s->rr_data_len, l);
http_parser_execute(&sandbox->http_parser, &settings, sandbox->req_resp_data + sandbox->rr_data_len, l);
return 0;
}

@ -104,12 +104,12 @@ u32
wasm_read(i32 filedes, i32 buf_offset, i32 nbyte)
{
if (filedes == 0) {
char * buf = get_memory_ptr_void(buf_offset, nbyte);
char * buffer = get_memory_ptr_void(buf_offset, nbyte);
struct sandbox * s = sandbox_current();
struct http_request *r = &s->rqi;
struct http_request *r = &s->http_request;
if (r->bodylen <= 0) return 0;
int l = nbyte > r->bodylen ? r->bodylen : nbyte;
memcpy(buf, r->body + r->bodyrlen, l);
memcpy(buffer, r->body + r->bodyrlen, l);
r->bodyrlen += l;
r->bodylen -= l;
return l;
@ -117,10 +117,10 @@ wasm_read(i32 filedes, i32 buf_offset, i32 nbyte)
int f = io_handle_fd(filedes);
// TODO: read on other file types
uv_fs_t req = UV_FS_REQ_INIT();
char * buf = get_memory_ptr_void(buf_offset, nbyte);
char * buffer = get_memory_ptr_void(buf_offset, nbyte);
debuglog("[%p] start[%d:%d, n%d]\n", uv_fs_get_data(&req), filedes, f, nbyte);
uv_buf_t bufv = uv_buf_init(buf, nbyte);
uv_buf_t bufv = uv_buf_init(buffer, nbyte);
uv_fs_read(runtime_uvio(), &req, f, &bufv, 1, -1, wasm_fs_callback);
sandbox_block();
@ -136,12 +136,12 @@ i32
wasm_write(i32 fd, i32 buf_offset, i32 buf_size)
{
if (fd == 1 || fd == 2) {
char * buf = get_memory_ptr_void(buf_offset, buf_size);
char * buffer = get_memory_ptr_void(buf_offset, buf_size);
struct sandbox *s = sandbox_current();
int l = s->module->max_response_size - s->rr_data_len;
l = l > buf_size ? buf_size : l;
if (l == 0) return 0;
memcpy(s->req_resp_data + s->rr_data_len, buf, l);
memcpy(s->req_resp_data + s->rr_data_len, buffer, l);
s->rr_data_len += l;
return l;
@ -149,9 +149,9 @@ wasm_write(i32 fd, i32 buf_offset, i32 buf_size)
int f = io_handle_fd(fd);
// TODO: read on other file types
uv_fs_t req = UV_FS_REQ_INIT();
char * buf = get_memory_ptr_void(buf_offset, buf_size);
char * buffer = get_memory_ptr_void(buf_offset, buf_size);
uv_buf_t bufv = uv_buf_init(buf, buf_size);
uv_buf_t bufv = uv_buf_init(buffer, buf_size);
uv_fs_write(runtime_uvio(), &req, f, &bufv, 1, -1, wasm_fs_callback);
sandbox_block();
@ -499,7 +499,7 @@ wasm_readv(i32 fd, i32 iov_offset, i32 iovcnt)
int len = 0;
struct wasm_iovec *iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec));
struct sandbox *s = sandbox_current();
struct http_request *r = &s->rqi;
struct http_request *r = &s->http_request;
if (r->bodylen <= 0) return 0;
for (int i = 0; i < iovcnt; i++) {
int l = iov[i].len > r->bodylen ? r->bodylen : iov[i].len;
@ -652,8 +652,8 @@ wasm_fsync(u32 fd)
u32
wasm_getcwd(u32 buf_offset, u32 buf_size)
{
char *buf = get_memory_ptr_void(buf_offset, buf_size);
char *res = getcwd(buf, buf_size);
char *buffer = get_memory_ptr_void(buf_offset, buf_size);
char *res = getcwd(buffer, buf_size);
if (!res) return 0;
return buf_offset;
@ -919,11 +919,11 @@ wasm_listen(i32 sockfd, i32 backlog)
#define SYS_RECVFROM 45
void
wasm_read_callback(uv_stream_t *s, ssize_t nread, const uv_buf_t *buf)
wasm_read_callback(uv_stream_t *s, ssize_t nread, const uv_buf_t *buffer)
{
struct sandbox *c = s->data;
debuglog("[%p] %ld %p\n", c, nread, buf);
debuglog("[%p] %ld %p\n", c, nread, buffer);
if (nread < 0) c->retval = -EIO;
c->read_len = nread;
debuglog("[%p] %ld\n", c, c->read_len);
@ -942,11 +942,11 @@ wasm_write_callback(uv_write_t *req, int status)
}
void
wasm_udp_recv_callback(uv_udp_t *h, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags)
wasm_udp_recv_callback(uv_udp_t *h, ssize_t nread, const uv_buf_t *buffer, const struct sockaddr *addr, unsigned flags)
{
struct sandbox *c = h->data;
debuglog("[%p] %ld %p\n", c, nread, buf);
debuglog("[%p] %ld %p\n", c, nread, buffer);
if (nread < 0) c->retval = -EIO;
c->read_len = nread;
debuglog("[%p] %ld\n", c, c->read_len);
@ -967,7 +967,7 @@ wasm_udp_send_callback(uv_udp_send_t *req, int status)
i32
wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i32 sockaddr_len)
{
char *buf = get_memory_ptr_void(buff_offset, len);
char *buffer = get_memory_ptr_void(buff_offset, len);
// TODO: only support "send" api for now
assert(sockaddr_len == 0);
struct sandbox * c = sandbox_current();
@ -979,7 +979,7 @@ wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i3
uv_write_t req = {
.data = c,
};
uv_buf_t b = uv_buf_init(buf, len);
uv_buf_t b = uv_buf_init(buffer, len);
debuglog("[%p] tcp\n", c);
int ret = uv_write(&req, (uv_stream_t *)h, &b, 1, wasm_write_callback);
sandbox_block();
@ -990,7 +990,7 @@ wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i3
uv_udp_send_t req = {
.data = c,
};
uv_buf_t b = uv_buf_init(buf, len);
uv_buf_t b = uv_buf_init(buffer, len);
debuglog("[%p] udp\n", c);
// TODO: sockaddr!
int r = uv_udp_send(&req, (uv_udp_t *)h, &b, 1, NULL, wasm_udp_send_callback);
@ -1005,19 +1005,19 @@ wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i3
}
static inline void
wasm_alloc_callback(uv_handle_t *h, size_t suggested, uv_buf_t *buf)
wasm_alloc_callback(uv_handle_t *h, size_t suggested, uv_buf_t *buffer)
{
struct sandbox *s = h->data;
// just let it use what is passed from caller!
buf->base = s->read_buf;
buf->len = s->read_size;
buffer->base = s->read_buf;
buffer->len = s->read_size;
}
i32
wasm_recvfrom(i32 fd, i32 buff_offset, i32 size, i32 flags, i32 sockaddr_offset, i32 socklen_offset)
{
char * buf = get_memory_ptr_void(buff_offset, size);
char * buffer = get_memory_ptr_void(buff_offset, size);
socklen_t *len = get_memory_ptr_void(socklen_offset, sizeof(socklen_t));
// TODO: only support "recv" api for now
assert(*len == 0);
@ -1030,7 +1030,7 @@ wasm_recvfrom(i32 fd, i32 buff_offset, i32 size, i32 flags, i32 sockaddr_offset,
// and there will only be one system call pending..
// so we keep the read buffer pointers in sandbox structure..
// for use in the callbacks..
c->read_buf = buf;
c->read_buf = buffer;
c->read_size = size;
c->read_len = 0;
c->retval = 0;

@ -23,10 +23,10 @@ free_linear_memory(void *base, u32 bound, u32 max)
void
expand_memory(void)
{
struct sandbox *curr = sandbox_current();
struct sandbox *sandbox = sandbox_current();
// max_pages = 0 => no limit: FIXME
assert((curr->sb_size + sandbox_lmbound) / WASM_PAGE_SIZE < WASM_MAX_PAGES);
assert((sandbox->sandbox_size + sandbox_lmbound) / WASM_PAGE_SIZE < WASM_MAX_PAGES);
// Remap the relevant wasm page to readable
char *mem_as_chars = sandbox_lmbase;
char *page_address = &mem_as_chars[sandbox_lmbound];
@ -38,9 +38,9 @@ expand_memory(void)
exit(1);
}
// TODO: check curr->linear_max_size
// TODO: check sandbox->linear_max_size
sandbox_lmbound += WASM_PAGE_SIZE;
curr->linear_size = sandbox_lmbound;
sandbox->linear_size = sandbox_lmbound;
}
INLINE char *

@ -274,17 +274,6 @@ sandbox_run_func(void *data)
pthread_exit(data);
}
/**
* Push the Sandbox Request to the Global Dequeue
* @param s The sandbox request we're pushing
**/
void
sandbox_run(sbox_request_t *sandbox_request)
{
debuglog("[%p: %s]\n", sandbox_request, sandbox_request->module->name);
sandbox_deque_push(sandbox_request);
}
/**
* ???
**/

@ -7,40 +7,48 @@
#include <uv.h>
#include <http_api.h>
/**
* Allocates the memory for a sandbox to run a module
* @param module the module that we want to run
* @returns the resulting sandbox or NULL if mmap failed
**/
static inline struct sandbox *
sandbox_memory_map(struct module *module)
{
unsigned long mem_sz = SBOX_MAX_MEM; // 4GB
unsigned long sb_sz = sizeof(struct sandbox) + module->max_request_or_response_size;
unsigned long lm_sz = WASM_PAGE_SIZE * WASM_START_PAGES;
if (lm_sz + sb_sz > mem_sz) return NULL;
assert(round_up_to_page(sb_sz) == sb_sz);
unsigned long rw_sz = sb_sz + lm_sz;
void *addr = mmap(NULL, sb_sz + mem_sz + /* guard page */ PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1,
unsigned long memory_size = SBOX_MAX_MEM; // 4GB
// Why do we add max_request_or_response_size?
unsigned long sandbox_size = sizeof(struct sandbox) + module->max_request_or_response_size;
unsigned long linear_memory_size = WASM_PAGE_SIZE * WASM_START_PAGES;
if (linear_memory_size + sandbox_size > memory_size) return NULL;
assert(round_up_to_page(sandbox_size) == sandbox_size);
// What does mmap do exactly with fd -1?
void *addr = mmap(NULL, sandbox_size + memory_size + /* guard page */ PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1,
0);
if (addr == MAP_FAILED) return NULL;
void *addr_rw = mmap(addr, sb_sz + lm_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,
void *addr_rw = mmap(addr, sandbox_size + linear_memory_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,
0);
if (addr_rw == MAP_FAILED) {
munmap(addr, mem_sz + PAGE_SIZE);
munmap(addr, memory_size + PAGE_SIZE);
return NULL;
}
struct sandbox *s = (struct sandbox *)addr;
struct sandbox *sandbox = (struct sandbox *)addr;
// can it include sandbox as well?
s->linear_start = (char *)addr + sb_sz;
s->linear_size = lm_sz;
s->module = module;
s->sb_size = sb_sz;
sandbox->linear_start = (char *)addr + sandbox_size;
sandbox->linear_size = linear_memory_size;
sandbox->module = module;
sandbox->sandbox_size = sandbox_size;
module_acquire(module);
return s;
return sandbox;
}
static inline void
sandbox_args_setup(i32 argc)
sandbox_args_setup(i32 argument_count)
{
struct sandbox *curr = sandbox_current();
char * args = sandbox_args();
@ -50,10 +58,10 @@ sandbox_args_setup(i32 argc)
assert(sandbox_lmbase == curr->linear_start);
expand_memory();
i32 *array_ptr = get_memory_ptr_void(curr->args_offset, argc * sizeof(i32));
i32 string_off = curr->args_offset + (argc * sizeof(i32));
i32 *array_ptr = get_memory_ptr_void(curr->args_offset, argument_count * sizeof(i32));
i32 string_off = curr->args_offset + (argument_count * sizeof(i32));
for (int i = 0; i < argc; i++) {
for (int i = 0; i < argument_count; i++) {
char * arg = args + (i * MOD_ARG_MAX_SZ);
size_t str_sz = strlen(arg) + 1;
@ -69,51 +77,51 @@ sandbox_args_setup(i32 argc)
static inline void
sb_read_callback(uv_stream_t *s, ssize_t nr, const uv_buf_t *b)
{
struct sandbox *c = s->data;
struct sandbox *sandbox = s->data;
if (nr > 0) {
if (http_request_parse_sb(c, nr) != 0) return;
c->rr_data_len += nr;
struct http_request *rh = &c->rqi;
if (http_request_parse_sb(sandbox, nr) != 0) return;
sandbox->rr_data_len += nr;
struct http_request *rh = &sandbox->http_request;
if (!rh->message_end) return;
}
uv_read_stop(s);
sandbox_wakeup(c);
sandbox_wakeup(sandbox);
}
static inline void
sb_close_callback(uv_handle_t *s)
{
struct sandbox *c = s->data;
sandbox_wakeup(c);
struct sandbox *sandbox = s->data;
sandbox_wakeup(sandbox);
}
static inline void
sb_shutdown_callback(uv_shutdown_t *req, int status)
{
struct sandbox *c = req->data;
sandbox_wakeup(c);
struct sandbox *sandbox = req->data;
sandbox_wakeup(sandbox);
}
static inline void
sb_write_callback(uv_write_t *w, int status)
{
struct sandbox *c = w->data;
struct sandbox *sandbox = w->data;
if (status < 0) {
c->cuvsr.data = c;
uv_shutdown(&c->cuvsr, (uv_stream_t *)&c->cuv, sb_shutdown_callback);
sandbox->cuvsr.data = sandbox;
uv_shutdown(&sandbox->cuvsr, (uv_stream_t *)&sandbox->cuv, sb_shutdown_callback);
return;
}
sandbox_wakeup(c);
sandbox_wakeup(sandbox);
}
static inline void
sb_alloc_callback(uv_handle_t *h, size_t suggested, uv_buf_t *buf)
{
struct sandbox *c = h->data;
size_t l = (c->module->max_request_or_response_size - c->rr_data_len);
buf->base = (c->req_resp_data + c->rr_data_len);
struct sandbox *sandbox = h->data;
size_t l = (sandbox->module->max_request_or_response_size - sandbox->rr_data_len);
buf->base = (sandbox->req_resp_data + sandbox->rr_data_len);
buf->len = l > suggested ? suggested : l;
}
@ -132,7 +140,7 @@ sandbox_client_request_get(void)
while (r > 0) {
if (http_request_parse(r) != 0) return -1;
curr->rr_data_len += r;
struct http_request *rh = &curr->rqi;
struct http_request *rh = &curr->http_request;
if (rh->message_end) break;
r = recv(curr->csock, (curr->req_resp_data + curr->rr_data_len),
@ -228,7 +236,7 @@ sandbox_entry(void)
softint_enable();
}
struct module *curr_mod = sandbox_module(curr);
int argc = module_argument_count(curr_mod);
int argument_count = module_argument_count(curr_mod);
// for stdio
int f = io_handle_open(0);
assert(f == 0);
@ -237,8 +245,8 @@ sandbox_entry(void)
f = io_handle_open(2);
assert(f == 2);
http_parser_init(&curr->hp, HTTP_REQUEST);
curr->hp.data = curr;
http_parser_init(&curr->http_parser, HTTP_REQUEST);
curr->http_parser.data = curr;
// NOTE: if more headers, do offset by that!
int rsp_hdr_len = strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN);
#ifdef USE_HTTP_UVIO
@ -256,9 +264,9 @@ sandbox_entry(void)
// module_table_init(curr_mod);
module_globals_init(curr_mod);
module_memory_init(curr_mod);
sandbox_args_setup(argc);
sandbox_args_setup(argument_count);
curr->retval = module_entry(curr_mod, argc, curr->args_offset);
curr->retval = module_entry(curr_mod, argument_count, curr->args_offset);
sandbox_client_response_set();
}
@ -279,56 +287,56 @@ sandbox_alloc(struct module *module, char *args, int sock, const struct sockaddr
// FIXME: don't use malloc. huge security problem!
// perhaps, main should be in its own sandbox, when it is not running any sandbox.
struct sandbox *sb = (struct sandbox *)sandbox_memory_map(module);
if (!sb) return NULL;
struct sandbox *sandbox = (struct sandbox *)sandbox_memory_map(module);
if (!sandbox) return NULL;
// Assign the start time from the request
sb->start_time = start_time;
sandbox->start_time = start_time;
// actual module instantiation!
sb->args = (void *)args;
sb->stack_size = module->stack_size;
sb->stack_start = mmap(NULL, sb->stack_size, PROT_READ | PROT_WRITE,
sandbox->args = (void *)args;
sandbox->stack_size = module->stack_size;
sandbox->stack_start = mmap(NULL, sandbox->stack_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
if (sb->stack_start == MAP_FAILED) {
if (sandbox->stack_start == MAP_FAILED) {
perror("mmap");
assert(0);
}
sb->csock = sock;
if (addr) memcpy(&sb->client, addr, sizeof(struct sockaddr));
for (int i = 0; i < SBOX_MAX_OPEN; i++) sb->handles[i].fd = -1;
ps_list_init_d(sb);
sandbox->csock = sock;
if (addr) memcpy(&sandbox->client, addr, sizeof(struct sockaddr));
for (int i = 0; i < SBOX_MAX_OPEN; i++) sandbox->handles[i].fd = -1;
ps_list_init_d(sandbox);
arch_context_init(&sb->ctxt, (reg_t)sandbox_entry, (reg_t)(sb->stack_start + sb->stack_size));
return sb;
arch_context_init(&sandbox->ctxt, (reg_t)sandbox_entry, (reg_t)(sandbox->stack_start + sandbox->stack_size));
return sandbox;
}
void
sandbox_free(struct sandbox *sb)
sandbox_free(struct sandbox *sandbox)
{
int ret;
// you have to context switch away to free a sandbox.
if (!sb || sb == sandbox_current()) return;
if (!sandbox || sandbox == sandbox_current()) return;
// again sandbox should be done and waiting for the parent.
// TODO: this needs to be enhanced. you may be killing a sandbox when its in any other execution states.
if (sb->state != SANDBOX_RETURNED) return;
if (sandbox->state != SANDBOX_RETURNED) return;
int sz = sizeof(struct sandbox);
sz += sb->module->max_request_or_response_size;
module_release(sb->module);
sz += sandbox->module->max_request_or_response_size;
module_release(sandbox->module);
// TODO free(sb->args);
void * stkaddr = sb->stack_start;
size_t stksz = sb->stack_size;
// TODO free(sandbox->args);
void * stkaddr = sandbox->stack_start;
size_t stksz = sandbox->stack_size;
// depending on the memory type
// free_linear_memory(sb->linear_start, sb->linear_size, sb->linear_max_size);
// free_linear_memory(sandbox->linear_start, sandbox->linear_size, sandbox->linear_max_size);
// mmaped memory includes sandbox structure in there.
ret = munmap(sb, sz);
ret = munmap(sandbox, sz);
if (ret) perror("munmap sandbox");
// remove stack!

Loading…
Cancel
Save