[6] MediaPlayerPrivateMediaSourceAVFObjC re-entrant KVO during destruction
Severity: Medium | Component: WebCore platform media | 4193d2c
Rated Medium because the diff fixes a UAF-during-teardown of MediaPlayerPrivateMediaSourceAVFObjC via KVO re-entrancy reading the already-destroyed m_logger; attacker influence is limited to driving the teardown shape, and the immediate effect is a renderer crash rather than a controllable read/write.
Revoke all weak pointers at the start of ~MediaPlayerPrivateMediaSourceAVFObjC() to prevent re-entrant callbacks during member destruction. C++ destroys m_logger before m_mediaSourcePrivate (reverse declaration order), and the m_mediaSourcePrivate destructor can trigger synchronous KVO notifications that invoke WeakPtr-guarded callbacks on the partially-destroyed object. Since the CanMakeWeakPtr base class destructor runs after all member destructors, WeakPtr::get() still succeeds, allowing callbacks to access already-destroyed members.
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm
MediaPlayerPrivateMediaSourceAVFObjC::~MediaPlayerPrivateMediaSourceAVFObjC()
{
ALWAYS_LOG(LOGIDENTIFIER);
+ // Prevent re-entrant callbacks during member destruction. Without this,
+ // KVO notifications fired during m_mediaSourcePrivate's destruction can
+ // call back into this partially-destroyed object via WeakPtr-guarded
+ // callbacks (such as the error callback calling setNetworkState(),
+ // which accesses the already-destroyed m_logger).
+ weakPtrFactory().revokeAll();
+
cancelPendingSeek();
m_seekTimer.stop();
dispatchToRendererQueue([](auto& renderer) {
renderer.pause();
});
}
Patch Details
A single line is added at the top of the destructor: weakPtrFactory().revokeAll(). This invalidates all outstanding WeakPtrs pointing at this object so any KVO notifications fired later during destruction of members like m_mediaSourcePrivate cannot resolve their WeakPtr back to the now partially-destroyed instance.
Failure to invalidate weak references before destroying members reachable by re-entrant callbacks during teardown.
Background
WeakPtr in WebKit is a non-owning reference backed by a WeakPtrFactory stored on the target via the CanMakeWeakPtr CRTP base; WeakPtr::get() returns null only after the factory has been revoked or destroyed. In C++, members of a derived class are destroyed in reverse declaration order, then base destructors run; the CanMakeWeakPtr destructor that revokes the factory is a base destructor and therefore runs after all derived-class member destructors. KVO (Key-Value Observing) is Cocoa's observer pattern, and AVFoundation objects fire KVO notifications synchronously to registered observers. MediaPlayerPrivateMediaSourceAVFObjC owns m_mediaSourcePrivate (a MediaSourcePrivateAVFObjC) and a Logger reference m_logger. setNetworkState() is the standard MediaPlayer hook used to surface network state changes and in this implementation it logs through m_logger.
Analysis
The destructor relied on the default CanMakeWeakPtr teardown ordering: the WeakPtrFactory is only revoked when the base destructor runs, which is after all derived-class members have already been destroyed. During member destruction (specifically m_mediaSourcePrivate's destructor), AVFoundation can synchronously fire KVO notifications. Those notifications are wired through WeakPtr-guarded callbacks; because the factory has not yet been revoked, WeakPtr::get() still returns a non-null pointer.
Aaa Aaaaaaaaa Aaaa Aaaaaa Aaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaa Aaaa Aaaaa Aaaaaaa Aaaaaaaa Aaaaaaa Aaaaaaaaaaaa Aaaaa Aaaa Aaaaaaa Aaaa Aaaaaaaaa Aa Aaaaaaa Aaaaaaaaaaa Aaaaaa Aaaa Aa a Aaaaaaaaaaaaaaaaaaaaa Aa a Aaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaaaaaaaaa Aa a Aaaaa Aa Aaaaaaaaaaaaaaaaa Aaaaaa Aaaaaaaaaaaa Aaa Aaa Aaaaaaaa Aaaa Aaaaaa Aa Aaaaaaaa Aaa Aaaaaaaaaa Aa Aaa Aaaa Aaaaa Aa Aaa Aaaaaaaaaaa Aa Aaa Aaaaaaaaaa Aaaaaaaaaa Aaaaaaaa Aaaaa a Aaaa Aaaaaaaaa Aaa Aaaaa Aaa Aaaaaa Aaaaaaaa Aaaaaaaaa Aaaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaaa Aaaaaa Aaaaaa Aa Aaa Aaaaaaaaaa Aaaaaaa Aaaaaa Aaaaa Aaaaaaa Aaaaaaaaa Aaa Aaaaaaaaa Aaaa Aa Aaaaaaaa Aaaaaaaaa Aaaaaaaaa Aaa a Aaaa Aaaaaaa Aaaa Aaa Aaaaaa Aa Aaaaa Aaaaaaaaa Aa Aaaaaaaa Aaa Aaaaaaa Aaaaa Aaaaaa Aaaaaaaaaaa Aaa Aaaa Aaaaaaaaa a Aaa Aaaaaaaaaaaaaaaa Aaaa Aaaaaaa Aaa Aaaaa Aaa Aaaaa Aaaa Aaaaaaa Aaaa Aaaaaaaaaaaaaaaa Aaa Aaaaa Aaaaaa Aaaaaaaaaaa Aaa Aaaaaaaaaaaaa Aaaaaa Aaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaaaaa Aaaaaaaaaa Aaaa Aaaaa Aaaaaaaaaa Aa Aaaaaaaaaa Aa Aaa Aaaa Aaaaaaaaaaaaa Aaaaaaaaaaaa Aaa Aaaaaaaaa Aaaaa Aaaaaaaaaaa Aaaa a Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaaa Aaaa Aa Aaa Aaaaaaaaaa a Aaaaaa Aaaaaaaa Aa Aaa Aaaaaaa Aaa Aaa Aaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaa Aaaaaa Aaaaa Aaaa Aa a Aaaaaaaaaa Aaaa Aaaaaaaa
🔒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.
Subscribe to read more
Audit directions
a Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaa Aaaaa Aaaaaa Aaaaaaaaaaa Aaa Aaaaaaaaaaaaa Aaaa Aaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaa Aaaaaaaa Aaaaaaaaaa Aaaaa Aaaaa Aaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaa Aaaaaaaa Aaaa Aaaaaaaaaaaaaaaa Aaa Aaaa Aaaaaaaaaaa Aaaaaaa Aaaaaaaa Aaa Aaa Aa Aaaaaaaaaa Aa Aaaaaaaaaa Aa Aaa Aaaaaaaaaa Aaaa Aaa Aaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aa Aa a Aaaaaaaaaa Aaaaa Aa Aaaaaaaa Aaa Aaaaaa Aa a Aaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaa Aaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaa Aaaaa Aa Aaaaa Aaaaaa
a Aaaaaaaa Aaaaaaaaaaa Aaaaa Aaaa Aaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaa Aaaaaaaaaaaa Aaaaaaaaaa Aaaaaa Aaaaaa Aa Aaaaaaaaaaaaaaaa Aaaaaaaaaa Aaaa Aaaaaaaaaa Aaa Aaaaaaaaaaaaaa Aaaa Aaaaa Aaaaa Aaa Aaaaaaaa Aaaaa Aa Aaaaa Aaaaa Aaaaaaaaaa Aaaaaa Aaaaaa Aaaaaaaaaaa Aaaaa Aa Aaaaaaaaaaaaaa Aaaaaa Aaaaaaa Aaa Aaaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaa Aaa Aaaaa Aaaaaaaaaaaaaa Aaaaa Aaaaaa Aaaa Aaaaa Aaaaaaaaaa Aa Aaaaa Aaaaaaaaaaaaaa Aaaaaaa
a Aaaaa Aaaaaaa Aaaaaaaaaaaaa Aaa Aaaa Aaa Aaa Aaa Aaaa Aaaaaa Aa Aaa Aaaaaaaa Aaaaaaaaaa Aaa Aa Aaa Aaaaaaaaaaa Aaa Aaaaaaaa Aaaaaaaaaaaa Aaaaa Aa Aaaaaaa Aaaaaaa Aaaaaaa Aaaaa a Aaa Aaa Aaaaaaaaaaaaa Aaaaaaa Aaaaaaaaaaa Aaaaaaaaa Aa Aaaaaaa a Aaaaa Aaaaaaaaaaaaa Aaaaa
a Aaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaaaa Aaaaaaaaaaa Aaaaaa Aaaaaa Aaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaa Aaa Aaaaaaaaaaaaaaa Aaaaaaaaa Aaaaa Aaa Aaaa Aaaaaaaaa Aaaaa Aaaaaaaaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaaaaaaaaaaaaa Aaaa Aaaaaaaa Aa Aaaaaa Aaaa Aaaaaaaaaa Aaa Aaaaaaa Aaaaaa Aaaaa Aaaaaa Aaa Aaaaaa
🔒Multiple reusable audit patterns identified for finding sibling bugs across WebKit's Cocoa-observer-owning classes, with concrete starting points for variant discovery.
Subscribe to read more