← All issues

[8] Wasm GC Type Dependency Tracking: Missing Subtype Expansion

Severity: Medium | Component: JSC WebAssembly GC | a0d2715

Medium으로 평가한 근거는 다음과 같습니다. Subtype indirection을 통해 도달 가능한 type definition의 GC root가 누락되는 현상이 관측되며, 이는 type metadata의 조기 수집과 use-after-free로 이어질 수 있는 논리 오류입니다. 다만 실제 조기 수집을 유발하려면 특정 GC timing과 중첩된 Subtype 계층이 필요합니다. 수정이 단일 라인의 canonicalization인 점을 고려하면, 신뢰할 수 있는 exploit이 구성되기 전에 sanitizer에 의해 포착되었을 가능성도 있습니다.

WebAssemblyGCStructureTypeDependencies::process(Wasm::FieldType, WorkList&).expand() 호출이 추가되었습니다. 이제 field의 type이 Subtype인 경우, unexpanded form 대신 expanded(실질적인) type definition이 work list에 추가됩니다.

Source/JavaScriptCore/wasm/js/WebAssemblyGCStructure.cpp

void WebAssemblyGCStructureTypeDependencies::process(Wasm::FieldType fieldType, WorkList& work)
{
if (fieldType.type.is<Wasm::Type>()) {
Wasm::Type type = fieldType.type.as<Wasm::Type>();
if (isRefWithTypeIndex(type)) {
- SUPPRESS_UNCHECKED_LOCAL const auto& typeDef = Wasm::TypeInformation::get(type.index);
+ SUPPRESS_UNCHECKED_LOCAL const auto& typeDef = Wasm::TypeInformation::get(type.index).expand();
work.append(typeDef);
}
}
}

dependency 순회 전 Wasm GC subtype reference의 canonicalization 누락으로 인해, expanded type을 통해서만 도달 가능한 transitive dependency가 type graph 탐색에서 누락된 패턴.

WebAssembly GC(gc proposal)는 JavaScript GC가 관리하는 struct 및 array type을 도입합니다. Type은 sub 키워드를 통해 subtype 계층을 형성할 수 있으며, Subtype은 추가 제약이 있는 parent type을 감싸는 형태입니다. WebKit 내부에서는 "unexpanded" type definition(Subtype wrapper일 수 있는 형태)과 "expanded" type definition(실제 field를 가진 canonical 구조 형태)을 구분합니다. 이 indirection을 해소하는 것이 .expand() 메서드입니다. WebAssemblyGCStructureTypeDependencies는 GC structure의 type definition으로부터 도달 가능한 모든 type을 graph 순회 방식으로 탐색합니다. 이를 통해 structure가 살아있는 동안 어느 type definition을 유지해야 하는지 GC에 알립니다.

수정 이전에는 process 메서드가 field의 type index에 해당하는 type definition을 조회할 때 .expand()를 호출하지 않았습니다. Subtype field의 경우, unexpanded type definition은 단순한 wrapper/alias에 불과합니다. 실제 field를 가진 structural type은 expanded form에 존재합니다. unexpanded form을 work list에 추가하면, 순회 과정에서 재귀적으로 탐색할 field가 없는 type을 만나게 됩니다. fix 패턴으로 미루어 볼 때, unexpanded Subtype definition에는 structural field가 없는 것으로 보입니다. 결과적으로 실제 expanded type과 그것의 모든 transitive dependency는 끝내 스캔되지 않았습니다.

이 inconsistency는 주목할 만합니다. constructor에서는 초기 type에 .expand()를 이미 호출하고 있었지만, field 수준의 재귀 호출에서는 누락되어 있었습니다. 한 entry point에서 canonicalization이 적용되었지만 재귀 호출 지점에서는 빠진, 전형적인 패턴입니다.

🔒

The ownership and lifetime implications of this GC dependency tracking gap are explored in depth

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

🔒

Multiple reusable audit patterns identified, with concrete starting points for variant discovery across the Wasm GC type system

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