CVE-2026-11099
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifsrc/gpu/ganesh/GrStagingBufferManager.cpp |
modified |
Files Changed
src/gpu/ganesh/GrStagingBufferManager.cpp
Patch
From 1d533738ea9d1ae853e30e33cef024358535afea Mon Sep 17 00:00:00 2001 From: Greg Daniel <[email protected]> Date: Fri, 01 May 2026 13:40:35 +0000 Subject: [PATCH] Fix potential integer underflow in GrStagingBufferManager Bug: b/500414865 Change-Id: I84bf24c1e6fc9b151c1d38f39521919e336e04cc Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1223736 Reviewed-by: Robert Phillips <[email protected]> Commit-Queue: Robert Phillips <[email protected]> Auto-Submit: Greg Daniel <[email protected]> Commit-Queue: Greg Daniel <[email protected]> Reviewed-by: Thomas Smith <[email protected]> --- diff --git a/src/gpu/ganesh/GrStagingBufferManager.cpp b/src/gpu/ganesh/GrStagingBufferManager.cpp index d41abca..5b6d4ad 100644 --- a/src/gpu/ganesh/GrStagingBufferManager.cpp +++ b/src/gpu/ganesh/GrStagingBufferManager.cpp @@ -24,7 +24,7 @@ size_t totalBufferSize = fBuffers[i].fBuffer->size(); size_t currentOffset = fBuffers[i].fOffset; offset = ((currentOffset + requiredAlignment - 1)/requiredAlignment)*requiredAlignment; - if (totalBufferSize - offset >= size) { + if (offset <= totalBufferSize && totalBufferSize - offset >= size) { buffer = &fBuffers[i]; break; }
Original Bug Report
Integer underflow in GrStagingBufferManager leading to OOB write in GPU process
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: An integer underflow in Skia’s GrStagingBufferManager allows an out-of-bounds write in the GPU process. When a staging buffer’s offset is rounded up for alignment, it can exceed the total buffer size, causing the remaining size check to underflow and pass incorrectly.
Affected files:
third_party/skia/src/gpu/ganesh/GrStagingBufferManager.cppthird_party/skia/src/gpu/ganesh/vk/GrVkGpu.cpp
Estimated timestamp from git blame: 2020-12-17
Description
A potential integer underflow vulnerability exists in GrStagingBufferManager::allocateStagingBufferSlice within Skia’s Ganesh Vulkan backend (third_party/skia/src/gpu/ganesh/GrStagingBufferManager.cpp).
When allocating a slice of a GPU staging buffer, the manager calculates an aligned offset and then verifies if the requested size fits within the remaining space:
size_t offset = ((currentOffset + requiredAlignment - 1)/requiredAlignment)*requiredAlignment;
if (totalBufferSize - offset >= size) {
// ... returns a slice starting at fMapPtr + offset
}
If the alignment calculation causes the offset to exceed totalBufferSize, the expression totalBufferSize - offset (which utilizes unsigned size_t arithmetic) underflows to a very large positive value. This causes the bounds check to pass incorrectly. The function then returns a GrStagingBufferManager::Slice containing a CPU pointer (fOffsetMapPtr) that points past the end of the staging buffer’s CPU-mapped memory block.
While staging buffer sizes are typically powers of two, the requested alignment can be non-power-of-two. For example, GrVkGpu::uploadTexDataOptimal calculates the alignment as a multiple of 4 and the texel block size. For a 3-byte format (like VK_FORMAT_R8G8B8_UNORM, mapped to GrColorType::kRGB_888), the required alignment is 12 bytes.
If an attacker manipulates the staging buffer such that currentOffset is very close to the end of the buffer (e.g., 65535 out of a 65536-byte buffer), requesting a 12-byte alignment pushes the new offset to 65544. This triggers the underflow (65536 - 65544 >= size), returning an OOB pointer. Subsequent data copying via SkRectMemcpy will then write out of bounds.
Impact
This vulnerability allows an attacker to achieve an out-of-bounds write in the CPU-mapped memory of the GPU process. Because Skia’s Vulkan backend uses the Vulkan Memory Allocator (VMA), which sub-allocates from large contiguous memory blocks, this OOB write corrupts adjacent data within the same VMA block. An attacker with a compromised renderer process could groom this memory to overwrite sensitive GPU resources or internal metadata, potentially leading to arbitrary code execution and a Sandbox Escape.
Potential Reproduction Steps
Note: These steps trace the required flow through the codebase, though a functional proof-of-concept has not been executed.
- From a compromised renderer, use the
RasterInterfaceto create twoSharedImageobjects. - Create Image A with a 1-byte-per-pixel format (e.g.,
viz::SinglePlaneFormat::kALPHA_8) and dimensions of65535x1(requiring exactly 65535 bytes). - Create Image B with a format that maps to an optimal 3-byte Vulkan format on the target device (e.g.,
VK_FORMAT_R8G8B8_UNORM). - Queue a
WritePixelscommand for Image A with 65535 bytes of data. This initializes a new 65536-byte staging buffer and leaves itscurrentOffsetat 65535. - In the same IPC batch (to prevent the
GrDirectContextfrom submitting and detaching the staging buffers), queue aWritePixelscommand for Image B with a malicious payload. - The GPU process processes Image B, requesting a slice with a 12-byte alignment. The offset calculates to 65544, triggering the underflow.
- The attacker’s payload is copied out of bounds starting at offset 65544.
Suggested Fix
Add an explicit check to ensure offset does not exceed totalBufferSize before performing the subtraction in GrStagingBufferManager::allocateStagingBufferSlice:
size_t offset = ((currentOffset + requiredAlignment - 1)/requiredAlignment)*requiredAlignment;
if (offset <= totalBufferSize && totalBufferSize - offset >= size) {
// ...
}
Evaluated with Chrome root at commit: 137d451a126685dd5010e6609db9f6d4a78d8234
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.