← All issues

[12] Wasm InstanceAnchor unregistered too late in destructor

Severity: High | Component: JSC Wasm runtime | 76b3468

High로 평가된 이유는 destructor 내 publish/unpublish 순서 역전이 수정되었기 때문입니다. 수정 이전에는 per-instance 상태를 먼저 해제한 뒤, compiler thread가 instance를 찾는 데 사용하는 thread-safe handle을 나중에 해제하는 구조였습니다. 그 사이 넓은 race window가 존재해, compiler thread의 profile merge가 이미 해제된 baselineData slot을 읽을 가능성이 있었습니다.

~JSWebAssemblyInstancem_anchor->tearDown()을 호출하기 전에, unregisterMirror, clearJSCallICs, 그리고 importFunctionInfos, tables, baselineDatas에 대한 std::destroy_at 루프를 먼저 실행했습니다. 그러나 compiler thread가 live instance를 찾는 데 사용하는 것이 바로 이 anchor입니다.

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;
- }
}

m_anchor->tearDown()이 destructor의 가장 첫 번째 동작으로 이동했습니다. owned state가 해제되기 전에 먼저 호출됩니다.

Destructor 내 publish/unpublish 순서 역전 패턴. 객체의 owned state가 먼저 해제된 뒤에야 thread-safe handle이 해제되는 구조로, 다른 thread가 부분적으로 해제된 객체를 회수해 역참조할 수 있는 race window가 발생합니다.

JSWebAssemblyInstance는 per-instance Wasm 상태(import call link info, table, per-function baseline profile data)를 소유합니다. Wasm::InstanceAnchor는 thread-safe-refcounted weak handle로, concurrent compiler thread가 Wasm::Module로부터 live instance를 찾는 데 사용됩니다. instance pointer는 m_lock 하에 저장됩니다. Wasm::Module::m_anchorsThreadSafeWeakHashSet<InstanceAnchor> 타입입니다. compiler thread는 tier-up 전에 baseline profile을 통합하기 위해 createMergedProfile에서 이 컬렉션을 순회합니다.

finishCreation에서는 instance를 m_anchors에 명시적으로 등록합니다. 코드 주석에도 "Expose it to the concurrent compiler"라고 명시되어 있습니다. 이에 대응하는 등록 해제는 destructor의 첫 번째 동작이어야 하지만, 실제로는 마지막에 위치했습니다.

🔒

Explores the publish/unpublish symmetry that was inverted here, and what an attacker would need to win the destructor race from web content.

더 확인하려면 구독해 주세요

🔒

Several reusable audit patterns identified for destructor/registry ordering bugs across JSC's concurrent subsystems, with concrete starting points for variant discovery.

더 확인하려면 구독해 주세요