← All issues

[6] MediaPlayerPrivateMediaSourceAVFObjC re-entrant KVO during destruction

Severity: Medium | Component: WebCore platform media | 4193d2c

Severity가 Medium으로 평가된 이유는, KVO re-entrancy를 통해 이미 소멸된 m_logger에 접근하는 MediaPlayerPrivateMediaSourceAVFObjC의 teardown 중 UAF를 수정하는 fix이기 때문입니다. Attacker가 행사할 수 있는 영향력은 teardown 형태를 조작하는 수준에 그치며, 즉각적인 결과는 제어 가능한 read/write가 아닌 renderer crash입니다.

~MediaPlayerPrivateMediaSourceAVFObjC()의 맨 앞에서 모든 weak pointer를 revoke하여, member 소멸 도중 발생하는 re-entrant callback을 차단합니다. C++은 선언 역순으로 member를 소멸하므로, m_loggerm_mediaSourcePrivate보다 먼저 소멸됩니다. m_mediaSourcePrivate의 destructor는 동기적으로 KVO notification을 발생시킬 수 있으며, 이 notification은 부분적으로 소멸된 객체에서 WeakPtr로 보호된 callback을 호출합니다. CanMakeWeakPtr base 클래스의 destructor는 모든 derived class member destructor가 완료된 후에야 실행됩니다. 이 시점까지 WeakPtr::get()은 여전히 null이 아닌 값을 반환하여, callback이 이미 소멸된 member에 접근하는 상황이 발생합니다.

Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm

MediaPlayerPrivateMediaSourceAVFObjC::~MediaPlayerPrivateMediaSourceAVFObjC()
{
ALWAYS_LOG(LOGIDENTIFIER);
 
+ // member 소멸 중 re-entrant callback을 방지합니다. 이 코드가 없으면
+ // m_mediaSourcePrivate 소멸 중 발생한 KVO notification이
+ // WeakPtr로 보호된 callback을 통해 부분적으로 소멸된 객체를
+ // 재진입합니다(예: error callback이 setNetworkState()를 호출하고,
+ // 이미 소멸된 m_logger에 접근하는 경우).
+ weakPtrFactory().revokeAll();
+
cancelPendingSeek();
m_seekTimer.stop();
dispatchToRendererQueue([](auto& renderer) {
renderer.pause();
});
}

Destructor 맨 앞에 weakPtrFactory().revokeAll() 한 줄이 추가되었습니다. 이 호출은 해당 객체를 가리키는 모든 WeakPtr를 무효화합니다. 이후 m_mediaSourcePrivate 같은 member가 소멸되는 과정에서 KVO notification이 발생하더라도, WeakPtr를 역참조하여 부분적으로 소멸된 인스턴스로 돌아오는 경로가 차단됩니다.

Teardown 중 re-entrant callback이 도달할 수 있는 member를 소멸하기 전에 weak reference를 무효화하지 않은 패턴.

WebKit의 WeakPtr는 non-owning reference로, CanMakeWeakPtr CRTP base를 통해 대상 객체에 저장된 WeakPtrFactory가 backing storage 역할을 담당합니다. Factory가 revoke되거나 소멸된 이후에만 WeakPtr::get()은 null을 반환합니다. C++에서 derived class의 member는 선언 역순으로 소멸되며, 이후 base class destructor가 실행됩니다. Factory를 revoke하는 CanMakeWeakPtr의 destructor는 base destructor에 해당하므로, 모든 derived class member destructor가 완료된 후에야 실행됩니다. KVO(Key-Value Observing)는 Cocoa의 observer pattern으로, AVFoundation 객체는 등록된 observer에게 동기적으로 KVO notification을 전달합니다. MediaPlayerPrivateMediaSourceAVFObjCMediaSourcePrivateAVFObjC 타입의 m_mediaSourcePrivate와 Logger 참조인 m_logger를 보유합니다. setNetworkState()는 network 상태 변화를 처리하는 MediaPlayer의 표준 hook입니다. 이 구현에서는 m_logger를 통해 상태 변화를 로그에 기록합니다.

이 destructor는 CanMakeWeakPtr의 기본 teardown 순서에 의존하고 있었습니다. WeakPtrFactory는 base destructor가 실행될 때만 revoke되는데, 이 시점은 모든 derived class member가 이미 소멸된 이후입니다. Member 소멸 과정, 특히 m_mediaSourcePrivate의 destructor가 실행되는 동안 AVFoundation은 동기적으로 KVO notification을 발생시킬 수 있습니다. 이 notification들은 WeakPtr로 보호된 callback을 통해 전달됩니다. 이 시점에는 factory가 아직 revoke되지 않은 상태이므로, WeakPtr::get()은 여전히 null이 아닌 pointer를 반환합니다.

🔒

The ownership and destructor-ordering implications of this bug, and whether the resulting crash can be escalated beyond a renderer DoS, are analyzed in depth.

더 확인하려면 구독해 주세요

🔒

Multiple reusable audit patterns identified for finding sibling bugs across WebKit's Cocoa-observer-owning classes, with concrete starting points for variant discovery.

더 확인하려면 구독해 주세요