Skip to content

Commit

Permalink
Bug 1728934 Part 2 - Update rlbox,wasm2c plugin for fallible create_s…
Browse files Browse the repository at this point in the history
…andbox r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D127022
  • Loading branch information
shravanrn committed Oct 1, 2021
1 parent edb3953 commit 86b9273
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 115 deletions.
4 changes: 2 additions & 2 deletions config/external/rlbox_wasm2c_sandbox/moz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ origin:
description: rlbox integration for the wasm2c sandboxed code
url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox

release: commit a7b7233cf1845bc2548ffc7ea06f27e8a024b851 (2021-08-24T08:37:28Z).
revision: a7b7233cf1845bc2548ffc7ea06f27e8a024b851
release: commit 95b0e954c9d140a22dfe1755e747ddc132ae82ac (2021-09-29T22:50:14Z).
revision: 95b0e954c9d140a22dfe1755e747ddc132ae82ac

license: MIT
license-file: LICENSE
Expand Down
4 changes: 2 additions & 2 deletions config/external/wasm2c_sandbox_compiler/moz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ origin:
description: wasm2c fork used for rlbox sandboxing
url: https://github.com/PLSysSec/wasm2c_sandbox_compiler

release: commit e209f351b894dd92c8047c3db89d8285e1caa2a3 (2021-09-29T06:27:15Z).
revision: e209f351b894dd92c8047c3db89d8285e1caa2a3
release: commit 32a8ad683fe2390200cc3b7c8e5ffb55b071e781 (2021-09-29T22:48:37Z).
revision: 32a8ad683fe2390200cc3b7c8e5ffb55b071e781

license: Apache-2.0
license-file: LICENSE
Expand Down
2 changes: 1 addition & 1 deletion third_party/rlbox/README-mozilla
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
This directory contains the rlbox source from the upstream repo:
https://github.com/PLSysSec/rlbox_sandboxing_api/

Current version: [commit fc796e549b3a48e89b9a8db28011dcad06494ba3]
Current version: [commit e1cb323a00a680c8b29001e485a99252130a6e32]

UPDATING:

Expand Down
37 changes: 27 additions & 10 deletions third_party/rlbox/include/rlbox_sandbox.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,11 @@ class rlbox_sandbox : protected T_Sbx
return nullptr;
}

template<typename... T_Args>
static auto impl_create_sandbox_helper(rlbox_sandbox<T_Sbx>* this_ptr, T_Args... args) {
return this_ptr->impl_create_sandbox(std::forward<T_Args>(args)...);
}

public:
/**
* @brief Unused member that allows the calling code to save data in a
Expand Down Expand Up @@ -362,7 +367,7 @@ class rlbox_sandbox : protected T_Sbx
* implementation. For the null sandbox, no arguments are necessary.
*/
template<typename... T_Args>
inline auto create_sandbox(T_Args... args)
inline bool create_sandbox(T_Args... args)
{
#ifdef RLBOX_MEASURE_TRANSITION_TIMES
// Warm up the timer. The first call is always slow (at least on the test
Expand All @@ -380,15 +385,27 @@ class rlbox_sandbox : protected T_Sbx
"create_sandbox called when sandbox already created/is being "
"created concurrently");

return detail::return_first_result(
[&]() {
return this->impl_create_sandbox(std::forward<T_Args>(args)...);
},
[&]() {
sandbox_created.store(Sandbox_Status::CREATED);
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, sandbox_list_lock);
sandbox_list.push_back(this);
});
using T_Result = rlbox::detail::polyfill::invoke_result_t<decltype(impl_create_sandbox_helper<T_Args...>), decltype(this), T_Args...>;

bool created = true;
if constexpr (std::is_same_v<T_Result, void>) {
this->impl_create_sandbox(std::forward<T_Args>(args)...);
} else if constexpr (std::is_same_v<T_Result, bool>) {
created = this->impl_create_sandbox(std::forward<T_Args>(args)...);
} else {
rlbox_detail_static_fail_because(
(!std::is_same_v<T_Result, void> && !std::is_same_v<T_Result, bool>),
"Expected impl_create_sandbox to return void or a boolean"
);
}

