From 0c85cd4102dbbae8f29f229e8c129affabdedc29 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Wed, 4 Mar 2020 21:36:12 -0500 Subject: [PATCH] chore: Assorted cleanup --- runtime/include/http_api.h | 12 +-- runtime/include/sandbox.h | 173 +++++++++++++++++++----------- runtime/src/http.c | 185 ++++++++++++++++++++------------- runtime/src/libc/uvio.c | 48 ++++----- runtime/src/memory/64bit_nix.c | 8 +- runtime/src/runtime.c | 11 -- runtime/src/sandbox.c | 138 ++++++++++++------------ 7 files changed, 333 insertions(+), 242 deletions(-) diff --git a/runtime/include/http_api.h b/runtime/include/http_api.h index 2e99a0d..46d2047 100644 --- a/runtime/include/http_api.h +++ b/runtime/include/http_api.h @@ -2,13 +2,13 @@ #define SRFT_HTTP_API_H #include -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); diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index c6d537d..4c8723d 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -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 */ diff --git a/runtime/src/http.c b/runtime/src/http.c index cfa3968..b5ae00c 100644 --- a/runtime/src/http.c +++ b/runtime/src/http.c @@ -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; } diff --git a/runtime/src/libc/uvio.c b/runtime/src/libc/uvio.c index ead75aa..9f89b26 100644 --- a/runtime/src/libc/uvio.c +++ b/runtime/src/libc/uvio.c @@ -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; diff --git a/runtime/src/memory/64bit_nix.c b/runtime/src/memory/64bit_nix.c index b35a0b2..5414ea4 100644 --- a/runtime/src/memory/64bit_nix.c +++ b/runtime/src/memory/64bit_nix.c @@ -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 * diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index a2d6d4d..7549071 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -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); -} - /** * ??? **/ diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 4e09236..af34e96 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -7,40 +7,48 @@ #include #include +/** + * 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!