CVE-2026-9981
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifsrc/gpu/ganesh/vk/GrVkOpsRenderPass.cpp |
modified |
Files Changed
src/gpu/ganesh/vk/GrVkOpsRenderPass.cpp
Patch
From 544395a5d9da52fdaa59ad9c98f32f731b64b6b2 Mon Sep 17 00:00:00 2001 From: Michael Ludwig <[email protected]> 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 <[email protected]> Reviewed-by: Nicolette Prevost <[email protected]> --- 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) {
Original Bug Report
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.
- Create a
Canvas2Dcontext. - Execute a draw operation using an advanced blend mode that requires a self-dependency (e.g.,
ctx.globalCompositeOperation = 'multiply'), setting thekForNonCoherentAdvBlendflag. - 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
kForInputAttachmentflag. - Flush the canvas to trigger the
GrVkOpsRenderPassexecution. - 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.