CVE-2026-11659
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifui/base/x/x11_display_util.cc |
modified |
Files Changed
ui/base/x/x11_display_util.cc
Patch
From 826fa2041c73cca8dbe5ed6fa2d9870ce7459489 Mon Sep 17 00:00:00 2001
From: Tom Anderson <thomasanderson@chromium.org>
Date: Mon, 18 May 2026 16:19:26 -0700
Subject: [PATCH] [X11][gfx] Validate ICC profiles from X11 root window
Limit the size and complexity of ICC profiles fetched from X11 to
prevent potential memory exhaustion and integer overflows in the color
management pipeline.
- Limit long_length in X11 GetProperty request to 4MB and reject truncated data.
- Use base::CheckedNumeric for size calculation to prevent wrap-around.
- Rely on hardened skcms parser for CLUT complexity validation.
R=thestig
Change-Id: Id5f36245cf0430f0764e233d4a83529649bfa708
Bug: 513702971
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7855799
Commit-Queue: Lei Zhang <thestig@chromium.org>
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1632463}
---
diff --git a/ui/base/x/x11_display_util.cc b/ui/base/x/x11_display_util.cc
index 9af47cd..3c1b275 100644
--- a/ui/base/x/x11_display_util.cc
+++ b/ui/base/x/x11_display_util.cc
@@ -19,6 +19,7 @@
#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "base/notimplemented.h"
+#include "base/numerics/checked_math.h"
#include "base/numerics/clamped_math.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -82,13 +83,21 @@
x11::Future<x11::GetPropertyReply> GetIccProfileFuture(
x11::Connection* connection,
size_t monitor) {
+ // Limit the size of the ICC profile to 4MB. Most monitor profiles are
+ // much smaller than this (typically < 1MB). This prevents potential
+ // memory exhaustion and serves as a first-line defense against malicious
+ // profiles with massive CLUTs.
+ constexpr size_t kMaxIccProfileSize = 4 * 1024 * 1024;
+ // GetProperty takes the length in 4-byte multiples.
+ constexpr uint32_t kMaxIccProfileLongLength = kMaxIccProfileSize / 4;
+
std::string atom_name = monitor == 0
? "_ICC_PROFILE"
: base::StringPrintf("_ICC_PROFILE_%zu", monitor);
auto future = connection->GetProperty({
.window = connection->default_root(),
.property = x11::GetAtom(atom_name.c_str()),
- .long_length = std::numeric_limits<uint32_t>::max(),
+ .long_length = kMaxIccProfileLongLength,
});
future.IgnoreError();
return future;
@@ -96,11 +105,17 @@
gfx::ICCProfile GetIccProfileSync(x11::Future<x11::GetPropertyReply> future) {
auto response = future.Sync();
- if (!response || !response->value_len) {
+ if (!response || !response->value_len || response->bytes_after > 0) {
return gfx::ICCProfile();
}
- return gfx::ICCProfile::FromData(response->value->bytes(),
- response->value_len * response->format / 8u);
+
+ base::CheckedNumeric<size_t> size = response->value_len;
+ size *= (response->format / 8u);
+ if (!size.IsValid()) {
+ return gfx::ICCProfile();
+ }
+
+ return gfx::ICCProfile::FromData(response->value->bytes(), size.ValueOrDie());
}
x11::Future<x11::RandR::GetOutputPropertyReply> GetEdidFuture(
Original Bug Report
Sandbox Escape from GPU to Browser via X11 Root Window _ICC_PROFILE
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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: A compromised GPU process on Linux/X11 can potentially escape its sandbox by manipulating X11 root window properties that are trusted by the unsandboxed browser process. By writing malicious ICC profile data and triggering a display update, the attacker forces the browser to parse and transform the data on the UI thread. This triggers a signed integer overflow in the skcms library, leading to a heap out-of-bounds read in the browser process context.
Affected files:
ui/base/x/x11_display_util.ccui/base/x/x11_display_manager.ccthird_party/skia/modules/skcms/src/Transform_inl.hui/ozone/platform/x11/ozone_platform_x11.ccui/ozone/platform/x11/x11_screen_ozone.ccui/gfx/icc_profile.cc
Estimated timestamp from git blame: Unknown (Google3 checkout)
Summary
A potential vulnerability exists on Linux/X11 systems where a compromised GPU process can escape its sandbox and attack the browser process. By manipulating properties on the X11 root window, an attacker can force the unsandboxed browser process to parse and transform malicious ICC profile data, leading to a heap out-of-bounds read or potential memory corruption in the browser process context.
Root Cause Analysis
On Linux, the GPU process is sandboxed using seccomp-bpf but retains an active X11 socket connection initialized before sandbox engagement (see ui/ozone/platform/x11/ozone_platform_x11.cc). This allows a compromised GPU process to issue X11 requests, such as ChangeProperty, on the root window.
The browser process monitors the X11 root window for changes to properties like _NET_WORKAREA to trigger display list updates. This logic is handled in ui/base/x/x11_display_manager.cc. When a change is detected, the browser calls FetchDisplayList(), which reads display-calibration data from the _ICC_PROFILE properties on the root window via ui/base/x/x11_display_util.cc.
Because any X11 client can write to root window properties, a sandboxed GPU process can deliver an arbitrary ICC profile directly into the browser process’s color-management pipeline. The browser process treats this data as trusted, parsing it on the UI thread without additional sandboxing.
Technical Details
A latent signed integer overflow exists in the Color Lookup Table (CLUT) indexing logic within Skia’s skcms library (third_party/skia/modules/skcms/src/Transform_inl.h). Specifically, index calculations such as 3 * ix or 6 * ix in SIMD gather functions can overflow a 32-bit signed integer when the CLUT grid size is large.
For a 4D CLUT with ~1.33e9 entries (fitting within the 4GB ICC tag limit), the calculated index ix can reach values that, when multiplied by 3 or 6, wrap to a negative value in 32-bit signed arithmetic. This results in an out-of-bounds read at a negative offset relative to the CLUT grid buffer in the browser process.
Potential Exploitation Steps
- From a compromised GPU process, use the existing X11 connection to write a crafted ICC profile to the
_ICC_PROFILEproperty on the root window. The profile should contain a largeA2B0CLUT designed to trigger the3 * ixoverflow. - Update the
_NET_WORKAREAproperty on the root window to trigger a property notification. - The browser process receives the notification, fetches the malicious profile, and executes the transformation pipeline during profile comparison or display initialization.
- The resulting out-of-bounds read may allow the attacker to leak browser process memory or cause a crash on the UI thread.
Suggested Fix
- Validation: The browser process should validate the size and complexity (e.g., total grid points) of ICC profiles fetched from the X11 root window before passing them to the transformation pipeline.
- skcms Hardening: Update
skcmsto usesize_tor 64-bit integers for offset calculations inTransform_inl.h, or implement explicit overflow checks using safe math primitives to ensure indices remain within buffer bounds.
Evaluated with Chrome root at commit: 1a8d40fc44df2088d5945c0bf53584038aa1614a
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.