CVE-2026-11064
Overview
Files Changed
gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc
Patch
From a82e3781e411a169709c5e7a0bb1778e5e2abea3 Mon Sep 17 00:00:00 2001 From: Stephen White <[email protected]> Date: Mon, 27 Apr 2026 12:32:19 -0700 Subject: [PATCH] Fix potential data leak in DawnEGLImageRepresentation. Bug: 499075743 Change-Id: I7d60e18a48e3a419a56423f931120f8c4b78621f Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7792603 Commit-Queue: Stephen White <[email protected]> Reviewed-by: Vasiliy Telezhnikov <[email protected]> Cr-Commit-Position: refs/heads/main@{#1621234} --- diff --git a/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc b/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc index 5c74a47..7b52a0ea2 100644 --- a/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc +++ b/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc @@ -64,7 +64,9 @@ wgpu::Texture DawnEGLImageRepresentation::BeginAccess( wgpu::TextureUsage usage, wgpu::TextureUsage internal_usage) { - gl_representation_->BeginAccess(ToSharedImageAccessGLMode(usage)); + if (!gl_representation_->BeginAccess(ToSharedImageAccessGLMode(usage))) { + return nullptr; + } wgpu::TextureDescriptor texture_descriptor; texture_descriptor.format = ToDawnFormat(format()); texture_descriptor.viewFormatCount = view_formats_.size();
Original Bug Report
Potential GPU data leak via unchecked DawnEGLImageRepresentation::BeginAccess
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the security team.
Overview: In Chrome’s GPU service, DawnEGLImageRepresentation::BeginAccess ignores the return value of its underlying GL representation access call. This allows a compromised renderer to bypass GPU synchronization and clear-state tracking by mapping the same SharedImage mailbox to multiple WebGPU textures concurrently. As a result, an attacker can potentially trigger a GPU-side data race to read uninitialized memory or cross-origin texture residue on older Android devices.
Affected files:
gpu/command_buffer/service/shared_image/dawn_egl_image_representation.ccgpu/command_buffer/service/webgpu_decoder_impl.ccgpu/command_buffer/service/shared_image/shared_image_representation.h
Estimated timestamp from git blame: 2024-06-03
Background
On Android devices lacking Vulkan support, Chrome’s WebGPU implementation falls back to OpenGLES. In this path, DawnEGLImageRepresentation is used to wrap EGLImage-backed SharedImages so they can be accessed by Dawn. Proper synchronization between Dawn and other GL contexts relies on acquiring exclusive read/write access to the SharedImage backing and emitting GL fences.
The Vulnerability
In gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc:67, the boolean return value of gl_representation_->BeginAccess(...) is ignored:
64: wgpu::Texture DawnEGLImageRepresentation::BeginAccess(...) {
65: gl_representation_->BeginAccess(ToSharedImageAccessGLMode(usage)); // Return value ignored
66: // ... proceeds to successfully wrap the EGLImage and return a wgpu::Texture ...
67: }
If the SharedImage is already locked by another writer, gl_representation_->BeginAccess() safely returns false, and its internal state mode_ remains kNone. However, because DawnEGLImageRepresentation ignores this failure, it proceeds to hand Dawn a valid wgpu::Texture handle for a texture it does not exclusively own.
Potential Exploit Steps
Note: These are suggested/potential steps derived from code analysis; our tooling agent does not run code to produce a live proof-of-concept.
An attacker in a compromised renderer could trigger a GPU data race using the following sequence:
- Create SharedImage: The attacker creates an uninitialized SharedImage via GPU IPC.
- Associate ID 1: The attacker sends an
AssociateMailboxImmediatecommand to the WebGPU decoder, associating the mailbox with a WebGPU textureid=1and requestingWEBGPU_WRITEusage. This successfully acquires the write lock on theEGLImageBacking. - Associate ID 2: The attacker associates the same mailbox with a second WebGPU texture
id=2.WebGPUDecoderImplpermits multiple IDs for the same mailbox. Becauseid=1holds the lock,BeginWrite()fails, but the failure is ignored.id=2successfully wraps the texture, but its internal accessmode_remainskNone. - Generate Stale Fence: The attacker dissociates
id=1. TheEndAccesscall drops the write lock and generates a newwrite_fence_(e.g.,GLFenceEGL), representing the GPU state before any commands forid=2are submitted. - Submit Unfenced Work: The attacker uses
id=2to submit a lazy-clear or compute operation in Dawn. These GL commands execute asynchronously on the GPU. - Bypass New Fence Generation: The attacker dissociates
id=2. Dawn marks the backing as fully initialized (SetCleared()). However, whengl_representation_->EndAccess()is called, it early-returns becausemode_iskNone. Crucially, no newwrite_fence_is generated to synchronize the Dawn commands from step 5. - Race Condition and Data Leak: The attacker immediately reads the same SharedImage from a WebGL context. WebGL sees the texture is marked as cleared and skips its own security lazy-clear. It waits on the backing’s
write_fence_, but this is the stale fence from step 4, which is already signaled. WebGL reads the memory immediately, racing with the asynchronous clear from step 5.
This race allows the attacker to read uninitialized GPU memory or cross-origin texture residue.
Suggested Fix
Check the return value of gl_representation_->BeginAccess(...) inside DawnEGLImageRepresentation::BeginAccess. If it returns false, fail gracefully by returning a null wgpu::Texture or an error texture, preventing Dawn from accessing a backing it failed to lock:
wgpu::Texture DawnEGLImageRepresentation::BeginAccess(
wgpu::TextureUsage usage,
wgpu::TextureUsage internal_usage) {
if (!gl_representation_->BeginAccess(ToSharedImageAccessGLMode(usage))) {
return nullptr;
}
// ...
}
Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33
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. And please feel free to reach out to me directly if you have concerns or feedback on the project.