Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Skia
DescriptionInappropriate implementation in Skia
ComponentSkia
Bug ClassLogic Error
Tracker512995705
Fix commit544395a5d9da (skia) +2/-2
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-27

Changed Functions

FunctionChangeNotes
if
src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp
modified

Files Changed

  • src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp
From 544395a5d9da52fdaa59ad9c98f32f731b64b6b2 Mon Sep 17 00:00:00 2001
From: Michael Ludwig <michaelludwig@google.com>
Date: Thu, 21 May 2026 11:57:33 -0400
Subject: [PATCH] [ganesh] Use & when testing for input attachment self-dep

Other than these two sites, kForInputAttachment and
kForNonCoherentAdvBlend are not treated as mutually exclusive.

When using only == kForInputAttachment, the layout and bindings wouldn't
apply correctly for a renderpass that was using both forms of self
dependencies.

Bug: 512995705
Fixed: 512995705
Change-Id: I40aff60a9209be77e6743d7a2f73dac46985507a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1242516
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Nicolette Prevost <nicolettep@google.com>
---

diff --git a/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp b/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp
index 5f9fddd..3ff4a7c 100644
--- a/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp
+++ b/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp
@@ -89,7 +89,7 @@
     bool withStencil = fCurrentRenderPass->hasStencilAttachment();
     bool withResolve = fCurrentRenderPass->hasResolveAttachment();
 
-    if (fSelfDependencyFlags == SelfDependencyFlags::kForInputAttachment) {
+    if (fSelfDependencyFlags & SelfDependencyFlags::kForInputAttachment) {
         // We need to use the GENERAL layout in this case since we'll be using texture barriers
         // with an input attachment.
         VkAccessFlags dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
@@ -738,7 +738,7 @@
                                                    this->currentCommandBuffer())) {
         return false;
     }
-    if (fSelfDependencyFlags == SelfDependencyFlags::kForInputAttachment) {
+    if (fSelfDependencyFlags & SelfDependencyFlags::kForInputAttachment) {
         // We bind the color attachment as an input attachment
         auto ds = fFramebuffer->colorAttachment()->inputDescSetForBlending(fGpu);
         if (!ds) {
Loading diff…

Original Bug Report

reported by vm...@google.com

Ganesh-Vulkan: Bitfield logic error in GrVkOpsRenderPass leads to GPU info leak

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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: Skia’s Ganesh-Vulkan backend incorrectly uses equality checks for bitfield flags in GrVkOpsRenderPass, causing missing descriptor bindings when multiple flags are present. This flaw potentially allows uninitialized GPU memory reads to be observed by web content via Canvas2D.

Affected files:

  • third_party/skia/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp

Estimated timestamp from git blame: 2020-10-02

Technical Details

In Skia’s Ganesh-Vulkan implementation, the GrVkRenderPass::SelfDependencyFlags enum is used as a bitfield to track requirements for subpass dependencies, such as input attachments and advanced blending. While these flags are correctly accumulated using bitwise OR throughout the backend, the GrVkOpsRenderPass class incorrectly uses equality (==) to check these flags at two critical execution sites where it should use bitwise AND (&).

1. Mismatched Image Layout Transition

In GrVkOpsRenderPass::setAttachmentLayouts (located at third_party/skia/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp:92):

if (fSelfDependencyFlags == SelfDependencyFlags::kForInputAttachment) {
    // Sets layout to VK_IMAGE_LAYOUT_GENERAL
} else {
    // Sets layout to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
}

If an operation accumulates both kForInputAttachment (bit 0) and kForNonCoherentAdvBlend (bit 1), resulting in a bitfield value of 3, this equality check fails. The color attachment is incorrectly transitioned to COLOR_ATTACHMENT_OPTIMAL. However, the underlying Vulkan RenderPass is created (correctly using bitwise AND in GrVkRenderPass::Create) with an expectation of GENERAL layout. This discrepancy results in Vulkan undefined behavior due to the layout mismatch.

2. Missing Input Attachment Binding

In GrVkOpsRenderPass::onBindTextures (located at third_party/skia/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp:732):

if (fSelfDependencyFlags == SelfDependencyFlags::kForInputAttachment) {
    auto ds = fFramebuffer->colorAttachment()->inputDescSetForBlending(fGpu);
    // ... binds input attachment descriptor set ...
}

When multiple flags are set, the binding of the input attachment descriptor set (Descriptor Set 2) is skipped entirely. However, the graphics pipeline and fragment shader are built expecting to read from this set via subpassLoad because their construction logic correctly uses bitwise checks.

Potential Security Impact

This vulnerability leads to a potential high-severity information leak within the GPU process:

GPU Memory Information Leak: When the input attachment descriptor set is not bound, the fragment shader’s subpassLoad operation reads from uninitialized or stale GPU memory. The result of this read is then blended into the canvas, potentially allowing an attacker to retrieve leaked GPU memory data via getImageData(). In environments like Android, where the GPU process is shared and often unsandboxed, this represents a significant cross-origin information leak.

Potential Reproduction Steps

Note: These are suggested steps based on code analysis; functional verification has not been performed.

  1. Create a Canvas2D context.
  2. Execute a draw operation using an advanced blend mode that requires a self-dependency (e.g., ctx.globalCompositeOperation = 'multiply'), setting the kForNonCoherentAdvBlend flag.
  3. In the same frame/task, execute a second draw operation that requires a texture barrier (e.g., drawing the canvas back into itself), setting the kForInputAttachment flag.
  4. Flush the canvas to trigger the GrVkOpsRenderPass execution.
  5. Read back the canvas data using ctx.getImageData(). The output may contain data from uninitialized or stale GPU memory due to the missing descriptor binding.

Suggested Fix

The equality checks at third_party/skia/src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp lines 92 and 732 should be replaced with bitwise AND checks:

if (SkToBool(fSelfDependencyFlags & SelfDependencyFlags::kForInputAttachment))

Evaluated with Chrome root at commit: b3153093eb3c78c3e88ccf562bcbc20437a04b0e


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

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