[12] Wasm InstanceAnchor unregistered too late in destructor
Severity: High | Component: JSC Wasm runtime | 76b3468
Rated High because the diff fixes a publish/unpublish ordering inversion: the destructor freed per-instance state before tearing down the thread-safe handle the compiler thread uses to recover the instance, leaving a wide race window during which a compiler-thread profile merge could read freed baselineData slots.
~JSWebAssemblyInstance ran unregisterMirror, clearJSCallICs, and std::destroy_at loops over importFunctionInfos, tables, and baselineDatas BEFORE calling m_anchor->tearDown() — even though the anchor is what the compiler thread uses to find live instances.
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
JSWebAssemblyInstance::~JSWebAssemblyInstance()
{
+ if (m_anchor) {
+ m_anchor->tearDown();
+ m_anchor = nullptr;
+ }
+
m_vm->traps().unregisterMirror(m_stackMirror);
clearJSCallICs(*m_vm);
for (auto& slot : importFunctionInfos())
std::destroy_at(&slot);
for (auto& slot : baselineDatas())
std::destroy_at(&slot);
- if (m_anchor) {
- m_anchor->tearDown();
- m_anchor = nullptr;
- }
}
Patch Details
m_anchor->tearDown() moves to the very first action of the destructor, before any owned state is destroyed.
Publish/unpublish ordering inversion in a destructor: a thread-safe handle to the object is torn down AFTER the object's owned state is destroyed, leaving a race window where another thread can recover and dereference the partially-destroyed object.
Background
JSWebAssemblyInstance owns per-instance Wasm state (import call link info, tables, per-function baseline profile data). Wasm::InstanceAnchor is a thread-safe-refcounted weak handle that lets the concurrent compiler thread find a live instance from a Wasm::Module; it holds the instance pointer under m_lock. Wasm::Module::m_anchors is a ThreadSafeWeakHashSet<InstanceAnchor> the compiler thread walks in createMergedProfile to combine baseline profiles before tier-up.
Analysis
finishCreation explicitly publishes the instance to m_anchors (commented as "Expose it to the concurrent compiler"). Symmetric unpublishing must be the first destructor step; instead, it was last.
Aaaaaaa Aaaaa Aaaa Aaa Aaaaaaaaaa Aaaaaa Aaaaaaaaaaa Aaa Aaaa Aaaaaa Aaaa Aaaaaa Aaaa Aaa Aaaaaaaaaa Aaaaaaaaaaa Aaaaa Aaaaaaa Aaaa Aaaaaaaaaaa Aaaaaaaaaaa Aaaaaaa Aa Aaa Aaaa Aaaaaa Aaaaa Aaaaaaaaaaaaa Aaaaaaaa Aaaaaaaa Aa a Aaa Aaaa Aa Aaaaaaa Aaaaaaa Aaaaaaaa Aaaa Aaaa Aaaaaaa Aaa Aaa Aaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaa a Aaaaa Aaaaaaaaaa Aaaaaaaaaa Aaa Aaaaaa Aaa Aaaaaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaa Aaa Aaa Aaa Aaaaaaa Aaa Aaa Aaaaaaaaaaaaaaa Aaaaaaaaaaaaa Aaa Aaaaaaaa Aaaaaa Aaaaa a Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaa Aaa Aaaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaaaaa Aa Aaaaaaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaa Aaa Aaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaaa Aa Aaa Aaaaaaaa Aaaaaa Aaa Aaa Aaaaaa Aaaa Aaaaa Aaa Aaaaa Aa Aaaaaaaa Aaaaaaaa Aaaaaaaaaaa Aaaa Aaaaa Aaa Aaaaa a Aaaaaaaaaa Aaaaaaa Aaaaa a Aaa Aaaaaaaaa Aa Aaaaaaaaaaaa Aaaa Aaaaaaaa Aaaa Aaaaaa Aaa Aaaaaaaaaa Aaaaaaaa
🔒Explores the publish/unpublish symmetry that was inverted here, and what an attacker would need to win the destructor race from web content.
Subscribe to read more
Audit directions
a Aaaaaaaaaaaaa Aa Aaaaaaa Aaaaaaaaa Aa Aaaaaaaaaaa Aaaa Aaaaaaaaaaaaa Aaaaa Aaa Aaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaa Aa Aaa Aaa Aaaaaaaa Aaa Aaaaa Aaaaaa Aaa Aaaaaaaaaaaa Aaaaa Aaaaaa Aa Aa Aaaa Aaaa Aaa Aaaaaa Aaaaa Aaa Aaaa Aaaa Aaa Aaaaaa Aaaaa
a Aaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaa Aaa Aaa Aaaaaaaaaaa Aaaaaaaa Aaaaaaaaaa Aaaaaaaa Aa Aaaaaaaaa Aaaa Aaaaaaaaaaaaaaaa Aaa Aaaaaa Aaa Aaaaaaaa Aaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaa
a Aaaaaaaaaaaaaaaaa Aaaaaaa Aaaaaaa Aaaaa Aaaaaaa Aaaa Aaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaa Aaaaaaaaa Aaaaaaaaaaaa Aaaaa Aaaaaaa Aaaa Aaaa Aaa Aaaa Aaaaaaaaaaaa Aaaaa Aaa Aaa Aaaa Aaaaaa Aaaaaaa Aaaaaaaaaaaa Aaaa Aaa Aaaaaaaaaaa
a Aaaaaaa Aaaaaaaaaaa Aaaaaaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaa Aaaaaa Aaaaaaaaaaaa Aaaa Aaaaa Aaa Aaaaa Aaaaaaaaa
🔒Several reusable audit patterns identified for destructor/registry ordering bugs across JSC's concurrent subsystems, with concrete starting points for variant discovery.
Subscribe to read more