Bug 1723447 - Get latest rlbox, wasm2c plugin, rt, compiler for 32bit platform support r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D121503
This commit is contained in:
shravanrn@gmail.com 2021-08-04 21:37:45 +00:00
Родитель f1aac2b3e6
Коммит ac42d89404
9 изменённых файлов: 146 добавлений и 152 удалений

Просмотреть файл

@ -9,8 +9,8 @@ origin:
description: rlbox integration for the wasm2c sandboxed code
url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox
release: commit 1cd3e4165d30d3ecc30974744e6fd52caa2a3f1d (2021-07-23T02:53:22Z).
revision: 1cd3e4165d30d3ecc30974744e6fd52caa2a3f1d
release: commit e92b497df1ee919182a95433c477f4998ca451bb (2021-07-31T07:25:03Z).
revision: e92b497df1ee919182a95433c477f4998ca451bb
license: MIT
license-file: LICENSE

Просмотреть файл

@ -9,8 +9,8 @@ origin:
description: wasm2c fork used for rlbox sandboxing
url: https://github.com/PLSysSec/wasm2c_sandbox_compiler
release: commit df7630a80686c1e3bc775a6cb261841e99484b54 (2021-07-28T00:22:29Z).
revision: df7630a80686c1e3bc775a6cb261841e99484b54
release: commit 8b0e6e8c96d534698bf8c2cf0c860883ec2b7d34 (2021-08-04T21:00:09Z).
revision: 8b0e6e8c96d534698bf8c2cf0c860883ec2b7d34
license: Apache-2.0
license-file: LICENSE

Просмотреть файл

