Skip to content

Commit

Permalink
Bug 1721765 part 1 - Vendor new wasm2c rlbox plugin, compiler+rt to s…
Browse files Browse the repository at this point in the history
…upport large unsafe stack r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D120570
  • Loading branch information
shravanrn committed Jul 30, 2021
1 parent 363d4b5 commit 820196c
Show file tree
Hide file tree
Showing 13 changed files with 761 additions and 121 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 3ed74da56a45bc6e556eea60d83995ee2ab962f8 (2021-07-11T21:18:27Z).
revision: 3ed74da56a45bc6e556eea60d83995ee2ab962f8
release: commit 1cd3e4165d30d3ecc30974744e6fd52caa2a3f1d (2021-07-23T02:53:22Z).
revision: 1cd3e4165d30d3ecc30974744e6fd52caa2a3f1d

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 498f15980a553dd41bc6ff97fb22b5ee1c52f701 (2021-07-11T23:33:38Z).
revision: 498f15980a553dd41bc6ff97fb22b5ee1c52f701
release: commit df7630a80686c1e3bc775a6cb261841e99484b54 (2021-07-28T00:22:29Z).
revision: df7630a80686c1e3bc775a6cb261841e99484b54

license: Apache-2.0
license-file: LICENSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ __attribute__((weak))
sandbox = sandbox_info.create_wasm2c_sandbox();
detail::dynamic_check(sandbox != nullptr, "Sandbox could not be created");

sandbox_memory_info = (wasm_rt_memory_t*) sandbox_info.lookup_wasm2c_nonfunc_export(sandbox, "memory");
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");

heap_base = reinterpret_cast<uintptr_t>(impl_get_memory_location());
Expand Down
164 changes: 133 additions & 31 deletions third_party/wasm2c/src/c-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,16 @@ class CWriter {
void WriteFuncDeclarations();
void WriteFuncDeclaration(const FuncDeclaration&, const std::string&, bool add_storage_class);
void WriteImportFuncDeclaration(const FuncDeclaration&, const std::string&);
std::string GetMainMemoryName();
void WriteGlobalInitializers();
void WriteGlobals();
void WriteGlobalsExport();
void WriteGlobal(const Global&, const std::string&);
void WriteMemories();
void WriteMemoriesExport();
void WriteMemory(const std::string&);
void WriteTables();
void WriteTablesExport();
void WriteTable(const std::string&);
void WriteDataInitializers();
void WriteElemInitializers();
Expand Down Expand Up @@ -991,21 +995,68 @@ void CWriter::WriteGlobals() {
}
}

