Medium chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in GPU
DescriptionUninitialized Use in GPU
ComponentGPU
Bug ClassUninitialized Memory
Tracker496441232
Fix commita8b79551f4bc (chromium/src) +6/-3
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-05

Files Changed

  • gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
From a8b79551f4bc5001d859115cede7eadcdd481257 Mon Sep 17 00:00:00 2001
From: Yuki Shiino <yukishiino@chromium.org>
Date: Mon, 30 Mar 2026 08:04:44 -0700
Subject: [PATCH] [gpu] Mark SetCleared iff succeeded in PassthroughResources::SharedImageData::EnsureClear

Bug: 496441232
Change-Id: I605e9f15400bd174979107f0729a359127e8328c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7706449
Reviewed-by: Saifuddin Hitawala <hitawala@chromium.org>
Commit-Queue: Saifuddin Hitawala <hitawala@chromium.org>
Auto-Submit: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1607104}
---

diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index 9514ae65..0947f6c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -473,13 +473,16 @@
     api->glDisableFn(GL_SCISSOR_TEST);
     api->glClearFn(GL_COLOR_BUFFER_BIT);
 
+    if (api->glCheckFramebufferStatusEXTFn(GL_FRAMEBUFFER) ==
+        GL_FRAMEBUFFER_COMPLETE) {
+      // Mark the shared image as cleared.
+      representation_->SetCleared();
+    }
+
     // Delete the generated framebuffer.
     api->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                      texture->target(), 0, 0);
     api->glDeleteFramebuffersEXTFn(1, &fbo);
-
-    // Mark the shared image as cleared.
-    representation_->SetCleared();
   }
 }
 
Loading diff…

Original Bug Report

reported by vm...@google.com

GPU memory leak via unchecked GL errors in SharedImageData::EnsureClear

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A compromised renderer can potentially read uninitialized GPU memory by creating a SharedImage with prefers_external_sampler=true. The GPU process’s EnsureClear function fails to clear GL_TEXTURE_EXTERNAL_OES textures on certain platforms due to silent GL attachment failures, but still marks them as cleared. The renderer can then sample the uncleared memory, leading to cross-origin or cross-process information disclosure.

Affected files:

  • gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
  • gpu/ipc/service/shared_image_stub.cc
  • gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
  • gpu/command_buffer/service/shared_image/ozone_image_gl_textures_holder.cc

Estimated timestamp from git blame: 2022-07-21

Vulnerability Details

There is a potential high-severity information disclosure vulnerability in the GPU process. Specifically, the function PassthroughResources::SharedImageData::EnsureClear() in gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc fails to handle OpenGL errors when attempting to clear uninitialized SharedImage backing memory.

When a SharedImage is created with the prefers_external_sampler flag set to true, its underlying OpenGL texture is initialized with the GL_TEXTURE_EXTERNAL_OES target (see OzoneImageGLTexturesHolder). Later, to prevent uninitialized memory from being exposed to the renderer, the command buffer invokes EnsureClear().

Inside EnsureClear():

  1. A temporary Framebuffer Object (FBO) is generated.
  2. The code attempts to attach the texture to the FBO: api->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture->target(), texture->service_id(), 0);
  3. It issues a glClear command.
  4. It unconditionally executes representation_->SetCleared(), marking the memory as safe for renderer consumption.

However, on certain platforms (such as Linux and ChromeOS using ANGLE-on-Vulkan), attaching a GL_TEXTURE_EXTERNAL_OES texture to an FBO is unsupported unless the GL_EXT_YUV_target extension is fully supported and enabled. In environments where it is not, the glFramebufferTexture2DEXTFn call silently fails and raises a GL_INVALID_OPERATION error. The FBO remains incomplete, causing the subsequent glClear to act as a silent no-op. Because EnsureClear() performs no error checking (e.g., glCheckFramebufferStatusEXT or glGetError), the uninitialized buffer is incorrectly marked as cleared.

Suggested Steps to Trigger

Note: These are potential steps suggested by our setup, which does not currently have the ability to run code to verify a working proof of concept.

  1. Compromise Renderer: An attacker gains arbitrary code execution within the sandboxed renderer process.
  2. Send IPC Request: The attacker crafts a CreateSharedImage IPC request. They specify a multi-planar format (e.g., NV12) and manually set the prefers_external_sampler flag to true.
  3. Bypass OS Constraints: On non-Windows/Apple platforms (e.g., Linux/Ozone), SharedImageStub::CreateSharedImage does not block the prefers_external_sampler flag, allowing the request to proceed.
  4. Allocate Uninitialized Memory: The OzoneImageBackingFactory allocates a fresh native pixmap (e.g., a dma-buf) containing uninitialized memory that may hold stale data from other processes or origins.
  5. Trigger EnsureClear: The renderer sends a CreateAndTexStorage2DSharedImageINTERNAL command. The GPU process maps the mailbox and triggers PassthroughResources::SharedImageData::EnsureClear().
  6. Silent Failure: The FBO attachment fails silently due to the GL_TEXTURE_EXTERNAL_OES target, the clear acts as a no-op, and the uninitialized image is marked as cleared.
  7. Exfiltrate Data: The compromised renderer binds the texture, uses a GLSL shader with samplerExternalOES to sample the uninitialized memory into a readable renderbuffer, and extracts the sensitive pixels using glReadPixels.

Suggested Fix

The EnsureClear() function must verify that the clear operation actually succeeded before marking the representation as cleared.

  1. Introduce a check for framebuffer completeness (api->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) after attaching the texture, or explicitly check glGetError().
  2. If the FBO is incomplete, EnsureClear must not call representation_->SetCleared().
  3. Instead, the implementation should either fallback to an alternative clear mechanism (e.g., clearing the native pixmap via CPU mapping or Skia before it is bound to GL), or explicitly fail the command and terminate the context to prevent uninitialized memory access.

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.

View on issue tracker