Medium chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in Skia
DescriptionUninitialized Use in Skia
ComponentSkia
Bug ClassUninitialized Memory
Tracker501861921
Fix commitd10ea850c21d (skia) +5/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Changed Functions

FunctionChangeNotes
switch
src/gpu/ganesh/ops/OpsTask.cpp
modified
if
src/gpu/ganesh/ops/OpsTask.cpp
modified

Files Changed

  • src/gpu/ganesh/ops/OpsTask.cpp
From d10ea850c21d01d0a715d03cb3b5d6dd676a953a Mon Sep 17 00:00:00 2001
From: Greg Daniel <egdaniel@google.com>
Date: Fri, 01 May 2026 16:11:53 +0000
Subject: [PATCH] Defer marking stencil as cleared until after render pass creation succeeds

Bug: b/501861921
Change-Id: I822d7560c3f51c0e0a49dfb1a7d3a526e5f2c0e6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1223896
Reviewed-by: Thomas Smith <thomsmit@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
---

diff --git a/src/gpu/ganesh/ops/OpsTask.cpp b/src/gpu/ganesh/ops/OpsTask.cpp
index 1bd578b..d7e49fe 100644
--- a/src/gpu/ganesh/ops/OpsTask.cpp
+++ b/src/gpu/ganesh/ops/OpsTask.cpp
@@ -585,6 +585,7 @@
         stencil = renderTarget->getStencilAttachment(fUsesMSAASurface);
     }
 
+    bool markStencilCleared = false;
     GrLoadOp stencilLoadOp;
     switch (fInitialStencilContent) {
         case StencilContent::kDontCare:
@@ -602,7 +603,7 @@
             }
             if (!stencil->hasPerformedInitialClear()) {
                 stencilLoadOp = GrLoadOp::kClear;
-                stencil->markHasPerformedInitialClear();
+                markStencilCleared = true;
                 break;
             }
             // SurfaceDrawContexts are required to leave the user stencil bits in a cleared state
@@ -643,6 +644,9 @@
     if (!renderPass) {
         return false;
     }
+    if (markStencilCleared) {
+        stencil->markHasPerformedInitialClear();
+    }
     flushState->setOpsRenderPass(renderPass);
     renderPass->begin();
 
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential cross-origin info leak via uninitialized Skia stencil buffer

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 Chrome Security team.

Overview: A logic flaw in Skia’s Ganesh backend prematurely marks shared stencil attachments as cleared before render pass creation. If creation fails due to memory pressure, the attachment is cached with uninitialized VRAM, allowing an attacker to reuse it and leak cross-origin GPU memory.

Affected files:

  • third_party/skia/src/gpu/ganesh/ops/OpsTask.cpp
  • third_party/skia/src/gpu/ganesh/GrAttachment.h
  • third_party/skia/src/gpu/ganesh/GrResourceProvider.cpp
  • gpu/command_buffer/service/raster_decoder.cc

Estimated timestamp from git blame: 2019-10-01

Vulnerability Details

In Skia’s Ganesh backend (third_party/skia/src/gpu/ganesh/ops/OpsTask.cpp), stencil GrAttachment objects are shared and cached using a unique key based on dimensions and format. Initial attachment management and tracking mechanisms correctly establish these shared resources.

The vulnerability occurs during the execution phase. In OpsTask::onExecute, the code evaluates if the stencil needs an initial clear. If so, it prematurely latches the stencil’s clear state by calling stencil->markHasPerformedInitialClear() (around line 605) before attempting to create the actual render pass (create_render_pass() at line 630).

If the backend fails to allocate the necessary render pass structures (e.g., due to an induced Out-of-Memory condition) and returns nullptr, the function aborts and returns false. Consequently, the GrAttachment remains in the shared GrResourceCache permanently flagged as cleared, even though the VRAM remains uninitialized.

When a subsequent render task requests a stencil buffer with the same properties, it retrieves this corrupted attachment. Because hasPerformedInitialClear() == true, Skia bypasses GrLoadOp::kClear and falls back to GrLoadOp::kLoad. This causes uninitialized recycled VRAM to be loaded into the stencil buffer. On Vulkan backends, RasterDecoderImpl::MakeCurrent() bypasses standard OOM context-loss checks, allowing the GPU context to survive the memory pressure and the attacker to reliably read the leaked memory.

Potential Attacker Steps

Note: These are suggested steps for exploitation; our tooling agent does not yet have the ability to run code, so a working proof-of-concept has not been verified executionally.

  1. The attacker allocates numerous large textures to intentionally consume almost all available VRAM.
  2. The attacker triggers a complex canvas drawing operation (e.g., using intricate clip paths) that requires a dynamic MSAA stencil attachment.
  3. The stencil attachment is allocated, but the subsequent render pass creation fails due to the induced memory pressure. The stencil is returned to the cache marked as cleared but uninitialized.
  4. The attacker clears their memory pressure and issues a subsequent draw to a new canvas with identical dimensions, causing Skia to reuse the uninitialized stencil buffer.
  5. The attacker reads the resulting canvas pixels via getImageData() to extract cross-origin VRAM residue (which may contain recycled stencil or depth data from other origins).

Suggested Fix

Defer the call to stencil->markHasPerformedInitialClear() in OpsTask::onExecute until after create_render_pass() has successfully executed and returned a valid GrOpsRenderPass object. Alternatively, clear this flag if the OpsTask execution is aborted.

Evaluated with Chrome root at commit: 096fc8fdbfacf2546485756d03f160a3d04fcc9b


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.

View on issue tracker