CVE-2026-11085
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifgpu/command_buffer/service/indexed_buffer_binding_host.cc |
modified |
Files Changed
gpu/command_buffer/service/indexed_buffer_binding_host.cc
Patch
From 857172c2d18b095acfd8e1a5ced0a5e89763a931 Mon Sep 17 00:00:00 2001 From: Corentin Wallez <[email protected]> Date: Thu, 21 May 2026 09:00:36 -0700 Subject: [PATCH] [gpu] indexed_buffer_binding_host.cc: Avoid overflow of size + offset In two cases the computation of a buffer binding's size + offset could overflow making computation take the wrong code path. Instead make sure that computation never have overflow by doing checks in this order: 1. offset >= buffer_size -> OOB case 2. size > buffer_size - offset -> OOB case 3. in bounds case Fixed: 500132379 Change-Id: I874d69f527d9811260ee4ab73b71bcb0681d885f Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7865284 Reviewed-by: Geoff Lang <[email protected]> Commit-Queue: Geoff Lang <[email protected]> Auto-Submit: Corentin Wallez <[email protected]> Cr-Commit-Position: refs/heads/main@{#1634328} --- diff --git a/gpu/command_buffer/service/indexed_buffer_binding_host.cc b/gpu/command_buffer/service/indexed_buffer_binding_host.cc index d19c6053..f605cb28 100644 --- a/gpu/command_buffer/service/indexed_buffer_binding_host.cc +++ b/gpu/command_buffer/service/indexed_buffer_binding_host.cc @@ -153,9 +153,7 @@ glBindBufferBase(target, index, service_id); return; } - GLsizeiptr range_end = 0; - if (!base::CheckAdd(offset, size).AssignIfValid(&range_end) || - range_end > full_buffer_size) { + if (size > full_buffer_size - offset) { adjusted_size = full_buffer_size - offset; // size needs to be a multiple of 4. adjusted_size = adjusted_size & ~3; @@ -281,8 +279,12 @@ case IndexedBufferBindingType::kBindBufferBase: return full_buffer_size; case IndexedBufferBindingType::kBindBufferRange: - if (binding.offset + binding.size > full_buffer_size) + if (binding.offset > full_buffer_size) { + return 0; + } + if (binding.size > full_buffer_size - binding.offset) { return full_buffer_size - binding.offset; + } return binding.size; case IndexedBufferBindingType::kBindBufferNone: return 0;
Original Bug Report
32-bit signed overflow in IndexedBufferBindingHost allows OOB GPU access
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: A signed integer overflow in IndexedBufferBindingHost::GetEffectiveBufferSize and DoAdjustedBindBufferRange bypasses buffer bounds checks on 32-bit platforms. This allows a malicious WebGL app to bind an inflated buffer size, potentially tricking the underlying GPU driver into allowing out-of-bounds reads/writes during Transform Feedback or Uniform Block operations.
Affected files:
gpu/command_buffer/service/indexed_buffer_binding_host.ccgpu/command_buffer/service/buffer_manager.ccgpu/command_buffer/service/gles2_cmd_decoder.cc
Estimated timestamp from git blame: 2019-02-12
Description
A potential 32-bit signed integer overflow vulnerability exists in the validating command decoder’s buffer binding logic on 32-bit platforms (such as 32-bit Android). The OpenGL types GLintptr and GLsizeiptr are defined as 32-bit signed integers (khronos_ssize_t / long int). Because Chromium compiles with -fno-strict-overflow, signed integer addition wraps predictably.
Two critical bounds checks in gpu/command_buffer/service/indexed_buffer_binding_host.cc use direct addition without overflow protection:
- In
IndexedBufferBindingHost::DoAdjustedBindBufferRange(which computes clamped parameters to safely send to the underlying OpenGL driver):
if (offset + size > full_buffer_size) {
adjusted_size = full_buffer_size - offset;
// ...
- In
IndexedBufferBindingHost::GetEffectiveBufferSize(which determines the size available forBufferManagerto validate draw calls):
if (binding.offset + binding.size > full_buffer_size)
return full_buffer_size - binding.offset;
return binding.size;
If an attacker provides an offset and size that overflow a signed 32-bit integer when added (e.g., offset = 4 and size = 0x7FFFFFFC), the sum becomes negative (e.g., -2147483648). This negative sum is less than full_buffer_size, causing the bounds check to be entirely bypassed.
Consequently, the command decoder passes the massive size directly to the graphics driver (glBindBufferRange) and subsequently returns that massive size to BufferManager::RequestBuffersAccess. This bypasses the protections designed to prevent out-of-bounds GPU access.
Potential Attack Steps
Note: These are potential steps; our automated tooling has not yet executed a live proof-of-concept.
- A malicious WebGL2 script running in the renderer creates a small
WebGLBuffer(e.g., 100 bytes). - The script calls
gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, buffer, 4, 0x7FFFFFFC). - Blink’s
WebGL2RenderingContextBase::bindBufferRangeverifies that the size and offset fit within a non-negative 32-bit range, but does not check them against the actual buffer size, dispatching the IPC command. - The GPU process executes
IndexedBufferBindingHost::DoBindBufferRange. Because4 + 0x7FFFFFFCoverflows to-2147483648, the checkoffset + size > full_buffer_sizefails. The underlying OpenGL driver is commanded to bind a ~2 GiB range. - The script issues a draw call utilizing the bound UBO or Transform Feedback, requiring a size larger than the actual 100-byte buffer (e.g., 1000 bytes).
- During draw validation,
BufferManager::RequestBuffersAccesscallsGetEffectiveBufferSize. The overflow occurs again, causing the function to incorrectly report that the buffer has0x7FFFFFFCbytes available. - The draw call successfully validates and is sent to the GPU driver. Because the driver was misconfigured in step 4, the GPU hardware performs an out-of-bounds read (for UBOs) or out-of-bounds write (for Transform Feedback) into adjacent GPU memory.
- An attacker can use Transform Feedback OOB writes to corrupt GPU memory, leading to a potential sandbox escape from the renderer to the GPU process.
Recommendation
Replace the unsafe addition in IndexedBufferBindingHost with safe integer arithmetic using base::CheckAdd. Other components, such as Buffer::CheckRange in gpu/command_buffer/service/buffer_manager.cc, already successfully use this pattern:
// Example fix
GLsizeiptr max;
if (!base::CheckAdd(offset, size).AssignIfValid(&max) || max > full_buffer_size) {
// clamp or handle error
}
Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad
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.