[15] [WebKit] Pin WebPageProxy across completion handlers via RefPtr promotion
Rated High because the diff promotes captured WeakPtr<WebPageProxy>/WeakPtr<WebProcessProxy> to RefPtr in multiple WebPageProxy completion handlers; the pre-fix shape if (!weakThis) return; weakThis->send(...); is not atomic on the main run loop and the object can be destroyed between the null check and the dereference.
Across loadSimulatedRequest, loadAlternateHTML, reload, executeEditCommand, contextMenuItemSelected, didPerformDictionaryLookup, and scheduleSetObscuredContentInsetsDispatch, WeakPtr captures are promoted to RefPtr once at the top of the lambda and used for the rest of the call.
Source/WebKit/UIProcess/WebPageProxy.cpp
WeakPtr promoted-too-late: the null check tested liveness, but the subsequent method call could run after destruction because no reference was held across the gap.
Patch Details
Each lambda promotes its weak capture to RefPtr (or Ref) before any method call. loadSimulatedRequest is the most egregious case — it had no null check at all and dereferenced weakProcess directly. The other call sites had the if (!weakThis) return; shape that is correct for liveness but does not pin the pointee for subsequent calls.
Background
WeakPtr::operator bool reports current liveness; it does not extend lifetime. Completion handlers in WebPageProxy are dispatched on the main run loop (callOnMainRunLoop) or fired after asynchronous sandbox-extension processing. Between the null check and the final dereference, an unrelated owner can drop its last Ref to the WebPageProxy / WebProcessProxy.
Analysis
Two pre-fix subpatterns:
(1) weakProcess->send(...); // no null check, direct UAF
(2) if (!weakThis) return; // liveness window
... // unrelated work
weakThis->send(...); // dangling here
The race is internal to the main run loop: a completion handler running unrelated work between the check and the dereference is enough for another event-loop task to destroy the proxy. The fix is the standard WebKit idiom — promote to RefPtr once and hold it for the lambda's duration.
The primitive is UAF on WebPageProxy / WebProcessProxy reached via completion-handler dispatch. The exploit shape involves driving the dispatch race during page teardown.
This weakens the UI-process completion-handler lifetime invariant across navigation and edit-command paths.
Audit directions
- Every
WeakPtrcapture in a completion handler acrossSource/WebKit/UIProcess. Grep forweakThis/WeakPtr {in lambda contexts and confirm aRefPtrpromotion at the top. callOnMainRunLoop-dispatched callbacks that reach into sandboxed or async paths. The dispatch boundary is the gap that turns aWeakPtrnull check into a TOCTOU.WebProcessProxycompletion-handler users. The same race exists at the process level — promotion pattern should match.