void CWriter::WriteGlobalInitializers() {
void CWriter::WriteGlobalsExport() {
Index global_index = 0;
if (module_->globals.size() != module_->num_global_imports) {

for (const Global* global : module_->globals) {
bool is_import = global_index < module_->num_global_imports;
if (!is_import) {
std::string curr_global_name = GetGlobalName(global->name);
Writef("if (strcmp(\"%s\", name) == 0)", curr_global_name.c_str());
Write(OpenBrace());
Write("return &(sbx->", curr_global_name, ");", Newline());
Write(CloseBrace(), Newline());
}
++global_index;
}
}
}

std::string CWriter::GetMainMemoryName() {
assert (!(module_->memories.size() == module_->num_memory_imports));
assert(module_->memories.size() <= 1);

std::string ret = GetGlobalName(module_->memories[0]->name);
return ret;
}

void CWriter::WriteGlobalInitializers() {

Write(Newline(), "static void init_globals(wasm2c_sandbox_t* const sbx) ", OpenBrace());

for (const Global* global : module_->globals) {
bool is_import = global_index < module_->num_global_imports;
if (!is_import) {
assert(!global->init_expr.empty());
Write("sbx->", GlobalName(global->name), " = ");
WriteInitExpr(global->init_expr);
Write(";", Newline());
{
Index global_index = 0;
for (const Global* global : module_->globals) {
bool is_import = global_index < module_->num_global_imports;
if (!is_import) {
assert(!global->init_expr.empty());
Write("sbx->", GlobalName(global->name), " = ");
WriteInitExpr(global->init_expr);
Write(";", Newline());
}
++global_index;
}
}

{
Index global_index = 0;
std::string memory_name = GetMainMemoryName();
for (const Global* global : module_->globals) {
bool is_import = global_index < module_->num_global_imports;
if (!is_import) {
std::string global_name = GetGlobalName(global->name);
std::string global_name_expr = "sbx->" + global_name;
Write("WASM2C_SHADOW_MEMORY_RESERVE(&(sbx->", memory_name ,"), ", global_name_expr, ", sizeof(", global_name_expr, "));", Newline());
if (global_name == "w2c___heap_base") {
Write("WASM2C_SHADOW_MEMORY_MARK_GLOBALS_HEAP_BOUNDARY(&(sbx->", memory_name, "), ", global_name_expr, ");", Newline());
}
}

++global_index;
}
++global_index;
}

Write(CloseBrace(), Newline());
}

Expand All @@ -1029,6 +1080,25 @@ void CWriter::WriteMemories() {
}
}

void CWriter::WriteMemoriesExport() {
if (module_->memories.size() == module_->num_memory_imports)
return;

assert(module_->memories.size() <= 1);
Index memory_index = 0;
for (const Memory* memory : module_->memories) {
bool is_import = memory_index < module_->num_memory_imports;
if (!is_import) {
std::string curr_memory_name = GetGlobalName(memory->name);
Writef("if (strcmp(\"%s\", name) == 0)", curr_memory_name.c_str());
Write(OpenBrace());
Write("return &(sbx->", curr_memory_name, ");", Newline());
Write(CloseBrace(), Newline());
}
++memory_index;
}
}

void CWriter::WriteMemory(const std::string& name) {
Write("wasm_rt_memory_t ", name, ";");
}
Expand All @@ -1052,6 +1122,25 @@ void CWriter::WriteTables() {
}
}

void CWriter::WriteTablesExport() {
if (module_->tables.size() == module_->num_table_imports)
return;

assert(module_->tables.size() <= 1);
Index table_index = 0;
for (const Table* table : module_->tables) {
bool is_import = table_index < module_->num_table_imports;
if (!is_import) {
std::string curr_table_name = GetGlobalName(table->name);
Writef("if (strcmp(\"%s\", name) == 0)", curr_table_name.c_str());
Write(OpenBrace());
Write("return &(sbx->", curr_table_name, ");", Newline());
Write(CloseBrace(), Newline());
}
++table_index;
}
}

void CWriter::WriteTable(const std::string& name) {
Write("wasm_rt_table_t ", name, ";");
}
Expand Down Expand Up @@ -1156,24 +1245,10 @@ void CWriter::WriteElemInitializers() {
void CWriter::WriteExportLookup() {
Write(Newline(), "static void* lookup_wasm2c_nonfunc_export(void* sbx_ptr, const char* name) ", OpenBrace());
Write("wasm2c_sandbox_t* const sbx = (wasm2c_sandbox_t* const) sbx_ptr;", Newline());
for (const Export* export_ : module_->exports) {
switch (export_->kind) {
case ExternalKind::Func: {
break;
}
case ExternalKind::Global :
case ExternalKind::Memory :
case ExternalKind::Table: {
Writef("if (strcmp(\"%s\", name) == 0)", export_->name.c_str());
Write(OpenBrace());
Write("return &(sbx->w2c_", export_->name, ");", Newline());
Write(CloseBrace(), Newline());
break;
}
default:
WABT_UNREACHABLE;
}
}

WriteMemoriesExport();
WriteTablesExport();
WriteGlobalsExport();

Write("return 0;", Newline());
Write(CloseBrace(), Newline());
Expand Down Expand Up @@ -1218,7 +1293,7 @@ void CWriter::WriteCallbackAddRemove() {
Write(CloseBrace(), Newline());
}
Write(CloseBrace(), Newline());
Write("TRAP(CALL_INDIRECT);", Newline());
Write("(void) TRAP(CALL_INDIRECT);", Newline());
}
Write(CloseBrace(), Newline());

Expand Down Expand Up @@ -1285,8 +1360,16 @@ void CWriter::Write(const Func& func) {
local_sym_map_.clear();
stack_var_sym_map_.clear();

Write(GetFuncStaticOrExport(GetGlobalName(func.name)), ResultType(func.decl.sig.result_types), " ",
GlobalName(func.name), "(");
std::string func_name_suffix;
auto out_func_name = GetGlobalName(func.name);

if (out_func_name == "w2c_dlmalloc" || out_func_name == "w2c_dlfree")
{
func_name_suffix = "_wrapped";
}

Write(GetFuncStaticOrExport(out_func_name), ResultType(func.decl.sig.result_types), " ",
out_func_name + func_name_suffix, "(");
WriteParamsAndLocals();
Write("FUNC_PROLOGUE;", Newline());

Expand Down Expand Up @@ -1317,6 +1400,22 @@ void CWriter::Write(const Func& func) {

Write(CloseBrace());

std::string memory_name = GetMainMemoryName();
if (out_func_name == "w2c_dlmalloc") {
Write(Newline(), Newline());
Write(GetFuncStaticOrExport(out_func_name), "u32 w2c_dlmalloc(wasm2c_sandbox_t* const sbx, u32 ptr_size) ", OpenBrace());
Write("u32 ret = w2c_dlmalloc_wrapped(sbx, ptr_size);", Newline());
Write("WASM2C_SHADOW_MEMORY_DLMALLOC(&(sbx->", memory_name, "), ret, ptr_size);", Newline());
Write("return ret;", Newline());
Write(CloseBrace());
} else if (out_func_name == "w2c_dlfree") {
Write(Newline(), Newline());
Write(GetFuncStaticOrExport(out_func_name), "void w2c_dlfree(wasm2c_sandbox_t* const sbx, u32 ptr) ", OpenBrace());
Write("WASM2C_SHADOW_MEMORY_DLFREE(&(sbx->", memory_name, "), ptr);", Newline());
Write("w2c_dlfree_wrapped(sbx, ptr);", Newline());
Write(CloseBrace());
}

func_stream_.Clear();
func_ = nullptr;
}
Expand Down Expand Up @@ -2100,6 +2199,7 @@ void CWriter::Write(const LoadExpr& expr) {
"), (u64)(", StackVar(0), ")");
if (expr.offset != 0)
Write(" + ", expr.offset, "u");
Write(", \"", GetGlobalName(func_->name), "\"");
Write(");", Newline());
DropTypes(1);
PushType(result_type);
Expand Down Expand Up @@ -2128,7 +2228,9 @@ void CWriter::Write(const StoreExpr& expr) {
Write(func, "(&(sbx->", ExternalRef(memory->name), "), (u64)(", StackVar(1), ")");
if (expr.offset != 0)
Write(" + ", expr.offset);
Write(", ", StackVar(0), ");", Newline());
Write(", ", StackVar(0));
Write(", \"", GetGlobalName(func_->name), "\"");
Write(");", Newline());
DropTypes(2);
}

Expand Down
79 changes: 54 additions & 25 deletions third_party/wasm2c/src/prebuilt/wasm2c.include.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,31 @@ const char SECTION_NAME(declarations)[] =
"\n"
"#define FUNC_EPILOGUE\n"
"\n"
"#define UNREACHABLE TRAP(UNREACHABLE)\n"
"#define UNREACHABLE (void) TRAP(UNREACHABLE)\n"
"\n"
"#define CALL_INDIRECT(table, t, ft, x, func_types, ...) \\\n"
" (LIKELY((x) < table.size && table.data[x].func && \\\n"
" table.data[x].func_type == func_types[ft]) \\\n"
" ? ((t)table.data[x].func)(__VA_ARGS__) \\\n"
" : TRAP(CALL_INDIRECT))\n"
"\n"
"\n"
"#if defined(WASM_CHECK_SHADOW_MEMORY)\n"
"#define WASM2C_SHADOW_MEMORY_LOAD(mem, func_name, ptr, ptr_size) wasm2c_shadow_memory_load(mem, func_name, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_STORE(mem, func_name, ptr, ptr_size) wasm2c_shadow_memory_store(mem, func_name, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_RESERVE(mem, ptr, ptr_size) wasm2c_shadow_memory_reserve(mem, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_DLMALLOC(mem, ptr, ptr_size) wasm2c_shadow_memory_dlmalloc(mem, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_DLFREE(mem, ptr) wasm2c_shadow_memory_dlfree(mem, ptr)\n"
"#define WASM2C_SHADOW_MEMORY_MARK_GLOBALS_HEAP_BOUNDARY(mem, ptr) wasm2c_shadow_memory_mark_globals_heap_boundary(mem, ptr)\n"
"#else\n"
"#define WASM2C_SHADOW_MEMORY_LOAD(mem, func_name, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_STORE(mem, func_name, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_RESERVE(mem, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_DLMALLOC(mem, ptr, ptr_size)\n"
"#define WASM2C_SHADOW_MEMORY_DLFREE(mem, ptr)\n"
"#define WASM2C_SHADOW_MEMORY_MARK_GLOBALS_HEAP_BOUNDARY(mem, ptr)\n"
"#endif\n"
"\n"
"#if WASM_USING_GUARD_PAGES == 1\n"
"#define MEMCHECK(mem, a, t)\n"
"#else\n"
Expand All @@ -53,39 +70,51 @@ const char SECTION_NAME(declarations)[] =
" dest_chars[n - i - 1] = cursor;\n"
" }\n"
"}\n"
"#define LOAD_DATA(m, o, i, s) load_data(&(m.data[m.size - o - s]), i, s)\n"
"#define DEFINE_LOAD(name, t1, t2, t3) \\\n"
" static inline t3 name(wasm_rt_memory_t* mem, u64 addr) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 result; \\\n"
" memcpy(&result, MEM_ACCESS_REF(mem, mem->size - addr - sizeof(t1)), sizeof(t1)); \\\n"
" return (t3)(t2)result; \\\n"
"#define LOAD_DATA(m, o, i, s) { load_data(&(m.data[m.size - o - s]), i, s); \\\n"
" WASM2C_SHADOW_MEMORY_RESERVE(&m, m.size - o - s, s); \\\n"
" WASM2C_SHADOW_MEMORY_STORE(&m, \"GlobalDataLoad\", m.size - o - s, s); \\\n"
"}\n"
"\n"
"#define DEFINE_LOAD(name, t1, t2, t3) \\\n"
" static inline t3 name(wasm_rt_memory_t* mem, u64 addr, const char* func_name) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 result; \\\n"
" memcpy(&result, MEM_ACCESS_REF(mem, mem->size - addr - sizeof(t1)), sizeof(t1)); \\\n"
" WASM2C_SHADOW_MEMORY_LOAD(mem, func_name, mem->size - addr - sizeof(t1), sizeof(t1)); \\\n"
" return (t3)(t2)result; \\\n"
" }\n"
"\n"
"#define DEFINE_STORE(name, t1, t2) \\\n"
" static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 wrapped = (t1)value; \\\n"
" memcpy(MEM_ACCESS_REF(mem, mem->size - addr - sizeof(t1)), &wrapped, sizeof(t1)); \\\n"
"#define DEFINE_STORE(name, t1, t2) \\\n"
" static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value, const char* func_name) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 wrapped = (t1)value; \\\n"
" memcpy(MEM_ACCESS_REF(mem, mem->size - addr - sizeof(t1), &wrapped, sizeof(t1)); \\\n"
" WASM2C_SHADOW_MEMORY_STORE(mem, func_name, mem->size - addr - sizeof(t1)), sizeof(t1)); \\\n"
" }\n"
"#else\n"
"static inline void load_data(void *dest, const void *src, size_t n) {\n"
" memcpy(dest, src, n);\n"
"}\n"
"#define LOAD_DATA(m, o, i, s) load_data(&(m.data[o]), i, s)\n"
"#define DEFINE_LOAD(name, t1, t2, t3) \\\n"
" static inline t3 name(wasm_rt_memory_t* mem, u64 addr) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 result; \\\n"
" memcpy(&result, MEM_ACCESS_REF(mem, addr), sizeof(t1)); \\\n"
" return (t3)(t2)result; \\\n"
"#define LOAD_DATA(m, o, i, s) { load_data(&(m.data[o]), i, s); \\\n"
" WASM2C_SHADOW_MEMORY_RESERVE(&m, o, s); \\\n"
" WASM2C_SHADOW_MEMORY_STORE(&m, \"GlobalDataLoad\", o, s); \\\n"
"}\n"
"\n"
"#define DEFINE_LOAD(name, t1, t2, t3) \\\n"
" static inline t3 name(wasm_rt_memory_t* mem, u64 addr, const char* func_name) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 result; \\\n"
" memcpy(&result, MEM_ACCESS_REF(mem, addr), sizeof(t1)); \\\n"
" WASM2C_SHADOW_MEMORY_LOAD(mem, func_name, addr, sizeof(t1)); \\\n"
" return (t3)(t2)result; \\\n"
" }\n"
"\n"
"#define DEFINE_STORE(name, t1, t2) \\\n"
" static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 wrapped = (t1)value; \\\n"
" memcpy(MEM_ACCESS_REF(mem, addr), &wrapped, sizeof(t1)); \\\n"
"#define DEFINE_STORE(name, t1, t2) \\\n"
" static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value, const char* func_name) { \\\n"
" MEMCHECK(mem, addr, t1); \\\n"
" t1 wrapped = (t1)value; \\\n"
" memcpy(MEM_ACCESS_REF(mem, addr), &wrapped, sizeof(t1)); \\\n"
" WASM2C_SHADOW_MEMORY_STORE(mem, func_name, addr, sizeof(t1)); \\\n"
" }\n"
"#endif\n"
"\n"
Expand Down
Loading

0 comments on commit 820196c

Please sign in to comment.