← All issues

[16] [JSC] Fix data race in WaiterListManager::unregister

Severity: Medium | Component: JSC WaiterListManager | 21ab50e

패치에서는 Waiter 생성 시점에 realm pointer를 캐시하여 cancellation 판단 시 VM 경계를 넘는 읽기가 발생하지 않도록 처리했습니다. 이 점 때문에 Medium으로 평가됩니다. 패치 이전에는 한 VM의 sweep thread에서 WaiterListManager::unregister가 실행되는 도중, 다른 VM의 GC End phase가 m_dependencies를 수정하고 있었습니다. 특정 스케줄링 조건에서는 torn 상태이거나 이미 해제된 pointer를 역참조하는 문제가 발생할 수 있었습니다.

Waiter는 생성 시점(어떤 리스트에도 등록되기 전)에 realm pointer를 캐시합니다. WaiterListManager::unregisterticket->target()->realm() 대신 이 캐시된 pointer를 참조합니다.

Source/JavaScriptCore/runtime/WaiterListManager.cpp

- JSGlobalObject* targetRealm = waiter->ticket(listLocker)->target()->realm();
+ JSGlobalObject* targetRealm = waiter->cachedRealm();

변경 중인 storage에 대한 cross-VM 읽기: 한 VM의 sweep thread가 다른 VM 소속의 waiter를 순회하며 m_dependencies를 역참조하는 동안, 해당 VM의 GC End phase가 이를 수정하고 있었습니다.

Waiter에 생성 시 설정되는 JSGlobalObject* 멤버가 추가되었습니다. unregister는 cancellation 여부를 판단할 때 이 캐시된 pointer만 읽습니다. WaiterList의 구조적 변경에 대한 직렬화는 list lock이 계속 담당합니다.

WaiterListManager는 SharedArrayBuffer의 Atomics.wait / Atomics.waitAsync를 지원하는 per-process registry입니다. SAB는 main window, iframe, dedicated worker 등 여러 VM에 걸쳐 공유됩니다. 이 때문에 SAB pointer를 키로 하는 단일 WaiterList에 서로 다른 VM의 Waiter가 함께 담길 수 있습니다. DeferredWorkTimer::TicketData::m_dependenciesFixedVector<JSCell*> 타입입니다. wait 중 promise/target을 GC가 회수하지 못하도록 유지하는 역할을 담당합니다.

패치 이전에는 WaiterListManager::unregister가 unregistering VM의 sweep thread에서 실행되며 공유 리스트의 모든 waiter를 순회했습니다. 각 waiter마다 waiter->ticket(listLocker)->target()을 호출했는데, 이 함수는 bit_cast<JSObject*>(m_dependencies.last())로 구현되어 있습니다. 이를 통해 target의 realm을 unregistering global object와 비교했습니다.

🔒

What can really happen when two VMs share a single SAB waiter list and one of them tears down its realm while the other GC-frees its ticket — the cross-VM lifetime and exploitation reasoning is unpacked in depth.

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

🔒

Four reusable audit patterns identified, covering shared per-process registries, ticket-target dereferences, cached-identity-at-construction, and racy interior-pointer reads of vector backing stores.

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