From 8b1341c77ecd31a27305674b8eb3d3d9b42d49e2 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Sat, 18 May 2024 20:01:29 +0200 Subject: [PATCH] LibWeb: Make exported Wasm functions keep the module instance alive As it's not uncommon for users to drop the module instance on the floor after having grabbed the few exports they need to hold on to. Fixes a few UAFs that show up as "invalid" accesses to memory/tables/etc. --- Userland/Libraries/LibWeb/WebAssembly/Instance.cpp | 2 +- Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp | 5 +++-- Userland/Libraries/LibWeb/WebAssembly/WebAssembly.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp b/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp index 75ccaed4d5..11bc256e87 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp @@ -51,7 +51,7 @@ void Instance::initialize(JS::Realm& realm) [&](Wasm::FunctionAddress const& address) { Optional> object = m_function_instances.get(address); if (!object.has_value()) { - object = Detail::create_native_function(vm, address, export_.name()); + object = Detail::create_native_function(vm, address, export_.name(), this); m_function_instances.set(address, *object); } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp index acae97f951..fab14755b5 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp @@ -342,7 +342,7 @@ JS::ThrowCompletionOr> parse_module(JS: return compiled_module; } -JS::NativeFunction* create_native_function(JS::VM& vm, Wasm::FunctionAddress address, ByteString const& name) +JS::NativeFunction* create_native_function(JS::VM& vm, Wasm::FunctionAddress address, ByteString const& name, Instance* instance) { auto& realm = *vm.current_realm(); Optional type; @@ -354,7 +354,8 @@ JS::NativeFunction* create_native_function(JS::VM& vm, Wasm::FunctionAddress add auto function = JS::NativeFunction::create( realm, name, - [address, type = type.release_value()](JS::VM& vm) -> JS::ThrowCompletionOr { + [address, type = type.release_value(), instance](JS::VM& vm) -> JS::ThrowCompletionOr { + (void)instance; auto& realm = *vm.current_realm(); Vector values; values.ensure_capacity(type.parameters().size()); diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.h index c73d9a22a9..3eab3a0f07 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.h @@ -57,7 +57,7 @@ WebAssemblyCache& get_cache(JS::Realm&); JS::ThrowCompletionOr> instantiate_module(JS::VM&, Wasm::Module const&); JS::ThrowCompletionOr> parse_module(JS::VM&, JS::Object* buffer); -JS::NativeFunction* create_native_function(JS::VM&, Wasm::FunctionAddress address, ByteString const& name); +JS::NativeFunction* create_native_function(JS::VM&, Wasm::FunctionAddress address, ByteString const& name, Instance* instance = nullptr); JS::ThrowCompletionOr to_webassembly_value(JS::VM&, JS::Value value, Wasm::ValueType const& type); JS::Value to_js_value(JS::VM&, Wasm::Value& wasm_value);