From 106974d9157750941940a974a2741f6f84633a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A4mes=20M=C3=A9n=C3=A9trey?= Date: Fri, 25 Mar 2022 10:46:29 +0100 Subject: [PATCH] Implement Berkeley Socket API for Intel SGX (#1061) Implement Berkeley Socket API for Intel SGX - bring Berkeley socket API in Intel SGX enclaves, - adapt the documentation of the socket API to mention Intel SGX enclaves, - adapt _iwasm_ in the mini-product _linux-sgx_ to support the same option as the one for _linux_, - tested on the socket sample as provided by WAMR (the TCP client/server). --- core/shared/platform/linux-sgx/sgx_socket.c | 369 ++++++++++++++++-- core/shared/platform/linux-sgx/sgx_socket.h | 45 ++- core/shared/platform/linux-sgx/sgx_wamr.edl | 25 +- .../platform/linux-sgx/untrusted/socket.c | 51 +++ doc/socket_api.md | 21 +- .../linux-sgx/enclave-sample/App/App.cpp | 42 +- .../enclave-sample/Enclave/Enclave.cpp | 28 +- 7 files changed, 543 insertions(+), 38 deletions(-) diff --git a/core/shared/platform/linux-sgx/sgx_socket.c b/core/shared/platform/linux-sgx/sgx_socket.c index 9ed92f53..156d79ef 100644 --- a/core/shared/platform/linux-sgx/sgx_socket.c +++ b/core/shared/platform/linux-sgx/sgx_socket.c @@ -9,21 +9,194 @@ #define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__) +/** OCALLs prototypes **/ int -ocall_socket(int *p_ret, int domain, int type, int protocol); +ocall_accept(int *p_ret, int sockfd, void *addr, uint32_t *addrlen, + uint32_t addr_size); + +int +ocall_bind(int *p_ret, int sockfd, const void *addr, uint32_t addrlen); + +int +ocall_close(int *p_ret, int fd); + +int +ocall_connect(int *p_ret, int sockfd, void *addr, uint32_t addrlen); + +int +ocall_fcntl_long(int *p_ret, int fd, int cmd, long arg); + +int +ocall_getsockname(int *p_ret, int sockfd, void *addr, uint32_t *addrlen, + uint32_t addr_size); + int ocall_getsockopt(int *p_ret, int sockfd, int level, int optname, void *val_buf, unsigned int val_buf_size, void *len_buf); int -ocall_sendmsg(ssize_t *p_ret, int sockfd, void *msg_buf, - unsigned int msg_buf_size, int flags); +ocall_listen(int *p_ret, int sockfd, int backlog); + +int +ocall_recv(int *p_ret, int sockfd, void *buf, size_t len, int flags); + int ocall_recvmsg(ssize_t *p_ret, int sockfd, void *msg_buf, unsigned int msg_buf_size, int flags); + +int +ocall_send(int *p_ret, int sockfd, const void *buf, size_t len, int flags); + +int +ocall_sendmsg(ssize_t *p_ret, int sockfd, void *msg_buf, + unsigned int msg_buf_size, int flags); + +int +ocall_setsockopt(int *p_ret, int sockfd, int level, int optname, void *optval, + unsigned int optlen); + int ocall_shutdown(int *p_ret, int sockfd, int how); +int +ocall_socket(int *p_ret, int domain, int type, int protocol); +/** OCALLs prototypes end **/ + +/** In-enclave implementation of POSIX functions **/ +static bool +is_little_endian() +{ + long i = 0x01020304; + unsigned char *c = (unsigned char *)&i; + return (*c == 0x04) ? true : false; +} + +static void +swap32(uint8 *pData) +{ + uint8 value = *pData; + *pData = *(pData + 3); + *(pData + 3) = value; + + value = *(pData + 1); + *(pData + 1) = *(pData + 2); + *(pData + 2) = value; +} + +static void +swap16(uint8 *pData) +{ + uint8 value = *pData; + *(pData) = *(pData + 1); + *(pData + 1) = value; +} + +static uint32 +htonl(uint32 value) +{ + uint32 ret; + if (is_little_endian()) { + ret = value; + swap32((uint8 *)&ret); + return ret; + } + + return value; +} + +static uint32 +ntohl(uint32 value) +{ + return htonl(value); +} + +static uint16 +htons(uint16 value) +{ + uint16 ret; + if (is_little_endian()) { + ret = value; + swap16((uint8 *)&ret); + return ret; + } + + return value; +} + +static uint16 +ntohs(uint16 value) +{ + return htons(value); +} + +/* Coming from musl, under MIT license */ +static int +__inet_aton(const char *s0, struct in_addr *dest) +{ + const char *s = s0; + unsigned char *d = (void *)dest; + unsigned long a[4] = { 0 }; + char *z; + int i; + + for (i = 0; i < 4; i++) { + a[i] = strtoul(s, &z, 0); + if (z == s || (*z && *z != '.') || !isdigit(*s)) + return 0; + if (!*z) + break; + s = z + 1; + } + if (i == 4) + return 0; + switch (i) { + case 0: + a[1] = a[0] & 0xffffff; + a[0] >>= 24; + case 1: + a[2] = a[1] & 0xffff; + a[1] >>= 16; + case 2: + a[3] = a[2] & 0xff; + a[2] >>= 8; + } + for (i = 0; i < 4; i++) { + if (a[i] > 255) + return 0; + d[i] = a[i]; + } + return 1; +} + +/* Coming from musl, under MIT license */ +static int +inet_addr(const char *p) +{ + struct in_addr a; + if (!__inet_aton(p, &a)) + return -1; + return a.s_addr; +} + +static int +inet_network(const char *p) +{ + return ntohl(inet_addr(p)); +} +/** In-enclave implementation of POSIX functions end **/ + +static int +textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr_in *out) +{ + assert(textual); + + out->sin_family = AF_INET; + out->sin_port = htons(port); + out->sin_addr.s_addr = inet_addr(textual); + + return BHT_OK; +} + int socket(int domain, int type, int protocol) { @@ -232,67 +405,219 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, unsigned int *addrlen) { - errno = ENOSYS; - return -1; + struct sockaddr addr_tmp; + unsigned int len = sizeof(struct sockaddr); + + if (ocall_accept(sock, server_sock, &addr_tmp, &len, len) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (*sock < 0) { + errno = get_errno(); + return BHT_ERROR; + } + + return BHT_OK; } int os_socket_bind(bh_socket_t socket, const char *host, int *port) { - errno = ENOSYS; - return -1; + struct sockaddr_in addr; + struct linger ling; + unsigned int socklen; + int ret; + + assert(host); + assert(port); + + ling.l_onoff = 1; + ling.l_linger = 0; + + if (ocall_fcntl_long(&ret, socket, F_SETFD, FD_CLOEXEC) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret < 0) { + goto fail; + } + + if (ocall_setsockopt(&ret, socket, SOL_SOCKET, SO_LINGER, &ling, + sizeof(ling)) + != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret < 0) { + goto fail; + } + + addr.sin_addr.s_addr = inet_addr(host); + addr.sin_port = htons(*port); + addr.sin_family = AF_INET; + + if (ocall_bind(&ret, socket, &addr, sizeof(addr)) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret < 0) { + goto fail; + } + + socklen = sizeof(addr); + + if (ocall_getsockname(&ret, socket, (void *)&addr, &socklen, socklen) + != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret == -1) { + goto fail; + } + + *port = ntohs(addr.sin_port); + + return BHT_OK; + +fail: + errno = get_errno(); + return BHT_ERROR; } int os_socket_close(bh_socket_t socket) { - errno = ENOSYS; - return -1; + int ret; + + if (ocall_close(&ret, socket) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret == -1) + errno = get_errno(); + + return ret; } int os_socket_connect(bh_socket_t socket, const char *addr, int port) -{} +{ + struct sockaddr_in addr_in = { 0 }; + socklen_t addr_len = sizeof(struct sockaddr_in); + int ret = 0; + + if ((ret = textual_addr_to_sockaddr(addr, port, &addr_in)) < 0) { + return ret; + } + + if (ocall_connect(&ret, socket, &addr_in, addr_len) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret == -1) + errno = get_errno(); + + return ret; +} int os_socket_create(bh_socket_t *sock, int tcp_or_udp) { - errno = ENOSYS; - return -1; + if (!sock) { + return BHT_ERROR; + } + + if (1 == tcp_or_udp) { + if (ocall_socket(sock, AF_INET, SOCK_STREAM, IPPROTO_TCP) + != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + } + else if (0 == tcp_or_udp) { + if (ocall_socket(sock, AF_INET, SOCK_DGRAM, 0) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + } + + if (*sock == -1) { + errno = get_errno(); + return BHT_ERROR; + } + + return BHT_OK; } int os_socket_inet_network(const char *cp, uint32 *out) { - errno = ENOSYS; - return -1; + if (!cp) + return BHT_ERROR; + + *out = inet_network(cp); + + return BHT_OK; } int os_socket_listen(bh_socket_t socket, int max_client) { - errno = ENOSYS; - return -1; + int ret; + + if (ocall_listen(&ret, socket, max_client) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret == -1) + errno = get_errno(); + + return ret; } int os_socket_recv(bh_socket_t socket, void *buf, unsigned int len) { - errno = ENOSYS; - return -1; + int ret; + + if (ocall_recv(&ret, socket, buf, len, 0) != SGX_SUCCESS) { + errno = ENOSYS; + return -1; + } + + if (ret == -1) + errno = get_errno(); + + return ret; } int os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) { - errno = ENOSYS; - return -1; + int ret; + + if (ocall_send(&ret, socket, buf, len, 0) != SGX_SUCCESS) { + errno = ENOSYS; + return -1; + } + + if (ret == -1) + errno = get_errno(); + + return ret; } int os_socket_shutdown(bh_socket_t socket) { - errno = ENOSYS; - return -1; + return shutdown(socket, O_RDWR); } #endif diff --git a/core/shared/platform/linux-sgx/sgx_socket.h b/core/shared/platform/linux-sgx/sgx_socket.h index 6e5b0438..7dc05fce 100644 --- a/core/shared/platform/linux-sgx/sgx_socket.h +++ b/core/shared/platform/linux-sgx/sgx_socket.h @@ -14,11 +14,12 @@ extern "C" { #define SOL_SOCKET 1 +#define SO_TYPE 3 +#define SO_LINGER 13 + #define SOCK_STREAM 1 #define SOCK_DGRAM 2 -#define SO_TYPE 3 - #define MSG_OOB 0x0001 #define MSG_PEEK 0x0002 #define MSG_DONTROUTE 0x0004 @@ -44,6 +45,16 @@ extern "C" { #define SHUT_WR 1 #define SHUT_RDWR 2 +/* Address families. */ +#define AF_INET 2 /* IP protocol family. */ + +/* Standard well-defined IP protocols. */ +#define IPPROTO_TCP 6 /* Transmission Control Protocol. */ + +/* Types of sockets. */ +#define SOCK_DGRAM \ + 2 /* Connectionless, unreliable datagrams of fixed maximum length. */ + struct msghdr { void *msg_name; socklen_t msg_namelen; @@ -54,6 +65,36 @@ struct msghdr { int msg_flags; }; +/* Internet address. */ +struct in_addr { + uint32_t s_addr; +}; +typedef struct in_addr in_addr_t; + +/* Structure describing an Internet socket address. */ +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr_in { + uint16_t sin_family; + uint16_t sin_port; /* Port number. */ + struct in_addr sin_addr; /* Internet address. */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char__pad[__SOCK_SIZE__ - sizeof(uint16_t) - sizeof(uint16_t) + - sizeof(struct in_addr)]; +}; + +/* Structure used to manipulate the SO_LINGER option. */ +struct linger { + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger. */ +}; + +/* Structure describing a generic socket address. */ +struct sockaddr { + unsigned short int sa_family; /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ +}; + int socket(int domain, int type, int protocol); diff --git a/core/shared/platform/linux-sgx/sgx_wamr.edl b/core/shared/platform/linux-sgx/sgx_wamr.edl index 0a47fcbb..a5ce1897 100644 --- a/core/shared/platform/linux-sgx/sgx_wamr.edl +++ b/core/shared/platform/linux-sgx/sgx_wamr.edl @@ -118,19 +118,34 @@ enclave { int ocall_pthread_rwlock_unlock([user_check]void *rwlock); int ocall_get_errno(); - int ocall_socket(int domain, int type, int protocol); + + /* sockets */ + int ocall_accept(int sockfd, [in, size=addr_size]void *addr, + [in, size=4] uint32_t *addrlen, uint32_t addr_size); + int ocall_bind(int sockfd, [in, size=addrlen]const void *addr, + uint32_t addrlen); + int ocall_connect(int sockfd, [in, size=addrlen]void *addr, uint32_t addrlen); + int ocall_getsockname(int sockfd, [in, size=addr_size]void *addr, + [in, out, size=4]uint32_t *addrlen, uint32_t addr_size); int ocall_getsockopt(int sockfd, int level, int optname, [out, size=val_buf_size]void *val_buf, unsigned int val_buf_size, [in, out, size=4]void *len_buf); - ssize_t ocall_sendmsg(int sockfd, - [in, size=msg_buf_size]void *msg_buf, - unsigned int msg_buf_size, - int flags); + int ocall_listen(int sockfd, int backlog); + int ocall_recv(int sockfd, [out, size=len]void *buf, size_t len, int flags); ssize_t ocall_recvmsg(int sockfd, [in, out, size=msg_buf_size]void *msg_buf, unsigned int msg_buf_size, int flags); + int ocall_send(int sockfd, [in, size=len]const void *buf, size_t len, int flags); + ssize_t ocall_sendmsg(int sockfd, + [in, size=msg_buf_size]void *msg_buf, + unsigned int msg_buf_size, + int flags); + int ocall_setsockopt(int sockfd, int level, int optname, + [in, size=optlen]void *optval, + unsigned int optlen); int ocall_shutdown(int sockfd, int how); + int ocall_socket(int domain, int type, int protocol); }; }; diff --git a/core/shared/platform/linux-sgx/untrusted/socket.c b/core/shared/platform/linux-sgx/untrusted/socket.c index 08d884bb..b9f3b2a5 100644 --- a/core/shared/platform/linux-sgx/untrusted/socket.c +++ b/core/shared/platform/linux-sgx/untrusted/socket.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include int ocall_socket(int domain, int type, int protocol) @@ -72,4 +74,53 @@ int ocall_shutdown(int sockfd, int how) { return shutdown(sockfd, how); +} + +int +ocall_setsockopt(int sockfd, int level, int optname, void *optval, + unsigned int optlen) +{ + return setsockopt(sockfd, level, optname, optval, optlen); +} + +int +ocall_bind(int sockfd, const void *addr, uint32_t addrlen) +{ + return bind(sockfd, (const struct sockaddr *)addr, addrlen); +} + +int +ocall_getsockname(int sockfd, void *addr, uint32_t *addrlen, uint32_t addr_size) +{ + return getsockname(sockfd, (struct sockaddr *)addr, addrlen); +} + +int +ocall_listen(int sockfd, int backlog) +{ + return listen(sockfd, backlog); +} + +int +ocall_accept(int sockfd, void *addr, uint32_t *addrlen, uint32_t addr_size) +{ + return accept(sockfd, (struct sockaddr *)addr, addrlen); +} + +int +ocall_recv(int sockfd, void *buf, size_t len, int flags) +{ + return recv(sockfd, buf, len, flags); +} + +int +ocall_send(int sockfd, const void *buf, size_t len, int flags) +{ + return send(sockfd, buf, len, flags); +} + +int +ocall_connect(int sockfd, void *addr, uint32_t addrlen) +{ + return connect(sockfd, (const struct sockaddr *)addr, addrlen); } \ No newline at end of file diff --git a/doc/socket_api.md b/doc/socket_api.md index 91f668e5..203a0e64 100644 --- a/doc/socket_api.md +++ b/doc/socket_api.md @@ -10,7 +10,7 @@ and `socket()`. Users can call those functions in WebAssembly code directly. Those WebAssembly socket calls will be dispatched to the imported functions and eventually will be implemented by host socket APIs. -This document introduces a way to support _Berkeley/Posix Socket APIs_ in +This document introduces a way to support the _Berkeley/POSIX Socket API_ in WebAssembly code. ## Patch the native code @@ -24,7 +24,7 @@ native source code. #endif ``` -`__wasi__` is a Marco defined by WASI. The host compiler will not enable it. +`__wasi__` is a macro defined by WASI. The host compiler will not enable it. ## CMake files @@ -57,10 +57,25 @@ The _iwasm_ should be compiled with `WAMR_BUILD_LIBC_WASI=1`. By default, it is enabled. _iwasm_ accepts address ranges via an option, `--addr-pool`, to implement -the capability control. All IP address the WebAssebmly application may need to `bind()` or `connect()` should be announced first. Every IP address should be in CIRD notation. +the capability control. All IP address the WebAssembly application may need to `bind()` or `connect()` +should be announced first. Every IP address should be in CIRD notation. ```bash $ iwasm --addr-pool=1.2.3.4/15,2.3.4.6/16 socket_example.wasm ``` Refer to [socket api sample](../samples/socket-api) for more details. + +## Intel SGX support + +WAMR also supports the socket API within Intel SGX enclaves. + +The _iwasm_ should be compiled with `WAMR_BUILD_LIBC_WASI=1` and `WAMR_BUILD_LIB_PTHREAD=1`, which are enabled by default. + +Similarly to running _iwasm_ outside of an enclave, the allowed address ranges are given via the option `--addr-pool`. + +```bash +$ iwasm --addr-pool=1.2.3.4/15,2.3.4.6/16 socket_example.wasm +``` + +Refer to [socket api sample](../samples/socket-api) for the compilation of the Wasm applications and [_iwasm_ for Intel SGX](../product-mini/platforms/linux-sgx) for the Wasm runtime. \ No newline at end of file diff --git a/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp b/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp index bd6b0e36..ba269d34 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp @@ -227,6 +227,10 @@ print_help() printf(" --dir= Grant wasi access to the given host directories\n"); printf(" to the program, for example:\n"); printf(" --dir= --dir=\n"); + printf(" --addr-pool= Grant wasi access to the given network addresses in\n"); + printf(" CIRD notation to the program, seperated with ',',\n"); + printf(" for example:\n"); + printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n"); printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n"); return 1; } @@ -550,9 +554,10 @@ app_instance_func(void *wasm_module_inst, const char *func_name, int app_argc, static bool set_wasi_args(void *wasm_module, const char **dir_list, uint32_t dir_list_size, const char **env_list, uint32_t env_list_size, int stdinfd, - int stdoutfd, int stderrfd, char **argv, uint32_t argc) + int stdoutfd, int stderrfd, char **argv, uint32_t argc, + const char **addr_pool, uint32_t addr_pool_size) { - uint64_t ecall_args[10]; + uint64_t ecall_args[12]; ecall_args[0] = (uint64_t)(uintptr_t)wasm_module; ecall_args[1] = (uint64_t)(uintptr_t)dir_list; @@ -564,9 +569,11 @@ set_wasi_args(void *wasm_module, const char **dir_list, uint32_t dir_list_size, ecall_args[7] = stderrfd; ecall_args[8] = (uint64_t)(uintptr_t)argv; ecall_args[9] = argc; + ecall_args[10] = (uint64_t)(uintptr_t)addr_pool; + ecall_args[11] = addr_pool_size; if (SGX_SUCCESS != ecall_handle_command(g_eid, CMD_SET_WASI_ARGS, (uint8_t *)ecall_args, - sizeof(uint64_t) * 10)) { + sizeof(uint64_t) * 12)) { printf("Call ecall_handle_command() failed.\n"); } @@ -590,6 +597,8 @@ main(int argc, char *argv[]) uint32_t dir_list_size = 0; const char *env_list[8] = { NULL }; uint32_t env_list_size = 0; + const char *addr_pool[8] = { NULL }; + uint32_t addr_pool_size = 0; uint32_t max_thread_num = 4; if (enclave_init(&g_eid) < 0) { @@ -666,6 +675,26 @@ main(int argc, char *argv[]) return print_help(); } } + /* TODO: parse the configuration file via --addr-pool-file */ + else if (!strncmp(argv[0], "--addr-pool=", strlen("--addr-pool="))) { + /* like: --addr-pool=100.200.244.255/30 */ + char *token = NULL; + + if ('\0' == argv[0][12]) + return print_help(); + + token = strtok(argv[0] + strlen("--addr-pool="), ","); + while (token) { + if (addr_pool_size >= sizeof(addr_pool) / sizeof(char *)) { + printf("Only allow max address number %d\n", + (int)(sizeof(addr_pool) / sizeof(char *))); + return -1; + } + + addr_pool[addr_pool_size++] = token; + token = strtok(NULL, ";"); + } + } else if (!strncmp(argv[0], "--max-threads=", 14)) { if (argv[0][14] == '\0') return print_help(); @@ -705,7 +734,8 @@ main(int argc, char *argv[]) /* Set wasi arguments */ if (!set_wasi_args(wasm_module, dir_list, dir_list_size, env_list, - env_list_size, 0, 1, 2, argv, argc)) { + env_list_size, 0, 1, 2, argv, argc, addr_pool, + addr_pool_size)) { printf("%s\n", "set wasi arguments failed.\n"); goto fail3; } @@ -771,6 +801,8 @@ wamr_pal_create_process(struct wamr_pal_create_process_args *args) uint32_t dir_list_size = 0; const char *env_list[8] = { NULL }; uint32_t env_list_size = 0; + const char *addr_pool[8] = { NULL }; + uint32_t addr_pool_size = 0; uint32_t max_thread_num = 4; char *wasm_files[16]; void *wasm_module_inst[16]; @@ -845,7 +877,7 @@ wamr_pal_create_process(struct wamr_pal_create_process_args *args) /* Set wasi arguments */ if (!set_wasi_args(wasm_module, dir_list, dir_list_size, env_list, env_list_size, stdinfd, stdoutfd, stderrfd, argv, - argc)) { + argc, addr_pool, addr_pool_size)) { printf("%s\n", "set wasi arguments failed.\n"); unload_module(wasm_module); free(wasm_file_buf); diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index c20abdc1..35367e08 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -50,6 +50,8 @@ typedef struct EnclaveModule { uint32 wasi_dir_list_size; char **wasi_env_list; uint32 wasi_env_list_size; + char **wasi_addr_pool_list; + uint32 wasi_addr_pool_list_size; char **wasi_argv; uint32 wasi_argc; bool is_xip_file; @@ -407,6 +409,8 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) char **wasi_argv = *(char ***)args++; char *p, *p1; uint32 wasi_argc = *(uint32 *)args++; + char **addr_pool_list = *(char ***)args++; + uint32 addr_pool_list_size = *(uint32 *)args++; uint64 total_size = 0; int32 i, str_len; @@ -414,6 +418,7 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) total_size += sizeof(char *) * (uint64)dir_list_size + sizeof(char *) * (uint64)env_list_size + + sizeof(char *) * (uint64)addr_pool_list_size + sizeof(char *) * (uint64)wasi_argc; for (i = 0; i < dir_list_size; i++) { @@ -424,6 +429,10 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) total_size += strlen(env_list[i]) + 1; } + for (i = 0; i < addr_pool_list_size; i++) { + total_size += strlen(addr_pool_list[i]) + 1; + } + for (i = 0; i < wasi_argc; i++) { total_size += strlen(wasi_argv[i]) + 1; } @@ -436,7 +445,7 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) } p1 = p + sizeof(char *) * dir_list_size + sizeof(char *) * env_list_size - + sizeof(char *) * wasi_argc; + + sizeof(char *) * addr_pool_list_size + sizeof(char *) * wasi_argc; if (dir_list_size > 0) { enclave_module->wasi_dir_list = (char **)p; @@ -462,6 +471,18 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) p += sizeof(char *) * env_list_size; } + if (addr_pool_list_size > 0) { + enclave_module->wasi_addr_pool_list = (char **)p; + enclave_module->wasi_addr_pool_list_size = addr_pool_list_size; + for (i = 0; i < addr_pool_list_size; i++) { + enclave_module->wasi_addr_pool_list[i] = p1; + str_len = strlen(addr_pool_list[i]); + bh_memcpy_s(p1, str_len + 1, addr_pool_list[i], str_len + 1); + p1 += str_len + 1; + } + p += sizeof(char *) * addr_pool_list_size; + } + if (wasi_argc > 0) { enclave_module->wasi_argv = (char **)p; enclave_module->wasi_argc = wasi_argc; @@ -481,6 +502,11 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) (stdinfd != -1) ? stdinfd : 0, (stdoutfd != -1) ? stdoutfd : 1, (stderrfd != -1) ? stderrfd : 2); + wasm_runtime_set_wasi_addr_pool( + enclave_module->module, + (const char **)enclave_module->wasi_addr_pool_list, + addr_pool_list_size); + *args_org = true; } #else