[15] ScrollerMac cross-thread UAF
Rated High because the diff fixes a deterministic cross-thread UAF: in-flight
NSAnimationcallbacks on theWebCore: Scrollingthread dereferenced aCheckedPtr<ScrollerMac>after the owningScrollerPairMachad freed it on the main thread.
ScrollerMac was held in WebScrollbarPartAnimationMac and WebScrollerImpDelegateMac via CheckedPtr — non-owning, no cross-thread synchronization. Once ScrollerPairMac::~ScrollerPairMac ran on the main thread, the scrolling thread's [setCurrentProgress:] callback dereferenced freed memory.
Source/WebCore/page/scrolling/mac/ScrollerMac.h
Source/WebCore/page/scrolling/mac/ScrollerMac.mm
Patch Details
ScrollerMac becomes ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr<ScrollerMac, DestructionThread::Main>. Delegates hold ThreadSafeWeakPtr<ScrollerMac> and promote to local RefPtr per callback. ScrollerPairMac stores its scrollers as Ref<ScrollerMac>. ~ScrollerMac() asserts isMainThread(). Null guards on m_pair cover lastKnownMousePositionInScrollbar, visibilityChanged, updateMinimumKnobLength for the window where a scrolling-thread RefPtr outlives ScrollerPairMac.
Non-owning cross-thread pointer to an object whose lifetime is bound to a different thread, with no synchronization between callback dispatch and destruction.
Background
ScrollerMac is the per-orientation scrollbar object in macOS WebCore; one vertical and one horizontal per ScrollerPairMac. WebScrollbarPartAnimationMac is an NSAnimation subclass whose setCurrentProgress: is invoked by AppKit's display-link from the WebCore: Scrolling thread. CheckedPtr<T> pairs with CanMakeCheckedPtr to assert at dereference that the pointee is still alive — debug-time UAF detection only, no cross-thread safety. ThreadSafeWeakPtr::get() returns a RefPtr<T> atomically. DestructionThread::Main routes the final delete to the main thread.
Analysis
CheckedPtr looks like "safe raw pointer" but its safety guarantee covers only same-thread access. Across threads it provides neither lifetime extension nor synchronization.
The fix shape is becoming the canonical remediation in WebKit for this class. The accompanying null guards on m_pair reveal a secondary subtlety: once ScrollerMac can outlive ScrollerPairMac (because a scrolling-thread callback briefly holds a RefPtr), every back-pointer member access becomes nullable.
This vulnerability weakens memory safety inside the WebContent process. The invariant that a ScrollerPairMac-owned object would not be touched by the scrolling thread after main-thread teardown was violated whenever an in-flight NSAnimation callback raced the destructor.
Audit directions
CheckedPtr<T>as a cross-thread back-reference from Objective-C delegates. GrepSource/WebCoreforCheckedPtr<fields inside@interfaceblocks and forCheckedPtr { _...}dereferences inside selectors that AppKit may dispatch from non-main threads (display links,NSAnimation,NSURLSession).UniqueRef<T>owning an object referenced from non-owner threads. Single ownership is incompatible with cross-thread callback survival. AuditSource/WebCore/page/scrollingandSource/WebKit/UIProcess/ViewGestureController*.- Back-pointers (
m_pair,m_parent,m_owner) inside classes that just acquired their own refcount. Every dereference of those back-pointers from a thread-callable method needs a null check after local promotion. WTF::DestructionThread::Mainomission. GrepThreadSafeRefCountedsubclasses inSource/WebCore/page/scrollingand Cocoa-bridging layers whose destructors touch AppKit/CoreAnimation but don't specifyDestructionThread::Main.