[13] NamedSlotAssignment iterator-invalidation UAF
Severity: High | Component: WebCore Shadow DOM | 20beac1
HashMap rehash-during-iteration UAF를 수정하는 패치이므로 High로 평가합니다. for (auto& slot : m_slots.values()) 루프 내부에서 호출된 lazy-cache helper가 m_slots에 새 항목을 다시 삽입해 루프의 value reference를 무효화합니다. 이후 slot->seenFirstElement = true 저장과 WTF::move(slot->element) 호출은 해제된 메모리를 통해 쓰기를 수행합니다.
NamedSlotAssignment::resolveSlotsAfterSlotMutation은 m_slots.values()를 순회합니다. 루프 내부에서 hasAssignedNodes(shadowRoot, *slot)이 lazy하게 assignSlots(shadowRoot)를 호출하며, 이 함수는 아직 등록되지 않은 slot 이름에 대해 m_slots에 새 항목을 삽입합니다. 삽입이 발생할 때마다 rehash가 일어나 value storage가 재배치될 수 있습니다.
Source/WebCore/dom/SlotAssignment.cpp
+ if (!m_slotAssignmentsIsValid)
+ assignSlots(shadowRoot);
+
for (auto& slot : m_slots.values()) {
if (slot->seenFirstElement)
continue;
...
slot->seenFirstElement = true;
ASSERT(slot->element);
- if (hasAssignedNodes(shadowRoot, *slot))
+ if (!slot->assignedNodes.isEmpty())
slot->oldElement = WTF::move(slot->element);
Patch Details
assignSlots 호출이 순회 시작 전 한 번만 실행되도록 앞으로 이동되었습니다(m_slotAssignmentsIsValid가 false일 때만). 이를 통해 순회가 진행되는 동안 map이 최종 레이아웃을 유지합니다. 루프 내부의 hasAssignedNodes 호출은 m_slots를 변경하지 않는 !slot->assignedNodes.isEmpty() 필드 직접 읽기로 대체되었습니다.
순회 도중 컨테이너의 mutation 경로로 재진입하는 helper에 의한 HashMap iterator 무효화.
Background
NamedSlotAssignment는 attachShadow({mode: 'open' | 'closed'})로 선언된 shadow tree의 기본 slot-assignment 전략입니다. m_slots라는 HashMap<AtomString, std::unique_ptr<Slot>>을 관리하며, 각 Slot에는 활성 <slot> element, oldElement, assignedNodes 목록, 그리고 slot별 플래그가 기록됩니다. m_slotAssignmentsIsValid는 캐시가 오래된 상태일 수 있을 때 초기화되는 dirty bit입니다. assignSlots(shadowRoot)는 host child를 순회하며 새로운 slot 이름에 해당하는 m_slots 항목을 삽입합니다. HashMap 삽입 시 rehash가 발생하면 iterator와 reference가 모두 무효화됩니다.
Analysis
hasAssignedNodes는 이름만 보면 읽기 전용처럼 보이지만, 실제로는 assignSlots를 호출해 m_slots에 항목을 삽입하는 mutation 동작을 수행합니다. 컨테이너를 직접 변경해 캐시를 lazy하게 채우는 predicate는, 동일한 컨테이너를 순회하는 도중 호출될 경우 위험합니다.
Aa Aaa Aaa Aaaaaaa Aaa Aaa Aaaaa Aa Aaaaaaa Aaaaaaaaaa Aaaaaaaaaa Aaaa Aaaaaa Aaaaa Aaaaaaaaaa Aa Aaaa Aaaaaaaa Aaaa Aaaa Aaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaaaa Aaaa Aaaaaaaaaa Aa Aaaa Aa Aaa Aaaaaa Aaa Aa Aaaa Aaaaaa Aaaa Aaaaaa Aaaaaa Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aa Aaaa a Aa Aaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaa Aaaaa a Aaa a Aaaa Aaaaaaaaaaaaaaa Aa Aaa Aaaaaaa Aaaaaa a Aaaa Aaa Aaaaaa Aaaaaaaaaa Aaaaaaaa Aaaaaaaaa Aa Aaa Aaaaa Aaaaaaaa Aaaa Aaaa Aa Aaaaaaaaaaaaaaaaaaaaaaa a Aaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaa Aa Aaaaaaa Aaaa Aaaaaaaaa Aa Aaa Aaaaaaa Aaaaaaaa Aaaa Aaaa Aaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaa Aaa Aaaaaa Aa Aaa Aa Aaaaaaaaaaa Aaa a Aaaaa
a Aaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaa Aaaaaa Aaaaaaa Aaaaaaa Aaaaaa Aaa Aaa Aaaa Aaaaaaaaaaa Aaa Aaa Aaaaaaaa Aaaaa Aaaaaaa Aaa Aaaa Aaaaaa Aa Aaa Aaa Aaa Aa Aaaa Aaaaaa
🔒How a query-shaped helper turned a routine slot-resolution loop into a renderer memory-safety bug, and what an attacker would need to escalate beyond a crash.
더 확인하려면 구독해 주세요
Audit directions
a Aaaa Aaaa Aaaa Aaaaa Aaaa Aaaaaaaaaa Aaaaaaaaaaaa Aaaaaaaaa Aaaaaaa Aaaaaa Aaaaaaaa Aaaaaaaaaaa Aaa Aaaaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaa Aaa Aaaaaa Aa Aaaa Aaaaaa a a Aaaaaaaaaaaaaaaaaaaa Aaaa Aaaa Aaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a Aa Aaaaaaaaaaaaaaaa Aaaaa Aaaaaa
a Aaaaa Aaaa Aaaa Aa Aaaaaaaaaaaaaa Aaaaa Aaaa Aaaaaa Aa a Aaaaaaaaaaaaaaa Aaaa Aa Aaaa Aaa Aaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaa Aaaaaa Aaaaaaaaaa Aaaaaaaaaaaaaaaa Aaa Aaa Aaaaaa
a Aaaaaaaaaa Aaa Aaaaaaaa Aaaa Aaaaaaaaa Aa Aaaa Aaaaaa Aaaaaaa Aaa Aaa Aa Aaaa Aaaaaa Aa Aaa a Aaa Aaaaa Aaaaaa Aaaaaaaaaaa a Aaaaaaaaaaaa Aaaa Aaaaaa
a Aaaaaaaaa Aaaaaaa Aaaa Aaa Aaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aa Aaaa Aa Aaaa Aaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaa Aaa Aa Aaaa Aaaaaaaaaaaaaaa Aaaaa Aaaaaa Aaaaaa
🔒Several reusable audit patterns spanning shadow DOM and other WebCore subsystems, with concrete grep targets for finding the same anti-pattern elsewhere.
더 확인하려면 구독해 주세요