[23] XMLHttpRequest GC-thread UAF on m_responseDocument
Severity: Medium | Component: WebCore XMLHttpRequest bindings | a814080
Rated Medium because the diff fixes a cross-thread race where the JSC GC marking thread dereferenced m_responseDocument without synchronization while the main thread could null it via responseXML()/clearResponseBuffers().
JSXMLHttpRequest::visitAdditionalChildrenInGCThread read wrapped().optionalResponseXML() and optionalUpload() with no synchronization while the main thread could perform m_responseDocument = nullptr; — a RefPtr reassignment that drops the previous ref.
Source/WebCore/xml/XMLHttpRequest.h
+ Lock m_gcLock;
+ const std::unique_ptr<XMLHttpRequestUpload> m_upload WTF_GUARDED_BY_LOCK(m_gcLock);
- RefPtr<Document> m_responseDocument;
+ RefPtr<Document> m_responseDocument WTF_GUARDED_BY_LOCK(m_gcLock);
+template<typename Visitor>
+void XMLHttpRequest::visitAdditionalChildrenInGCThread(Visitor& visitor)
+{
+ Locker locker { m_gcLock };
+ if (m_upload)
+ addWebCoreOpaqueRoot(visitor, *m_upload);
+ if (auto* document = m_responseDocument.get())
+ addWebCoreOpaqueRoot(visitor, *document);
+}
Unsynchronized GC-thread read of refcounted DOM pointers that the main thread can null or reassign without barriers, producing a data-race UAF on a JS opaque root.
Every main-thread reader/writer of those two members is wrapped in Locker { m_gcLock }. The header drops the now-unused inline getters optionalResponseXML() and optionalUpload().
Aaa Aa Aaaaaa Aaa Aaaa a Aaaaaaaa Aaaaaaaaaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aa a Aaaaaaaaaa Aaaaa Aaaa Aaa Aaa Aaaa Aaaaaaa Aa Aaa Aaaa Aaaaaa a Aaa Aa Aaa Aaaaaa Aaaaaaa Aaaaaaaaa Aaaaaa Aaa Aaaaaaa Aaaaaaaa Aaaaaa Aaaaa Aaa Aaa Aaaaaaaaa Aaaaaaa Aaaa Aaa Aaaaaa Aaaaaaaaa Aaaaaaa Aa Aaaaaaaaaaaa Aaaaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaa Aaaaaa Aaaaaa Aaaaaa Aaa Aaaaaaaaaa Aaaaaaaa Aa Aaaaaaaa Aaa Aaaaaaaaaaaaa Aaaaaaaaa Aaaaaaa Aa Aaaaaaa Aaa Aaaaaaaaaaa Aaa Aaaaaaaaa
🔒A multi-threading hazard between JSC's marking phase and main-thread DOM mutation — the analysis walks through how the visitor's view of an owned DOM pointer can race a re-entrant nullification.
Subscribe to read more
Audit directions
a Aaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaa Aaaaa Aaaaaa Aaaa Aaaaaaaaaaa Aa Aaaaaaaaaa Aaaaaaaaaaaaa Aa Aaaaaaaaaaaaaaaa Aaaaaaaa Aaaaa Aaaa Aaaaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaa
a Aaaaaaaa Aaaaaaaaaaaaaaaaaaa a Aaaaaa Aaaaaaaaaa Aaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaa Aa Aaaaaaa Aaaaaaaaaaaa Aaa Aa Aaaaaaaa
a Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaaaaaaaaaa Aaaaaa Aaaa Aaa Aaaaa Aaa Aaaaaaaaa Aa Aaa Aaaa Aaaa Aaaa Aaaaaaaaaa Aaa Aaaaaaa
a Aaaaaa Aaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaa Aaaaaa Aaaaaa Aaaa Aaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaa
🔒Four reusable audit patterns covering GC-visitor thread-safety across WebKit JS bindings, with concrete grep starting points for variant discovery.
Subscribe to read more