diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 385aa15c..8fcf455a 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -614,14 +614,21 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, } // Picks an unused slot from the file descriptor table. -static __wasi_fd_t -fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock) +static __wasi_errno_t +fd_table_unused(struct fd_table *ft, __wasi_fd_t *out) REQUIRES_SHARED(ft->lock) { assert(ft->size > ft->used && "File descriptor table has no free slots"); for (;;) { - __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size); - if (ft->entries[fd].object == NULL) - return fd; + uintmax_t random_fd = 0; + __wasi_errno_t error = random_uniform(ft->size, &random_fd); + + if (error != __WASI_ESUCCESS) + return error; + + if (ft->entries[(__wasi_fd_t)random_fd].object == NULL) { + *out = (__wasi_fd_t)random_fd; + return error; + } } } @@ -641,10 +648,14 @@ fd_table_insert(wasm_exec_env_t exec_env, struct fd_table *ft, return convert_errno(errno); } - *out = fd_table_unused(ft); + __wasi_errno_t error = fd_table_unused(ft, out); + + if (error != __WASI_ESUCCESS) + return error; + fd_table_attach(ft, *out, fo, rights_base, rights_inheriting); rwlock_unlock(&ft->lock); - return 0; + return error; } // Inserts a numerical file descriptor into the file descriptor table. @@ -2282,8 +2293,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_errno_t wasmtime_ssp_random_get(void *buf, size_t nbyte) { - random_buf(buf, nbyte); - return 0; + return random_buf(buf, nbyte); } __wasi_errno_t diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c index b21aa197..29c50dd8 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c @@ -13,14 +13,16 @@ #include "ssp_config.h" #include "bh_platform.h" +#include "libc_errno.h" #include "random.h" #if CONFIG_HAS_ARC4RANDOM_BUF -void +__wasi_errno_t random_buf(void *buf, size_t len) { arc4random_buf(buf, len); + return __WASI_ESUCCESS; } #elif CONFIG_HAS_GETRANDOM @@ -29,7 +31,7 @@ random_buf(void *buf, size_t len) #include #endif -void +__wasi_errno_t random_buf(void *buf, size_t len) { for (;;) { @@ -37,57 +39,71 @@ random_buf(void *buf, size_t len) if (x < 0) { if (errno == EINTR) continue; - os_printf("getrandom failed: %s", strerror(errno)); - abort(); + return convert_errno(errno); } if ((size_t)x == len) - return; + break; buf = (void *)((unsigned char *)buf + x); len -= (size_t)x; } + return __WASI_ESUCCESS; } #elif defined(BH_PLATFORM_WINDOWS) -#include +#include +#pragma comment(lib, "Bcrypt.lib") -void +__wasi_errno_t random_buf(void *buf, size_t len) { - static int crypt_initialized = 0; - static HCRYPTPROV provider; - if (!crypt_initialized) { - CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT); - crypt_initialized = 1; - } - CryptGenRandom(provider, len, buf); + NTSTATUS ret = + BCryptGenRandom(NULL, buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG); + + // Since we pass NULL for the algorithm handle, the only way BCryptGenRandom + // can fail is if one of the parameters is invalid + // (STATUS_INVALID_PARAMETER). + return ret ? __WASI_EINVAL : __WASI_ESUCCESS; } #else -static int urandom; +static int urandom = -1; +static __wasi_errno_t urandom_error = __WASI_ESUCCESS; static void open_urandom(void) { urandom = open("/dev/urandom", O_RDONLY); - if (urandom < 0) { - os_printf("Failed to open /dev/urandom\n"); - abort(); - } + if (urandom < 0) + urandom_error = convert_errno(errno); } -void +__wasi_errno_t random_buf(void *buf, size_t len) { static pthread_once_t open_once = PTHREAD_ONCE_INIT; - pthread_once(&open_once, open_urandom); + int pthread_ret = pthread_once(&open_once, open_urandom); - if ((size_t)read(urandom, buf, len) != len) { - os_printf("Short read on /dev/urandom\n"); - abort(); + if (pthread_ret != 0) + return convert_errno(pthread_ret); + + if (urandom < 0) + return urandom_error; + + size_t bytes_read = 0; + + while (bytes_read < len) { + ssize_t bytes_read_now = + read(urandom, buf + bytes_read, len - bytes_read); + + if (bytes_read_now < 0) + return convert_errno(errno); + + bytes_read += (size_t)bytes_read_now; } + + return __WASI_ESUCCESS; } #endif @@ -99,8 +115,8 @@ random_buf(void *buf, size_t len) // arc4random() until it lies within the range [2^k % upper, 2^k). As // this range has length k * upper, we can safely obtain a number // without any modulo bias. -uintmax_t -random_uniform(uintmax_t upper) +__wasi_errno_t +random_uniform(uintmax_t upper, uintmax_t *out) { // Compute 2^k % upper // == (2^k - upper) % upper @@ -108,8 +124,14 @@ random_uniform(uintmax_t upper) uintmax_t lower = -upper % upper; for (;;) { uintmax_t value; - random_buf(&value, sizeof(value)); - if (value >= lower) - return value % upper; + __wasi_errno_t error = random_buf(&value, sizeof(value)); + + if (error != __WASI_ESUCCESS) + return error; + + if (value >= lower) { + *out = value % upper; + return error; + } } } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h index 23c2da4d..7cd94d74 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h @@ -14,8 +14,12 @@ #ifndef RANDOM_H #define RANDOM_H -void +#include "bh_platform.h" + +__wasi_errno_t random_buf(void *, size_t); -uintmax_t random_uniform(uintmax_t); + +__wasi_errno_t +random_uniform(uintmax_t upper, uintmax_t *out); #endif