CVE-2026-8578
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifgpu/command_buffer/service/shared_image/d3d_image_backing.cc |
modified |
Files Changed
gpu/command_buffer/service/shared_image/d3d_image_backing.cc
Patch
From a93eb13c129e125e5ba347a136cb2daa1c614049 Mon Sep 17 00:00:00 2001 From: Kalvin Lee <[email protected]> Date: Wed, 01 Apr 2026 07:36:33 -0700 Subject: [PATCH] Terracotta-Phase-1: Gate `BeginAccessDawnBuffer()` This patch is speculative. Please see the linked bug for details. Bug: 496395450 Change-Id: I883e9b1b01a97261f56f5aee00bd3e24a7f1c5e0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7707479 Auto-Submit: Kalvin Lee <[email protected]> Commit-Queue: Vasiliy Telezhnikov <[email protected]> Reviewed-by: Vasiliy Telezhnikov <[email protected]> Reviewed-by: Colin Blundell <[email protected]> Cr-Commit-Position: refs/heads/main@{#1608520} --- diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc index 1fd7df893..b1392f6 100644 --- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc @@ -1593,6 +1593,11 @@ wgpu::BackendType backend_type, wgpu::BufferUsage usage) { AutoLock auto_lock(this); + + if (!ValidateBeginAccess(true)) { + return nullptr; + } + Microsoft::WRL::ComPtr<ID3D12Device> dawn_d3d12_device; if (backend_type == wgpu::BackendType::D3D12) { dawn_d3d12_device = dawn::native::d3d12::GetD3D12Device(device.Get());
Original Bug Report
Potential cross-origin GPU memory disclosure via missing ValidateBeginAccess in D3DImageBacking
Project Fortify, an experimental security project, has identified the following potential security issue.
Overview: A synchronization flaw exists in D3DImageBacking::BeginAccessDawnBuffer where it fails to call ValidateBeginAccess. This allows a compromised renderer to establish concurrent, unsynchronized write access to a single D3D12 resource from both WebNN and WebGPU. This concurrent access can be used to exploit a Time-of-Check Time-of-Use (TOCTOU) vulnerability in Dawn’s indirect draw validation, leading to out-of-bounds reads and cross-origin GPU memory disclosure.
Affected files:
gpu/command_buffer/service/shared_image/d3d_image_backing.ccgpu/command_buffer/service/shared_image/d3d_image_backing_factory.ccservices/webnn/webnn_context_impl.ccgpu/command_buffer/service/webgpu_decoder_impl.cc
Estimated timestamp from git blame: 2024-09-12
Summary
A synchronization vulnerability exists in D3DImageBacking where the BeginAccessDawnBuffer method (located in gpu/command_buffer/service/shared_image/d3d_image_backing.cc) fails to call ValidateBeginAccess. This omission allows a compromised renderer to bypass internal state tracking (in_write_access_) and obtain concurrent write access to an underlying D3D12 resource while it is already locked for exclusive access by WebNN.
Vulnerability Details
In the D3DImageBacking implementation, all other access entry points—BeginAccessDawn, BeginAccessD3D11, and BeginAccessWebNN—call ValidateBeginAccess() to ensure that the backing is not already locked for exclusive (write) access.
However, BeginAccessDawnBuffer (lines 1591-1643) lacks this critical check. Furthermore, Dawn has its own internal mExclusiveAccess tracking, but this check is bypassed because WebNN access only updates Chrome’s SharedImage state (in_write_access_ via BeginAccessCommon) and does not interact with Dawn’s internal resource management.
Attack Scenario / Exploitation
This concurrency enables a Time-of-Check to Time-of-Use (TOCTOU) vulnerability in Dawn’s indirect draw validation. Specifically, Dawn’s IndirectDrawValidationEncoder reads parameters (like indexCount and firstIndex) from an indirect buffer, validates them against bounds, and then re-reads the buffer to copy the values to a safe scratch buffer for ExecuteIndirect.
An attacker can use WebNN to concurrently overwrite the indirect buffer after Dawn’s validation but before the copy. This allows unvalidated out-of-bounds indexCount or firstIndex values to be consumed by ExecuteIndirect. In D3D12, an out-of-bounds index buffer read will fetch arbitrary memory from the D3D12 heap. By crafting a vertex shader to reflect these fetched values, an attacker can leak cross-origin GPU memory, such as textures belonging to other origins or browser UI elements.
Suggested Steps to Reproduce
(Note: These are potential steps, as Fortify LLM agent doesn’t yet have the ability to run code.)
- Preparation: A compromised renderer creates a SharedImage with both
SHARED_IMAGE_USAGE_WEBGPU_SHARED_BUFFERandSHARED_IMAGE_USAGE_WEBNN_SHARED_TENSORusages. This combination is explicitly permitted inD3DImageBackingFactory::IsSupported. - WebNN Access: The renderer sends an
ImportTensorWebNN Mojo command to acquire WebNN access to the tensor. The GPU process executesBeginAccessWebNN, which callsBeginAccessCommon(true), settingin_write_access_ = trueand clearing any existingwrite_fences_andread_fences_. - Bypassed WebGPU Access: Without finishing the WebNN access, the renderer sends an
AssociateMailboxForBufferImmediatecommand for WebGPU using the same SharedImage mailbox. The GPU process executesBeginAccessDawnBuffer. - Race Condition: Because
BeginAccessDawnBuffermissesValidateBeginAccess(true), it does not checkin_write_access_. It reads the empty fences (cleared by WebNN) and initiates Dawn access with zero fence waits. Now, both DirectML (via WebNN) and Dawn (via WebGPU) are submitting commands to the sameID3D12Resourceconcurrently without synchronization. - Exploitation: The attacker dispatches a WebGPU indirect draw command that sources parameters from this SharedImage buffer. Concurrently, the attacker dispatches a WebNN workload that rapidly writes out-of-bounds (OOB) values (e.g., extremely large
indexCount) to the buffer. If the WebNN overwrite occurs precisely between Dawn’s validation read and its copy read insRenderValidationShaderSource, Dawn will copy the unvalidated OOB values to its internal scratch buffer. - Information Leak: The hardware executes
ExecuteIndirectusing the OOB parameters from the scratch buffer, fetching out-of-bounds indices from the D3D12 heap. The attacker’s vertex shader reflects these leaked values onto a render target, which is read back to the renderer, disclosing cross-origin memory. - State Corruption: Upon
EndAccess, the overlapping access causesnum_readers_to underflow (decrementing from 0 to -1), permanently corrupting the synchronization state for thatSharedImage.
Suggested Fix
Add the missing validation check to D3DImageBacking::BeginAccessDawnBuffer:
wgpu::Buffer D3DImageBacking::BeginAccessDawnBuffer(
const wgpu::Device& device,
wgpu::BackendType backend_type,
wgpu::BufferUsage usage) {
AutoLock auto_lock(this);
// Add validation check here
if (!ValidateBeginAccess(true)) {
return nullptr;
}
// ... rest of the function
}
Note: BeginAccessDawnBuffer implicitly grants write access as it creates a wgpu::Buffer and Dawn currently treats all mapped buffers as potentially writable from the perspective of SharedImage synchronization.
Evaluated with Chrome root at commit: 0eb4855bda702feaaa8b899336664f97e3df88b8
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. Please feel free to reach out to me if you have concerns or feedback.