[3] Use-After-Free in BaseDateAndTimeInputType::didChangeValueFromControl
Severity: High | Component: WebCore HTML forms | 869d5c5
이 diff는 해제된 this에 대해 virtual call이 여러 차례 수행되는 renderer-reachable UAF를 수정합니다. 대상은 다형 C++ 객체이며, regression test는 input event listener에서 input.type을 교체하는 20줄짜리 JS PoC입니다.
didChangeValueFromControl()은 input event를 동기적으로 dispatch합니다. 이때 event handler가 input.type을 재할당하면, 현재의 BaseDateAndTimeInputType 인스턴스가 소멸됩니다. 해당 인스턴스의 유일한 소유자는 HTMLInputElement::m_inputType입니다. handler가 반환된 뒤, 메서드는 이미 해제된 this에 대해 setupDateTimeChooserParameters()와 showDateTimeChooser() 호출을 계속 수행합니다.
Source/WebCore/html/BaseDateAndTimeInputType.cpp
bool BaseDateAndTimeInputType::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
{
- ASSERT(element());
+ RefPtr element = this->element();
+ if (!element)
+ return false;
- Ref element = *this->element();
Source/WebCore/html/BaseDateAndTimeInputType.h
+ void ref() const final { InputType::ref(); }
+ void deref() const final { InputType::deref(); }
Source/WebCore/html/shadow/DateTimeEditElement.cpp
void DateTimeEditElement::fieldValueChanged()
{
- if (m_editControlOwner)
- m_editControlOwner->didChangeValueFromControl();
+ if (RefPtr editControlOwner = m_editControlOwner)
+ editControlOwner->didChangeValueFromControl();
}
Patch Details
BaseDateAndTimeInputType은 ref()/deref() override를 통해 ref-countable 구조로 전환되었으며, 두 메서드는 모두 InputType에 위임합니다. DateTimeEditElementEditControlOwner의 기반은 CanMakeWeakPtr에서 AbstractRefCountedAndCanMakeWeakPtr로 변경되었고, DateTimeEditElement 내의 모든 m_editControlOwner 역참조는 로컬 RefPtr로 먼저 promote하는 방식으로 재작성되었습니다. setupDateTimeChooserParameters에서는 ASSERT(element())가 런타임 null check로 교체되었습니다. type swap으로 back-pointer가 초기화된 경우, 호출자가 정상적으로 처리를 중단하게 됩니다.
JavaScript re-entrancy 경계를 넘어 callback 대상을 유지하지 않은 패턴. 대상의 lifetime은 dispatch된 event가 변경할 수 있는 가변 HTML element 상태에 의존합니다.
Background
<input type=date|datetime-local|month|time|week>는 DateTimeEditElement를 기반으로 구성된 shadow tree를 통해 mm/dd/yyyy 위젯을 렌더링합니다. DateTimeEditElement는 소유자인 DateTimeEditElementEditControlOwner를 가리키는 back-pointer를 보유하며, 실제 구현체는 BaseDateAndTimeInputType입니다. 필드 값이 수정되면 DateTimeEditElement::fieldValueChanged()가 호출됩니다. 이 함수는 didChangeValueFromControl()을 통해 소유자에게 알림을 전달하고, 결과적으로 DOM input event가 발생합니다. HTMLInputElement::m_inputType은 활성 InputType 서브클래스의 유일한 소유자입니다. input.type = 'text'를 할당하면 HTMLInputElement::updateType()이 m_inputType을 교체하며, 이전 인스턴스는 소멸됩니다. WeakPtr은 lifetime을 연장하지 않고 관찰만 하는 반면, RefPtr은 lifetime을 연장합니다. AbstractRefCountedAndCanMakeWeakPtr은 두 가지를 동시에 지원합니다.
Analysis
shadow-tree control은 소유자를 bare WeakPtr로만 보유하고 있었습니다. 따라서 JS event handler가 input.type을 재할당하면, BaseDateAndTimeInputType을 살려두는 stack 참조가 존재하지 않게 됩니다. 실행 흐름이 didChangeValueFromControl()로 돌아왔을 때, 이미 해제된 this에 대해 virtual call이 계속 수행되었습니다.
Aa Aa Aaaaaaaaa Aaaaaaa Aaaaa Aaaaaaa Aa Aa Aaa Aaa Aaa Aaa Aaaaaaaaaaa Aaa Aa Aaa Aaa a Aaaaa Aaa Aa Aaaaaaaaaaa Aaaaaaaaa Aaa Aaa Aaaaaaaaaa Aaa a a Aaaaa Aa Aaa Aaa Aa Aaaaaa Aaaaaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaaaaa Aa Aa Aaaaa Aaa Aaa Aaaaa Aaaaaa Aaa Aaaaaaa Aa Aaaaaaa Aaaaaaaaa Aaaa Aaaaaaaa Aaaa a Aaaaaa Aa Aaaaaaaaaaaa Aaaaaaaa Aaaa Aaaa Aa Aaa Aaaaaa Aaaa Aaaaaaaa Aaaaa Aa Aaa Aaaa Aaa Aaaaaaaa Aaaaaaaaa
a Aaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaa Aaa Aaaaaa Aaaaaaa Aaaaaaa Aaaa Aaa Aaaaaaaaaaaa Aaa Aaaa Aaaaaa Aaaaaaaa Aaaa Aaaaa Aaaaa Aaaaaa Aa Aaaa Aaaaaaaaaaaaaa Aaaaaaa Aaaa Aaa Aa a Aaaaaaaaaa Aaaa Aaaaaa
🔒Detailed walkthrough of how a DOM event handler can free a C++ object mid-method, and the ownership and lifetime implications of the fix's structural change.
더 확인하려면 구독해 주세요
Audit directions
a Aaaaaaaaaaaa Aa Aaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa a Aaaa a Aaa Aaa a Aaaaa Aaaaaa Aaaaaaaa Aaaaaaaa Aaaa Aaa Aa Aaaaaaaaaaa Aaaaaa Aaaa Aaaa Aaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaaa Aaaaaaa a Aaaaaaaa Aaa Aa Aa Aaa Aa Aaaaaaaaaaaa Aa Aaaaaaaaa Aaaaaa Aaaaaaaaaa Aa Aa Aa Aaaaa Aaaa Aaaa
a Aaaa Aaaaaaaaaaa Aaa Aa Aa Aa Aaaaa Aaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaa Aa Aaa Aa Aaaaaa Aaaaaaaa Aaaaaaaaa Aaa Aa Aaaaa Aaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aa Aaa Aaa Aaaa Aaaa
a Aaaaaa Aaaa Aaaa Aa Aaa Aaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaa Aaaaaaaaaaaaa Aaaaa Aa Aaaa Aaa a Aa Aaaaaaa Aaa Aaaa Aaaa
a Aaaaaaaaaaaa Aaaaa Aaaaa Aaaa Aaaaa a Aaaaa Aaaaa Aaa Aaaaaaaaaaa a Aaaaaaaaa a Aaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaaaaa Aaaaaa Aa Aaaa Aaa Aa Aaa a Aaaaaa a Aaa Aaaaaa Aaa Aaaaaa a Aaa Aaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaa Aaaa Aaa a Aaaaa
🔒Several reusable audit patterns identified, including a fuzzing harness shape that generalizes this bug class across multiple form control subsystems.
더 확인하려면 구독해 주세요