← All issues

[24] ReadableStreamDefaultReader GC-thread UAF on m_stream

Severity: Medium | Component: WebCore Streams | ad57b51

Rated Medium because the diff fixes the same cross-thread UAF class as #23 in a different DOM object: GC-thread visitors read m_stream while the main thread can null it via releaseLock/genericRelease.

Sister fix to the XMLHttpRequest commit. m_stream becomes WTF_GUARDED_BY_LOCK(m_streamLock); every access serialises through the lock.

Source/WebCore/Modules/streams/ReadableStreamDefaultReader.h

- RefPtr<ReadableStream> m_stream;
+ mutable Lock m_streamLock;
+ RefPtr<ReadableStream> m_stream WTF_GUARDED_BY_LOCK(m_streamLock);
template<typename Visitor>
void ReadableStreamDefaultReader::visitAdditionalChildrenInGCThread(Visitor& visitor)
{
+ Locker locker { m_streamLock };
if (m_stream)
SUPPRESS_UNCOUNTED_ARG m_stream->visitAdditionalChildrenInGCThread(visitor);
}

Unsynchronized access from a GC visitor thread to a main-thread-mutable reference-counted member, allowing the visitor to dereference a pointer concurrently being released.

The commit message explicitly notes "we cannot easily ref the stream on the GC thread" — atomic ref does not solve the race because the object could be destroying mid-ref.

🔒

The cross-thread lifetime and synchronization implications between GC-thread visitors and main-thread mutators are analyzed in depth, with a feasibility assessment for triggering the race from web content.

Subscribe to read more

🔒

Multiple reusable audit patterns identified for related Streams classes and other WebCore opaque-root participants, with concrete starting points for variant discovery.

Subscribe to read more