[15] ScrollerMac cross-thread UAF
Severity: High | Component: WebCore macOS scrolling | a926a67
High로 평가된 이유는 이 diff가 매번 재현 가능한 cross-thread UAF를 수정하기 때문입니다. WebCore: Scrolling 스레드에서 실행 중이던 NSAnimation callback이, main thread에서 ScrollerPairMac이 해제한 CheckedPtr<ScrollerMac>를 역참조하고 있었습니다.
ScrollerMac은 WebScrollbarPartAnimationMac과 WebScrollerImpDelegateMac에서 CheckedPtr로 참조되는 구조였습니다. 소유권도 없고 cross-thread 동기화도 없는 참조 방식이었습니다. main thread에서 ScrollerPairMac::~ScrollerPairMac이 실행된 이후, scrolling thread의 [setCurrentProgress:] callback이 이미 해제된 메모리를 역참조하게 됩니다.
Source/WebCore/page/scrolling/mac/ScrollerMac.h
-class ScrollerMac final : public CanMakeThreadSafeCheckedPtr<ScrollerMac> {
+class ScrollerMac final : public ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr<ScrollerMac, WTF::DestructionThread::Main> {
Source/WebCore/page/scrolling/mac/ScrollerMac.mm
@interface WebScrollbarPartAnimationMac : NSAnimation {
- CheckedPtr<WebCore::ScrollerMac> _scroller;
+ ThreadSafeWeakPtr<WebCore::ScrollerMac> _scroller;
- (void)setCurrentProgress:(NSAnimationProgress)progress
{
[super setCurrentProgress:progress];
+ RefPtr scroller = _scroller.get();
+ if (!scroller)
+ return;
Patch Details
ScrollerMac은 ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr<ScrollerMac, DestructionThread::Main>으로 변경되었습니다. Delegate들은 ThreadSafeWeakPtr<ScrollerMac>을 보유하며, callback마다 local RefPtr로 승격합니다. ScrollerPairMac은 scroller를 Ref<ScrollerMac>으로 저장합니다. ~ScrollerMac()은 isMainThread()를 assert합니다. 한편 m_pair에 대한 null 검사가 lastKnownMousePositionInScrollbar, visibilityChanged, updateMinimumKnobLength에 추가되었습니다. 이는 scrolling thread의 RefPtr이 ScrollerPairMac보다 오래 유지될 수 있는 구간을 처리하기 위한 조치입니다.
객체의 lifetime이 다른 스레드에 귀속된 상태에서, callback 실행과 소멸 사이에 동기화 없이 non-owning cross-thread pointer를 사용한 패턴.
Background
ScrollerMac은 macOS WebCore에서 방향별 scrollbar 객체입니다. ScrollerPairMac당 수직과 수평 각각 하나씩 존재합니다. WebScrollbarPartAnimationMac은 NSAnimation의 서브클래스로, setCurrentProgress:는 AppKit의 display-link에 의해 WebCore: Scrolling 스레드에서 호출됩니다. CheckedPtr<T>은 CanMakeCheckedPtr과 쌍을 이루어, 역참조 시점에 대상 객체가 살아있는지 assert합니다. 다만 이는 debug 시 UAF 감지 용도일 뿐이며, cross-thread 안전성은 보장하지 않습니다. ThreadSafeWeakPtr::get()은 RefPtr<T>을 원자적으로 반환하며, DestructionThread::Main은 최종 delete가 main thread에서 실행되도록 라우팅합니다.
Analysis
CheckedPtr은 "안전한 raw pointer"처럼 보이지만, 안전성 보장은 동일 스레드 내 접근에만 적용됩니다. 스레드를 넘어서면 lifetime 연장도 동기화도 기대할 수 없습니다.
a Aaa Aaa Aaaaaaaa a Aaa Aaa Aa Aaaa Aa Aaaa Aaaa Aaaaa Aaaaaaaaa Aa Aaaa Aaa Aa Aaaaa Aa Aaaa Aaaa Aaaaaa Aaaaaaaaa Aaaaaaa Aaaaaaaaa Aa Aaaaaaaaa Aaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaa Aa a a Aa Aaa Aa Aaaaaaaaaaaa Aaa Aa Aa Aaa Aaaaaaaaaaaaa
a Aaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaa Aaa Aaa Aaaa Aaaaaaa Aaaaaaaaaaaaaaaaa Aa Aaa Aaaa Aaaaaaaa Aaa Aa Aaaaaaaaa Aaaaaaa Aa Aaaa Aaaa Aaaaaaaaaa Aaaaaaa Aaa Aa Aa Aaaaaaaaaaaaa Aaaaaaaaa Aaaaaaaaaaa Aaaa Aaaaa a Aaa Aaaaaa
🔒Detailed cross-thread lifetime analysis covering the race window and reclamation feasibility for this scrolling-thread crash
더 확인하려면 구독해 주세요
Audit directions
a Aaaaaaaaaaaaaaaaa Aa a Aaaaaaaaaaaa Aaaaaaaaaaaaaa Aaaa Aaaaaaaaaaa Aaaaaaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaa Aa Aa Aaaaaaaaaaaaa Aaa Aa Aaa Aaaaaa Aa Aaaaaaa Aaaaaaaa Aaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaa a Aa Aaaaaaaa Aaa Aaaaaaaaaaaa Aaaa Aaaaaa Aaaaaa
a Aaaaaaaaaaaaaaaa Aaaaaa Aa Aaaaaa Aaaaaaaaaa Aaaa Aaaaaaaaa Aaaaaaaaaa Aa Aaaa Aaaaaaaaaaaa Aaaaaaaa Aaa Aaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa
a Aaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaaaa Aaaaaaaaaa Aaaaaa Aaaaaaa Aaaa Aaaa Aaaaaaaa Aaaaa Aaa Aaaaaaaaaaa Aaaaa Aa Aaa Aaaaa Aaa Aaaaaaaaaaaaa Aaaa Aaaa Aaaaa Aa Aa Aaaa Aaa Aaaaaa
a Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaa a Aaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aa Aaa Aaaaaa
🔒Four reusable audit patterns identified for cross-thread lifetime bugs in Cocoa-bridging code, with concrete starting points across WebCore scrolling and platform layers
더 확인하려면 구독해 주세요