if (created) {
sandbox_created.store(Sandbox_Status::CREATED);
RLBOX_ACQUIRE_UNIQUE_GUARD(lock, sandbox_list_lock);
sandbox_list.push_back(this);
}

return created;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion third_party/rlbox/update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

MY_TEMP_DIR=`mktemp -d -t rlbox_update.XXXXXX` || exit 1

git clone https://github.com/PLSysSec/rlbox_sandboxing_api ${MY_TEMP_DIR}/rlbox
git clone https://github.com/PLSysSec/rlbox_sandboxing_api -b fallible_create ${MY_TEMP_DIR}/rlbox

COMMIT=$(git -C ${MY_TEMP_DIR}/rlbox rev-parse HEAD)
perl -p -i -e "s/\[commit [0-9a-f]{40}\]/[commit ${COMMIT}]/" README-mozilla;
Expand Down
57 changes: 42 additions & 15 deletions third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_sandbox.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,28 @@ __attribute__((weak))
using path_buf = const char*;
#endif

inline void impl_create_sandbox(path_buf wasm2c_module_path, const char* wasm_module_name = "")
#define CREATE_SANDBOX_CHECK_ERR(infallible, cond, msg) \
if (!(cond)) { \
if (infallible) { \
detail::dynamic_check(cond, msg); \
} else { \
impl_destroy_sandbox(); \
return false; \
} \
}

/**
* @brief creates the Wasm sandbox from the given shared library
*
* @param wasm2c_module_path path to shared library compiled with wasm2c
* @param infallible if set to true, the sandbox aborts on failure. If false, the sandbox returns creation status as a return value
* @param wasm_module_name optional module name used when compiling with wasm2c
* @return true when sandbox is successfully created
* @return false when infallible if set to false and sandbox was not successfully created. If infallible is set to true, this function will never return false.
*/
inline bool impl_create_sandbox(path_buf wasm2c_module_path, bool infallible = true, const char* wasm_module_name = "")
{
detail::dynamic_check(sandbox == nullptr, "Sandbox already initialized");
CREATE_SANDBOX_CHECK_ERR(infallible, sandbox == nullptr, "Sandbox already initialized");

#if defined(_WIN32)
library = (void*) LoadLibraryW(wasm2c_module_path);
Expand All @@ -435,24 +454,24 @@ __attribute__((weak))
#else
error_msg += dlerror();
#endif
detail::dynamic_check(false, error_msg.c_str());
CREATE_SANDBOX_CHECK_ERR(infallible, false, error_msg.c_str());
}

std::string info_func_name = wasm_module_name;
info_func_name += "get_wasm2c_sandbox_info";
auto get_info_func = reinterpret_cast<wasm2c_sandbox_funcs_t(*)()>(symbol_lookup(info_func_name));
detail::dynamic_check(get_info_func != nullptr, "wasm2c could not find <MODULE_NAME>get_wasm2c_sandbox_info");
CREATE_SANDBOX_CHECK_ERR(infallible, get_info_func != nullptr, "wasm2c could not find <MODULE_NAME>get_wasm2c_sandbox_info");
sandbox_info = get_info_func();

std::call_once(wasm2c_runtime_initialized, [&](){
sandbox_info.wasm_rt_sys_init();
});

sandbox = sandbox_info.create_wasm2c_sandbox();
detail::dynamic_check(sandbox != nullptr, "Sandbox could not be created");
CREATE_SANDBOX_CHECK_ERR(infallible, sandbox != nullptr, "Sandbox could not be created");

sandbox_memory_info = (wasm_rt_memory_t*) sandbox_info.lookup_wasm2c_nonfunc_export(sandbox, "w2c_memory");
detail::dynamic_check(sandbox_memory_info != nullptr, "Could not get wasm2c sandbox memory info");
CREATE_SANDBOX_CHECK_ERR(infallible, sandbox_memory_info != nullptr, "Could not get wasm2c sandbox memory info");

heap_base = reinterpret_cast<uintptr_t>(impl_get_memory_location());

Expand All @@ -462,30 +481,38 @@ __attribute__((weak))
// 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,
CREATE_SANDBOX_CHECK_ERR(infallible, (heap_base & heap_offset_mask) == 0,
"Sandbox heap not aligned to 4GB");
}

