[15] [WebKit] Pin WebPageProxy across completion handlers via RefPtr promotion
Severity: High | Component: WebKit UIProcess | 1682be9
diff에서는 여러 WebPageProxy completion handler 내의 WeakPtr<WebPageProxy>/WeakPtr<WebProcessProxy> 캡처를 RefPtr로 승격시키고 있습니다. 패치 이전의 if (!weakThis) return; weakThis->send(...); 형태는 main run loop에서 원자적으로 동작하지 않습니다. null 검사와 역참조 사이에 객체가 소멸될 수 있다는 점 때문에 High로 평가됩니다.
loadSimulatedRequest, loadAlternateHTML, reload, executeEditCommand, contextMenuItemSelected, didPerformDictionaryLookup, scheduleSetObscuredContentInsetsDispatch — 이 7개 함수에 걸쳐 동일한 패턴이 적용되었습니다. 각 함수에서 WeakPtr 캡처는 lambda 상단에서 한 번 RefPtr로 승격된 뒤, 이후 모든 호출에 사용됩니다.
Source/WebKit/UIProcess/WebPageProxy.cpp
WeakPtr 승격 지연: null 검사 이후 참조 미보유로 소멸 후 메서드 호출이 발생하는 패턴.
Patch Details
각 lambda는 메서드를 호출하기 전에 weak 캡처를 RefPtr(또는 Ref)로 승격합니다. loadSimulatedRequest가 가장 심각한 사례로, null 검사가 전혀 없는 상태에서 weakProcess를 직접 역참조하고 있었습니다. 나머지 호출 지점들은 if (!weakThis) return; 형태를 사용해 생존 여부는 확인했지만, 이후 호출에서 대상 객체의 소멸을 막지는 못했습니다.
Background
WeakPtr::operator bool은 현재 생존 여부만을 알려줄 뿐, 객체의 lifetime을 연장하지 않습니다. WebPageProxy의 completion handler는 main run loop(callOnMainRunLoop)에서 dispatch되거나, 비동기 sandbox-extension 처리 후 실행됩니다. null 검사와 최종 역참조 사이에, 관계없는 소유자가 WebPageProxy / WebProcessProxy에 대한 마지막 Ref를 해제할 가능성이 있습니다.
Analysis
패치 이전 코드에는 두 가지 subpattern이 존재했습니다:
(1) weakProcess->send(...); // null 검사 없이 직접 역참조, UAF 직행
(2) if (!weakThis) return; // 생존 확인 시점
... // 관련 없는 작업
weakThis->send(...); // 이 시점에서 dangling 가능