@ -397,7 +397,7 @@ protected:
detail::dynamic_check(sandbox == nullptr, "Sandbox already initialized");
#if defined(_WIN32)
library = LoadLibraryA(wasm2c_module_path);
library = (void*) LoadLibraryA(wasm2c_module_path);
#else
library = dlopen(wasm2c_module_path, RTLD_LAZY);
#endif
@ -439,16 +439,16 @@ protected:
detail::dynamic_check(sandbox_memory_info != nullptr, "Could not get wasm2c sandbox memory info");
heap_base = reinterpret_cast<uintptr_t>(impl_get_memory_location());
// Check that the address space is larger than the sandbox heap i.e. 4GB
// sandbox heap, host has to have more than 4GB
static_assert(sizeof(uintptr_t) > sizeof(T_PointerType));
// Check that the heap is aligned to the pointer size i.e. 32-bit pointer =>
// aligned to 4GB. The implementations of
// impl_get_unsandboxed_pointer_no_ctx and impl_get_sandboxed_pointer_no_ctx
// below rely on this.
uintptr_t heap_offset_mask = std::numeric_limits<T_PointerType>::max();
detail::dynamic_check((heap_base & heap_offset_mask) == 0,
"Sandbox heap not aligned to 4GB");
if constexpr (sizeof(uintptr_t) != sizeof(uint32_t)) {
// On larger platforms, check that the heap is aligned to the pointer size
// i.e. 32-bit pointer => aligned to 4GB. The implementations of
// impl_get_unsandboxed_pointer_no_ctx and impl_get_sandboxed_pointer_no_ctx
// below rely on this.
uintptr_t heap_offset_mask = std::numeric_limits<T_PointerType>::max();
detail::dynamic_check((heap_base & heap_offset_mask) == 0,
"Sandbox heap not aligned to 4GB");
}
// cache these for performance
exec_env = sandbox;
@ -509,7 +509,11 @@ protected:
}
return static_cast<T_PointerType>(slot_number);
} else {
return static_cast<T_PointerType>(reinterpret_cast<uintptr_t>(p));
if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) {
return static_cast<T_PointerType>(reinterpret_cast<uintptr_t>(p) - heap_base);
} else {
return static_cast<T_PointerType>(reinterpret_cast<uintptr_t>(p));
}
}
}
@ -520,20 +524,26 @@ protected:
rlbox_wasm2c_sandbox* (*expensive_sandbox_finder)(
const void* example_unsandboxed_ptr))
{
if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
// swizzling function pointers needs access to the function pointer tables
// and thus cannot be done without context
// on 32-bit platforms we don't assume the heap is aligned
if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) {
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
return sandbox->impl_get_unsandboxed_pointer<T>(p);
} else {
// grab the memory base from the example_unsandboxed_ptr
uintptr_t heap_base_mask =
std::numeric_limits<uintptr_t>::max() &
~(static_cast<uintptr_t>(std::numeric_limits<T_PointerType>::max()));
uintptr_t computed_heap_base =
reinterpret_cast<uintptr_t>(example_unsandboxed_ptr) & heap_base_mask;
uintptr_t ret = computed_heap_base | p;
return reinterpret_cast<void*>(ret);
if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
// swizzling function pointers needs access to the function pointer tables
// and thus cannot be done without context
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
return sandbox->impl_get_unsandboxed_pointer<T>(p);
} else {
// grab the memory base from the example_unsandboxed_ptr
uintptr_t heap_base_mask =
std::numeric_limits<uintptr_t>::max() &
~(static_cast<uintptr_t>(std::numeric_limits<T_PointerType>::max()));
uintptr_t computed_heap_base =
reinterpret_cast<uintptr_t>(example_unsandboxed_ptr) & heap_base_mask;
uintptr_t ret = computed_heap_base | p;
return reinterpret_cast<void*>(ret);
}
}
}
@ -544,17 +554,23 @@ protected:
rlbox_wasm2c_sandbox* (*expensive_sandbox_finder)(
const void* example_unsandboxed_ptr))
{
if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
// swizzling function pointers needs access to the function pointer tables
// and thus cannot be done without context
// on 32-bit platforms we don't assume the heap is aligned
if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) {
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
return sandbox->impl_get_sandboxed_pointer<T>(p);
} else {
// Just clear the memory base to leave the offset
RLBOX_WASM2C_UNUSED(example_unsandboxed_ptr);
uintptr_t ret = reinterpret_cast<uintptr_t>(p) &
std::numeric_limits<T_PointerType>::max();
return static_cast<T_PointerType>(ret);
if constexpr (std::is_function_v<std::remove_pointer_t<T>>) {
// swizzling function pointers needs access to the function pointer tables
// and thus cannot be done without context
auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr);
return sandbox->impl_get_sandboxed_pointer<T>(p);
} else {
// Just clear the memory base to leave the offset
RLBOX_WASM2C_UNUSED(example_unsandboxed_ptr);
uintptr_t ret = reinterpret_cast<uintptr_t>(p) &
std::numeric_limits<T_PointerType>::max();
return static_cast<T_PointerType>(ret);
}
}
}
@ -580,7 +596,7 @@ protected:
inline size_t impl_get_total_memory() { return sandbox_memory_info->size; }
inline void* impl_get_memory_location()
inline void* impl_get_memory_location() const
{
return sandbox_memory_info->data;
}
@ -695,8 +711,10 @@ protected:
inline T_PointerType impl_malloc_in_sandbox(size_t size)
{
detail::dynamic_check(size <= std::numeric_limits<uint32_t>::max(),
"Attempting to malloc more than the heap size");
if constexpr(sizeof(size) > sizeof(uint32_t)) {
detail::dynamic_check(size <= std::numeric_limits<uint32_t>::max(),
"Attempting to malloc more than the heap size");
}
using T_Func = void*(size_t);
using T_Converted = T_PointerType(uint32_t);
T_PointerType ret = impl_invoke_with_func_ptr<T_Func, T_Converted>(

15
third_party/wasm2c/src/c-writer.cc поставляемый
Просмотреть файл

@ -159,7 +159,6 @@ class CWriter {
void PopLabel();
static std::string AddressOf(const std::string&);
static std::string Deref(const std::string&);
static char MangleType(Type);
static std::string MangleTypes(const TypeVector&);
@ -382,11 +381,6 @@ std::string CWriter::AddressOf(const std::string& s) {
return "(&" + s + ")";
}
// static
std::string CWriter::Deref(const std::string& s) {
return "(*" + s + ")";
}
// static
char CWriter::MangleType(Type type) {
switch (type) {
@ -489,7 +483,7 @@ std::string CWriter::DefineImportName(const std::string& name,
import_syms_.insert(name);
global_syms_.insert(mangled);
global_sym_map_.insert(SymbolMap::value_type(name, mangled));
return "(*" + mangled + ")";
return mangled;
}
std::string CWriter::DefineGlobalScopeName(const std::string& name) {
@ -600,12 +594,7 @@ void CWriter::Write(const ExternalPtr& name) {
}
void CWriter::Write(const ExternalRef& name) {
bool is_import = import_syms_.count(name.name) != 0;
if (is_import) {
Write(Deref(GetGlobalName(name.name)));
} else {
Write(GetGlobalName(name.name));
}
Write(GetGlobalName(name.name));
}
void CWriter::Write(const Var& var) {

Просмотреть файл

@ -50,7 +50,7 @@ const char SECTION_NAME(declarations)[] =
"#define MEMCHECK(mem, a, t)\n"
"#else\n"
"#define MEMCHECK(mem, a, t) \\\n"
" if (UNLIKELY((a) + sizeof(t) > mem->size)) TRAP(OOB)\n"
" if (UNLIKELY((a) + sizeof(t) > mem->size)) (void) TRAP(OOB)\n"
"#endif\n"
"\n"
"#if defined(WASM_USING_GLOBAL_HEAP)\n"

2
third_party/wasm2c/src/wasm2c.c.tmpl поставляемый
Просмотреть файл

@ -47,7 +47,7 @@
#define MEMCHECK(mem, a, t)
#else
#define MEMCHECK(mem, a, t) \
if (UNLIKELY((a) + sizeof(t) > mem->size)) TRAP(OOB)
if (UNLIKELY((a) + sizeof(t) > mem->size)) (void) TRAP(OOB)
#endif
#if defined(WASM_USING_GLOBAL_HEAP)

54
third_party/wasm2c/wasm2c/wasm-rt-impl.c поставляемый
Просмотреть файл

@ -26,7 +26,7 @@
#include <stdlib.h>
#include <string.h>
#define PAGE_SIZE 65536
#define WASM_PAGE_SIZE 65536
void wasm_rt_trap(wasm_rt_trap_t code) {
assert(code != WASM_RT_TRAP_NONE);
@ -99,15 +99,28 @@ void wasm_rt_cleanup_func_types(wasm_func_type_t** p_func_type_structs, uint32_t
void wasm_rt_allocate_memory(wasm_rt_memory_t* memory,
uint32_t initial_pages,
uint32_t max_pages) {
uint32_t byte_length = initial_pages * PAGE_SIZE;
uint32_t byte_length = initial_pages * WASM_PAGE_SIZE;
#if WASM_USING_GUARD_PAGES == 1
/* Reserve 8GiB. */
const uint64_t heap_alignment = 0x100000000ul;
/* Reserve 8GiB, aligned to 4GB. */
const size_t heap_alignment = 0x100000000ull;
const size_t reserve_size = 0x200000000ull;
const uint32_t chosen_max_pages = max_pages;
#else
/* Reserve 8MB, aligned to 8MB. */
const size_t heap_alignment = 0x800000ul;
const size_t reserve_size = 0x800000ul;
const uint32_t allowed_max_pages = reserve_size / WASM_PAGE_SIZE;
uint32_t chosen_max_pages = max_pages;
if (allowed_max_pages < max_pages) {
chosen_max_pages = allowed_max_pages;
}
#endif
void* addr = NULL;
const uint64_t retries = 10;
for (uint64_t i = 0; i < retries; i++) {
addr = os_mmap_aligned(NULL, 0x200000000ul, MMAP_PROT_NONE, MMAP_MAP_NONE, heap_alignment, 0 /* alignment_offset */);
addr = os_mmap_aligned(NULL, reserve_size, MMAP_PROT_NONE, MMAP_MAP_NONE, heap_alignment, 0 /* alignment_offset */);
if (addr) {
break;
}
@ -126,12 +139,10 @@ void wasm_rt_allocate_memory(wasm_rt_memory_t* memory,
// Summary: malloc of a struct, followed by a write to the constant fields is still defined behavior iff
// there is no prior read of the field
*(uint8_t**) &memory->data = addr;
#else
memory->data = calloc(byte_length, 1);
#endif
memory->size = byte_length;
memory->pages = initial_pages;
memory->max_pages = max_pages;
memory->max_pages = chosen_max_pages;
#if defined(WASM_CHECK_SHADOW_MEMORY)
wasm2c_shadow_memory_create(memory);
@ -140,10 +151,12 @@ void wasm_rt_allocate_memory(wasm_rt_memory_t* memory,
void wasm_rt_deallocate_memory(wasm_rt_memory_t* memory) {
#if WASM_USING_GUARD_PAGES == 1
os_munmap(memory->data, 0x200000000ul);
const size_t reserve_size = 0x200000000ull;
#else
os_munmap(memory->data, memory->size);
const size_t reserve_size = 0x800000ul;
#endif
os_munmap(memory->data, reserve_size);
#if defined(WASM_CHECK_SHADOW_MEMORY)
wasm2c_shadow_memory_destroy(memory);
#endif
@ -158,25 +171,14 @@ uint32_t wasm_rt_grow_memory(wasm_rt_memory_t* memory, uint32_t delta) {
if (new_pages < old_pages || new_pages > memory->max_pages) {
return (uint32_t)-1;
}
uint32_t old_size = old_pages * PAGE_SIZE;
uint32_t new_size = new_pages * PAGE_SIZE;
uint32_t delta_size = delta * PAGE_SIZE;
uint32_t old_size = old_pages * WASM_PAGE_SIZE;
uint32_t new_size = new_pages * WASM_PAGE_SIZE;
uint32_t delta_size = delta * WASM_PAGE_SIZE;
#if WASM_USING_GUARD_PAGES == 1
int ret = os_mmap_commit(memory->data + old_size, delta_size, MMAP_PROT_READ | MMAP_PROT_WRITE);
if (ret != 0) {
return (uint32_t)-1;
}
#else
uint8_t* new_data = realloc(memory->data, new_size);
if (new_data == NULL) {
return (uint32_t)-1;
}
#if !WABT_BIG_ENDIAN
memset(new_data + old_size, 0, delta_size);
#endif
memory->data = new_data;
#endif
#if WABT_BIG_ENDIAN
memmove(memory->data + new_size - old_size, memory->data, old_size);
@ -250,4 +252,4 @@ void wasm2c_ensure_linked() {
// We use this to ensure the dynamic library with the wasi symbols is loaded for the host application
}
#undef PAGE_SIZE
#undef WASM_PAGE_SIZE

127
third_party/wasm2c/wasm2c/wasm-rt-wasi.c поставляемый
Просмотреть файл

@ -140,14 +140,11 @@ DEFINE_WASI_STORE(wasm_i64_store32, u32, u64);
#define VERBOSE_LOG(...)
#endif
#define IMPORT_IMPL(ret, name, params, body) \
static ret _##name params { \
VERBOSE_LOG("[import: " #name "]\n"); \
body \
} \
ret (*name) params = _##name
#define STUB_IMPORT_IMPL(ret, name, params, returncode) IMPORT_IMPL(ret, name, params, { return returncode; })
#define STUB_IMPORT_IMPL(ret, name, params, returncode) \
ret name params { \
VERBOSE_LOG("[stub import: " #name "]\n"); \
return returncode; \
}
// Generic abort method for a runtime error in the runtime.
@ -159,21 +156,21 @@ static void abort_with_message(const char* message) {
/////////////////////////////////////////// Emscripten runtime ///////////////////////////////////////////////
// Setjmp/longjmp are not currently supported safely. So lonjmp with abort, setjmp can be a noop.
IMPORT_IMPL(void, Z_envZ_emscripten_longjmpZ_vii, (wasm_sandbox_wasi_data* wasi_data, u32 buf, u32 value), {
void Z_envZ_emscripten_longjmpZ_vii(wasm_sandbox_wasi_data* wasi_data, u32 buf, u32 value) {
abort_with_message("longjmp not supported");
});
}
STUB_IMPORT_IMPL(u32, Z_envZ_emscripten_setjmpZ_ii, (wasm_sandbox_wasi_data* wasi_data, u32 buf), 0);
IMPORT_IMPL(void, Z_envZ_emscripten_notify_memory_growthZ_vi, (wasm_sandbox_wasi_data* wasi_data, u32 size), {});
void Z_envZ_emscripten_notify_memory_growthZ_vi(wasm_sandbox_wasi_data* wasi_data, u32 size) {}
IMPORT_IMPL(u32, Z_envZ_getTempRet0Z_iv, (wasm_sandbox_wasi_data* wasi_data), {
u32 Z_envZ_getTempRet0Z_iv(wasm_sandbox_wasi_data* wasi_data) {
return wasi_data->tempRet0;
});
}
IMPORT_IMPL(void, Z_envZ_setTempRet0Z_vi, (wasm_sandbox_wasi_data* wasi_data, u32 x), {
void Z_envZ_setTempRet0Z_vi(wasm_sandbox_wasi_data* wasi_data, u32 x) {
wasi_data->tempRet0 = x;
});
}
static const char* get_null_file_path()
{
@ -318,7 +315,7 @@ static int get_native_fd(wasm_sandbox_wasi_data* wasi_data, u32 fd) {
return wasi_data->wasm_fd_to_native[fd];
}
IMPORT_IMPL(u32, Z_envZ___sys_accessZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 pathname, u32 mode), {
u32 Z_envZ___sys_accessZ_iii(wasm_sandbox_wasi_data* wasi_data, u32 pathname, u32 mode) {
VERBOSE_LOG(" access: %s 0x%x\n", MEMACCESS(wasi_data->heap_memory, pathname), mode);
// only permit access checks on the the null file
@ -335,10 +332,9 @@ IMPORT_IMPL(u32, Z_envZ___sys_accessZ_iii, (wasm_sandbox_wasi_data* wasi_data, u
return EM_EACCES;
}
return 0;
});
}
IMPORT_IMPL(u32, Z_envZ___sys_openZ_iiii, (wasm_sandbox_wasi_data* wasi_data, u32 path, u32 flags, u32 varargs), {
u32 Z_envZ___sys_openZ_iiii(wasm_sandbox_wasi_data* wasi_data, u32 path, u32 flags, u32 varargs) {
VERBOSE_LOG(" open: %s %d\n", MEMACCESS(wasi_data->heap_memory, path), flags);
// only permit opening the null file
@ -359,18 +355,18 @@ IMPORT_IMPL(u32, Z_envZ___sys_openZ_iiii, (wasm_sandbox_wasi_data* wasi_data, u3
return fd;
}
return -1;
});
}
IMPORT_IMPL(u32, Z_envZ___sys_fstat64Z_iii, (wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 buf), {
u32 Z_envZ___sys_fstat64Z_iii(wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 buf) {
int nfd = get_native_fd(wasi_data, fd);
VERBOSE_LOG(" fstat64 %d (=> %d) %d\n", fd, nfd, buf);
if (nfd < 0) {
return EM_EACCES;
}
return do_stat(wasi_data, nfd, buf);
});
}
IMPORT_IMPL(u32, Z_envZ___sys_stat64Z_iii, (wasm_sandbox_wasi_data* wasi_data, u32 path, u32 buf), {
u32 Z_envZ___sys_stat64Z_iii(wasm_sandbox_wasi_data* wasi_data, u32 path, u32 buf) {
VERBOSE_LOG(" stat64: %s\n", MEMACCESS(wasi_data->heap_memory, path));
int fd = Z_envZ___sys_openZ_iiii(wasi_data, path, 0 /* read_only */, 0);
int nfd = get_native_fd(wasi_data, fd);
@ -379,9 +375,9 @@ IMPORT_IMPL(u32, Z_envZ___sys_stat64Z_iii, (wasm_sandbox_wasi_data* wasi_data, u
return EM_EACCES;
}
return do_stat(wasi_data, nfd, buf);
});
}
IMPORT_IMPL(u32, Z_envZ___sys_readZ_iiii, (wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 buf, u32 count), {
u32 Z_envZ___sys_readZ_iiii(wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 buf, u32 count) {
int nfd = get_native_fd(wasi_data, fd);
VERBOSE_LOG(" read %d (=> %d) %d %d\n", fd, nfd, buf, count);
if (nfd < 0) {
@ -399,7 +395,7 @@ IMPORT_IMPL(u32, Z_envZ___sys_readZ_iiii, (wasm_sandbox_wasi_data* wasi_data, u3
return EM_EACCES;
}
return ret;
});
}
STUB_IMPORT_IMPL(u32, Z_envZ_dlopenZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 a, u32 b), 1);
@ -536,7 +532,7 @@ STUB_IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_sock_shutdownZ_iii, (u32 a, u32
// Original file: Modified emscripten/tools/wasm2c/main.c
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_args_getZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 argv, u32 argv_buf), {
u32 Z_wasi_snapshot_preview1Z_args_getZ_iii(wasm_sandbox_wasi_data* wasi_data, u32 argv, u32 argv_buf) {
u32 buf_size = 0;
for (u32 i = 0; i < wasi_data->main_argc; i++) {
u32 ptr = argv_buf + buf_size;
@ -554,9 +550,9 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_args_getZ_iii, (wasm_sandbox_wasi_dat
buf_size += len;
}
return 0;
});
}
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_args_sizes_getZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 pargc, u32 pargv_buf_size), {
u32 Z_wasi_snapshot_preview1Z_args_sizes_getZ_iii(wasm_sandbox_wasi_data* wasi_data, u32 pargc, u32 pargv_buf_size) {
wasm_i32_store(wasi_data->heap_memory, pargc, wasi_data->main_argc);
u32 buf_size = 0;
for (u32 i = 0; i < wasi_data->main_argc; i++) {
@ -564,41 +560,41 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_args_sizes_getZ_iii, (wasm_sandbox_wa
}
wasm_i32_store(wasi_data->heap_memory, pargv_buf_size, buf_size);
return 0;
});
}
// Original file: Modified emscripten/tools/wasm2c/os.c
#ifdef WASM2C_WASI_EXIT_HOST_ON_MODULE_EXIT
IMPORT_IMPL(void, Z_wasi_snapshot_preview1Z_proc_exitZ_vi, (wasm_sandbox_wasi_data* wasi_data, u32 x), {
void Z_wasi_snapshot_preview1Z_proc_exitZ_vi(wasm_sandbox_wasi_data* wasi_data, u32 x) {
exit(1);
});
}
#else
IMPORT_IMPL(void, Z_wasi_snapshot_preview1Z_proc_exitZ_vi, (wasm_sandbox_wasi_data* wasi_data, u32 x), {
void Z_wasi_snapshot_preview1Z_proc_exitZ_vi(wasm_sandbox_wasi_data* wasi_data, u32 x) {
// upstream emscripten implements this as exit(x)
// This seems like a bad idea as a misbehaving sandbox will cause the app to exit
// Since this is a library sandboxing runtime, it's fine to do nothing here.
// Worst case the library continues execution and returns malformed data, which is already a possibility in any sandbox library
VERBOSE_LOG("wasm2c module called proc_exit: this is a noop in this runtime\n");
});
}
#endif
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_environ_sizes_getZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 pcount, u32 pbuf_size), {
u32 Z_wasi_snapshot_preview1Z_environ_sizes_getZ_iii(wasm_sandbox_wasi_data* wasi_data, u32 pcount, u32 pbuf_size) {
// TODO: Allow the sandbox to have its own env
wasm_i32_store(wasi_data->heap_memory, pcount, 0);
wasm_i32_store(wasi_data->heap_memory, pbuf_size, 0);
return 0;
});
}
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_environ_getZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 __environ, u32 environ_buf), {
u32 Z_wasi_snapshot_preview1Z_environ_getZ_iii(wasm_sandbox_wasi_data* wasi_data, u32 __environ, u32 environ_buf) {
// TODO: Allow the sandbox to have its own env
return 0;
});
}
/////////////////////////////////////////////////////////////
////////// File operations
/////////////////////////////////////////////////////////////
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_prestat_getZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 prestat), {
u32 Z_wasi_snapshot_preview1Z_fd_prestat_getZ_iii(wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 prestat) {
int nfd = get_native_fd(wasi_data, fd);
VERBOSE_LOG(" fd_prestat_get wasm %d => native %d\n", fd, nfd);
if (nfd < 0) {
@ -606,9 +602,9 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_prestat_getZ_iii, (wasm_sandbox_wa
}
return WASI_DEFAULT_ERROR;
});
}
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_writeZ_iiiii, (wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 iov, u32 iovcnt, u32 pnum), {
u32 Z_wasi_snapshot_preview1Z_fd_writeZ_iiiii(wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 iov, u32 iovcnt, u32 pnum) {
int nfd = get_native_fd(wasi_data, fd);
VERBOSE_LOG(" fd_write wasm %d => native %d\n", fd, nfd);
if (nfd < 0) {
@ -637,7 +633,7 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_writeZ_iiiii, (wasm_sandbox_wasi_d
VERBOSE_LOG(" error, %d %s\n", errno, strerror(errno));
return WASI_DEFAULT_ERROR;
}
if (result != len) {
if ((size_t) result != len) {
VERBOSE_LOG(" amount error, %ld %d\n", result, len);
return WASI_DEFAULT_ERROR;
}
@ -646,9 +642,9 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_writeZ_iiiii, (wasm_sandbox_wasi_d
VERBOSE_LOG(" success: %d\n", num);
wasm_i32_store(wasi_data->heap_memory, pnum, num);
return 0;
});
}
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_readZ_iiiii, (wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 iov, u32 iovcnt, u32 pnum), {
u32 Z_wasi_snapshot_preview1Z_fd_readZ_iiiii(wasm_sandbox_wasi_data* wasi_data, u32 fd, u32 iov, u32 iovcnt, u32 pnum) {
int nfd = get_native_fd(wasi_data, fd);
VERBOSE_LOG(" fd_read wasm %d => native %d\n", fd, nfd);
if (nfd < 0) {
@ -669,16 +665,16 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_readZ_iiiii, (wasm_sandbox_wasi_da
return WASI_DEFAULT_ERROR;
}
num += result;
if (result != len) {
if ((size_t) result != len) {
break; // nothing more to read
}
}
VERBOSE_LOG(" success: %d\n", num);
wasm_i32_store(wasi_data->heap_memory, pnum, num);
return 0;
});
}
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_closeZ_ii, (wasm_sandbox_wasi_data* wasi_data, u32 fd), {
u32 Z_wasi_snapshot_preview1Z_fd_closeZ_ii(wasm_sandbox_wasi_data* wasi_data, u32 fd) {
int nfd = get_native_fd(wasi_data, fd);
VERBOSE_LOG(" close wasm %d => native %d\n", fd, nfd);
if (nfd < 0) {
@ -690,7 +686,7 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_closeZ_ii, (wasm_sandbox_wasi_data
}
POSIX_PREFIX(close)(nfd);
return 0;
});
}
static int whence_to_native(u32 whence) {
if (whence == 0) return SEEK_SET;
@ -699,7 +695,7 @@ static int whence_to_native(u32 whence) {
return -1;
}
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_seekZ_iijii, (wasm_sandbox_wasi_data* wasi_data, u32 fd, u64 offset, u32 whence, u32 new_offset), {
u32 Z_wasi_snapshot_preview1Z_fd_seekZ_iijii(wasm_sandbox_wasi_data* wasi_data, u32 fd, u64 offset, u32 whence, u32 new_offset) {
int nfd = get_native_fd(wasi_data, fd);
int nwhence = whence_to_native(whence);
VERBOSE_LOG(" seek %d (=> native %d) %ld %d (=> %d) %d\n", fd, nfd, offset, whence, nwhence, new_offset);
@ -720,12 +716,12 @@ IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_seekZ_iijii, (wasm_sandbox_wasi_da
}
wasm_i64_store(wasi_data->heap_memory, new_offset, off);
return 0;
});
}
// wasm2c includes a version of seek, the u64 offset in two u32 parts. Unclear if this is needed, as WASI does not require this, but no harm in including it.
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_fd_seekZ_iiiiii, (wasm_sandbox_wasi_data* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e), {
u32 Z_wasi_snapshot_preview1Z_fd_seekZ_iiiiii(wasm_sandbox_wasi_data* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e) {
return Z_wasi_snapshot_preview1Z_fd_seekZ_iijii(wasi_data, a, b + (((u64)c) << 32), d, e);
});
}
/////////////////////////////////////////////////////////////
////////// Clock operations
@ -741,38 +737,31 @@ static int check_clock(u32 clock_id) {
clock_id == WASM_CLOCK_PROCESS_CPUTIME || clock_id == WASM_CLOCK_THREAD_CPUTIME_ID;
}
// out is a pointer index to a struct of the form
// // https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/headers/public/__struct_timespec.h
// struct timespec {
// // https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/headers/public/__typedef_time_t.h
// // time is long long in wasm32 which is an i64
// time_t tv_sec
// // long in wasm is an i32
// long tv_nsec;
// }
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_clock_time_getZ_iiji, (wasm_sandbox_wasi_data* wasi_data, u32 clock_id, u64 max_lag, u32 out), {
// out is a pointer to a u64 timestamp in nanoseconds
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-timestamp-u64
u32 Z_wasi_snapshot_preview1Z_clock_time_getZ_iiji(wasm_sandbox_wasi_data* wasi_data, u32 clock_id, u32 precision, u32 out) {
if (!check_clock(clock_id)) {
return WASI_INVAL_ERROR;
}
struct timespec out_struct;
int ret = os_clock_gettime(wasi_data->clock_data, clock_id, &out_struct);
wasm_i64_store(wasi_data->heap_memory, out, (u64) out_struct.tv_sec);
wasm_i32_store(wasi_data->heap_memory, out + sizeof(u64), (u32) out_struct.tv_nsec);
u64 result = ((u64)out_struct.tv_sec)*1000000 + ((u64)out_struct.tv_nsec)/1000;
wasm_i64_store(wasi_data->heap_memory, out, result);
return ret;
});
}
IMPORT_IMPL(u32, Z_wasi_snapshot_preview1Z_clock_res_getZ_iii, (wasm_sandbox_wasi_data* wasi_data, u32 clock_id, u32 out), {
u32 Z_wasi_snapshot_preview1Z_clock_res_getZ_iii(wasm_sandbox_wasi_data* wasi_data, u32 clock_id, u32 out) {
if (!check_clock(clock_id)) {
return WASI_INVAL_ERROR;
}
struct timespec out_struct;
int ret = os_clock_getres(wasi_data->clock_data, clock_id, &out_struct);
wasm_i64_store(wasi_data->heap_memory, out, (u64) out_struct.tv_sec);
wasm_i32_store(wasi_data->heap_memory, out + sizeof(u64), (u32) out_struct.tv_nsec);
u64 result = ((u64)out_struct.tv_sec)*1000000 + ((u64)out_struct.tv_nsec)/1000;
wasm_i64_store(wasi_data->heap_memory, out, result);
return ret;
});
}
/////////////////////////////////////////////////////////////
////////// Misc

4
third_party/wasm2c/wasm2c/wasm-rt.h поставляемый
Просмотреть файл

@ -106,11 +106,7 @@ typedef struct {
/** A Memory object. */
typedef struct {
/** The linear memory data, with a byte length of `size`. */
#if WASM_USING_GUARD_PAGES == 1
uint8_t* const data;
#else
uint8_t* data;
#endif
/** The current and maximum page count for this Memory object. If there is no
* maximum, `max_pages` is 0xffffffffu (i.e. UINT32_MAX). */
uint32_t pages, max_pages;