// cache these for performance
exec_env = sandbox;
malloc_index = impl_lookup_symbol("malloc");
free_index = impl_lookup_symbol("free");
return true;
}

#undef CREATE_SANDBOX_CHECK_ERR

inline void impl_destroy_sandbox()
{
if (return_slot_size) {
impl_free_in_sandbox(return_slot);
}
sandbox_info.destroy_wasm2c_sandbox(sandbox);
sandbox = nullptr;

#if defined(_WIN32)
FreeLibrary((HMODULE) library);
#else
dlclose(library);
#endif
library = nullptr;
if (sandbox != nullptr) {
sandbox_info.destroy_wasm2c_sandbox(sandbox);
sandbox = nullptr;
}

if (library != nullptr) {
#if defined(_WIN32)
FreeLibrary((HMODULE) library);
#else
dlclose(library);
#endif
library = nullptr;
}
}

template<typename T>
Expand Down
90 changes: 10 additions & 80 deletions third_party/wasm2c/src/c-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ class CWriter {
void WriteDataInitializers();
void WriteElemInitializers();
void WriteExportLookup();
void WriteFuncIndexLookup();
void WriteCallbackAddRemove();
void WriteInit();
void WriteFuncs();
Expand Down Expand Up @@ -1216,12 +1215,13 @@ void CWriter::WriteDataInitializers() {
memory = module_->memories[0];
}

Write(Newline(), "static void init_memory(wasm2c_sandbox_t* const sbx) ", OpenBrace());
Write(Newline(), "static bool init_memory(wasm2c_sandbox_t* const sbx) ", OpenBrace());
if (memory && module_->num_memory_imports == 0) {
uint32_t max =
memory->page_limits.has_max ? memory->page_limits.max : 65536;
Write("wasm_rt_allocate_memory(&(sbx->", ExternalRef(memory->name), "), ",
Write("bool success = wasm_rt_allocate_memory(&(sbx->", ExternalRef(memory->name), "), ",
memory->page_limits.initial, ", ", max, ");", Newline());
Write("if (!success) { return false; }", Newline());
}
data_segment_index = 0;
for (const DataSegment* data_segment : module_->data_segments) {
Expand All @@ -1233,6 +1233,7 @@ void CWriter::WriteDataInitializers() {
}

Write("sbx->wasi_data.heap_memory = &(sbx->", ExternalRef(memory->name), ");", Newline());
Write("return true;", Newline());
Write(CloseBrace(), Newline());

Write(Newline(), "static void cleanup_memory(wasm2c_sandbox_t* const sbx) ", OpenBrace());
Expand Down Expand Up @@ -1298,93 +1299,23 @@ void CWriter::WriteExportLookup() {
Write(CloseBrace(), Newline());
}

void CWriter::WriteFuncIndexLookup() {
Write(Newline(), "static u32 lookup_wasm2c_func_index(void* sbx_ptr, u32 param_count, u32 result_count, wasm_rt_type_t* types) ", OpenBrace());
Write("wasm2c_sandbox_t* const sbx = (wasm2c_sandbox_t* const) sbx_ptr;", Newline());
Write("return wasm_rt_register_func_type(&sbx->func_type_structs, &sbx->func_type_count, param_count, result_count, types);", Newline());
Write(CloseBrace(), Newline());
}

void CWriter::WriteCallbackAddRemove() {
const Table* table = module_->tables.empty() ? nullptr : module_->tables[0];

Write(Newline(), "static u32 add_wasm2c_callback(void* sbx_ptr, u32 func_type_idx, void* func_ptr, wasm_rt_elem_target_class_t func_class) ", OpenBrace());
{
Write("wasm2c_sandbox_t* const sbx = (wasm2c_sandbox_t* const) sbx_ptr;", Newline());

if (table->elem_limits.max == 0) {
Writef("for (u32 i = 1; i != 0; i++) ");
} else {
Writef("for (u32 i = 1; i < %" PRIu64 "; i++) ", table->elem_limits.max);
}
Write(OpenBrace());
{
assert(module_->tables.size() == 1);
const Table* table = module_->tables[0];
Write("if (i >= sbx->", ExternalRef(table->name), ".size) ", OpenBrace());
{
Write("wasm_rt_expand_table(&(sbx->", ExternalRef(table->name), "));", Newline());
}
Write(CloseBrace(), Newline());

Write("if (sbx->", ExternalRef(table->name), ".data[i].func == 0) ", OpenBrace());
{
Write("sbx->",ExternalRef(table->name), ".data[i]",
" = (wasm_rt_elem_t){ func_class, func_type_idx, ",
"(wasm_rt_anyfunc_t) func_ptr };", Newline());
Write("return i;", Newline());
}
Write(CloseBrace(), Newline());
}
Write(CloseBrace(), Newline());
Write("(void) TRAP(CALL_INDIRECT);", Newline());
}
Write(CloseBrace(), Newline());

Write(Newline(), "static void remove_wasm2c_callback(void* sbx_ptr, u32 callback_idx) ", OpenBrace());
{
Write("wasm2c_sandbox_t* const sbx = (wasm2c_sandbox_t* const) sbx_ptr;", Newline());
Write("sbx->", ExternalRef(table->name), ".data[callback_idx].func = 0;", Newline());
}
Write(Newline(), "static wasm_rt_table_t* get_wasm2c_callback_table(void* sbx_ptr)", OpenBrace());
Write("wasm2c_sandbox_t* const sbx = (wasm2c_sandbox_t* const) sbx_ptr;", Newline());
Write("return &(sbx->", ExternalRef(table->name), ");", Newline());
Write(CloseBrace(), Newline());
}

void CWriter::WriteInit() {
Write(Newline(), "static void* create_wasm2c_sandbox(void) ", OpenBrace());
Write("wasm2c_sandbox_t* const sbx = (wasm2c_sandbox_t* const) calloc(sizeof(wasm2c_sandbox_t), 1);", Newline());
Write("init_memory(sbx);", Newline());
Write("init_func_types(sbx);", Newline());
Write("init_globals(sbx);", Newline());
Write("init_table(sbx);", Newline());
Write("wasm_rt_init_wasi(&(sbx->wasi_data));", Newline());
Write(Newline(), "static void init_module_starts(void) ", OpenBrace());
for (Var* var : module_->starts) {
Write(ExternalRef(module_->GetFunc(*var)->name), "();", Newline());
}
Write("return sbx;", Newline());
Write(CloseBrace(), Newline(), Newline());

Write("static void destroy_wasm2c_sandbox(void* aSbx) ", OpenBrace());
Write("wasm2c_sandbox_t* const sbx = (wasm2c_sandbox_t* const) aSbx;", Newline());
Write("cleanup_memory(sbx);", Newline());
Write("cleanup_func_types(sbx);", Newline());
Write("cleanup_table(sbx);", Newline());
Write("wasm_rt_cleanup_wasi(&(sbx->wasi_data));", Newline());
Write("free(sbx);", Newline());
Write(CloseBrace(), Newline(), Newline());

Write("FUNC_EXPORT wasm2c_sandbox_funcs_t WASM_CURR_ADD_PREFIX(get_wasm2c_sandbox_info)() ", OpenBrace());
{
Write("wasm2c_sandbox_funcs_t ret;", Newline());
Write("ret.wasm_rt_sys_init = &wasm_rt_sys_init;", Newline());
Write("ret.create_wasm2c_sandbox = &create_wasm2c_sandbox;", Newline());
Write("ret.destroy_wasm2c_sandbox = &destroy_wasm2c_sandbox;", Newline());
Write("ret.lookup_wasm2c_nonfunc_export = &lookup_wasm2c_nonfunc_export;", Newline());
Write("ret.lookup_wasm2c_func_index = &lookup_wasm2c_func_index;", Newline());
Write("ret.add_wasm2c_callback = &add_wasm2c_callback;", Newline());
Write("ret.remove_wasm2c_callback = &remove_wasm2c_callback;", Newline());
Write("return ret;", Newline());
}
Write(CloseBrace(), Newline());

Write(s_source_sandboxapis);
}

void CWriter::WriteFuncs() {
Expand Down Expand Up @@ -2484,7 +2415,6 @@ void CWriter::WriteCSource() {
WriteDataInitializers();
WriteElemInitializers();
WriteExportLookup();
WriteFuncIndexLookup();
WriteCallbackAddRemove();
WriteInit();
}
Expand Down
Loading

0 comments on commit 86b9273

Please sign in to comment.