← All issues

[6] GPU process dangling reference via MarkSurfacesVolatile during prepareBufferForDisplay

Severity: High | Component: GPU Process RemoteRenderingBackend | 325e4cb

Rated High because the observable effect is a dangling reference to a destroyed graphics context in the GPU process — which runs outside the WebContent sandbox — triggered by a reproducible IPC message sequence from a compromised WebProcess, with the attack scenario confirmed by the regression test.

The WebProcess can send MarkSurfacesVolatile while prepareBufferForDisplay is still active on the GPU Process. This calls releaseGraphicsContext() on each image buffer, destroying the graphics context that prepareBufferForDisplay is actively using through m_context.

Source/WebKit/GPUProcess/graphics/RemoteImageBufferSet.h

+ bool isPreparingForDisplay() const { return m_context.get(); }

Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp

RefPtr<RemoteImageBufferSet> remoteImageBufferSet = m_remoteImageBufferSets.get(identifier.first);
 
MESSAGE_CHECK(remoteImageBufferSet, "BufferSet is being marked volatile before being created");
+ MESSAGE_CHECK(!remoteImageBufferSet->isPreparingForDisplay(), "BufferSet is being marked volatile while preparing for display");
 
OptionSet<BufferInSetType> volatileBuffers;
if (!remoteImageBufferSet->makeBuffersVolatile(identifier.second, volatileBuffers, forcePurge))

LayoutTests/ipc/mark-surfaces-volatile-during-prepare-for-display.html

+ remoteRenderingBackend.PrepareImageBufferSetsForDisplaySync({ ... });
+
+ remoteRenderingBackend.MarkSurfacesVolatile({
+ requestIdentifier: randomIPCID(),
+ renderingResourceIdentifiers: [[imageBufferSetIdentifier, 1]],
+ forcePurge: false,
+ });
+
+ remoteGraphicsContext.SetShouldAntialias({
+ shouldAntialias: true
+ });

The fix adds a MESSAGE_CHECK guard in RemoteRenderingBackend::markSurfacesVolatile that rejects the IPC message when the target RemoteImageBufferSet is currently preparing for display. The check uses a new isPreparingForDisplay() accessor which returns whether m_context is non-null. MESSAGE_CHECK terminates the offending WebContent process on failure.

Missing IPC message ordering validation allows a resource lifetime to be terminated while an operation consuming that resource is still in flight.

WebKit's GPU process architecture separates rendering operations into a dedicated GPU process. The WebProcess communicates with the GPU process over IPC stream connections. RemoteImageBufferSet manages a set of image buffers (front/back) used for compositing. prepareBufferForDisplay initializes the front buffer's contents using a graphics context stored in m_context. makeBuffersVolatile marks buffers as reclaimable by the OS and calls releaseGraphicsContext() to destroy the associated context. MESSAGE_CHECK is WebKit's IPC validation macro — when a check fails, the GPU process terminates the offending WebContent process, enforcing IPC contracts between processes.

Before the fix, RemoteRenderingBackend::markSurfacesVolatile did not check whether the target RemoteImageBufferSet was actively being used by prepareBufferForDisplay. When the WebProcess sends MarkSurfacesVolatile while prepareBufferForDisplay is still active, makeBuffersVolatile() calls releaseGraphicsContext(), destroying the graphics context held in m_context (as the commit message confirms: "MarkSurfacesVolatile calls makeBuffersVolatile, which calls releaseGraphicsContext() on each image buffer — destroying the graphics context that prepareBufferForDisplay is actively using through m_context"). The prepareBufferForDisplay code path continues to use m_context after this destruction, producing a dangling reference.

🔒

Explores the cross-process exploitation potential and sandbox implications of this GPU process vulnerability

Subscribe to read more

🔒

Multiple audit patterns identified for IPC resource lifecycle vulnerabilities across GPU process handlers

Subscribe to read more