← All issues

[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::resolveSlotsAfterSlotMutationm_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);

assignSlots 호출이 순회 시작 전 한 번만 실행되도록 앞으로 이동되었습니다(m_slotAssignmentsIsValid가 false일 때만). 이를 통해 순회가 진행되는 동안 map이 최종 레이아웃을 유지합니다. 루프 내부의 hasAssignedNodes 호출은 m_slots를 변경하지 않는 !slot->assignedNodes.isEmpty() 필드 직접 읽기로 대체되었습니다.

순회 도중 컨테이너의 mutation 경로로 재진입하는 helper에 의한 HashMap iterator 무효화.

NamedSlotAssignmentattachShadow({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가 모두 무효화됩니다.

hasAssignedNodes는 이름만 보면 읽기 전용처럼 보이지만, 실제로는 assignSlots를 호출해 m_slots에 항목을 삽입하는 mutation 동작을 수행합니다. 컨테이너를 직접 변경해 캐시를 lazy하게 채우는 predicate는, 동일한 컨테이너를 순회하는 도중 호출될 경우 위험합니다.

🔒

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.

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

🔒

Several reusable audit patterns spanning shadow DOM and other WebCore subsystems, with concrete grep targets for finding the same anti-pattern elsewhere.

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