Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Skia
DescriptionInsufficient validation of untrusted input in Skia
ComponentSkia
Bug ClassLogic Error
Tracker496565479
Fix commit2540f0d8870b (chromium/src) +16/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-27

Files Changed

  • gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h
From 2540f0d8870b855bd58a696ccfd9c213a2e95c88 Mon Sep 17 00:00:00 2001
From: Vasiliy Telezhnikov <vasilyt@chromium.org>
Date: Thu, 07 May 2026 13:33:56 -0700
Subject: [PATCH] Validate YCbCr info enum values

Due to dependency issues, we passed uint32_t values instead of enum
historically, until we can resolve this we should validate against known
values.

Bug: 496282591,496565479
Change-Id: I36e3429b19cd71c32e4317cad24dfb1299c3406f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7823022
Reviewed-by: Joe Mason <joenotcharles@google.com>
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1627197}
---

diff --git a/gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h b/gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h
index e349c8bd..0048aef 100644
--- a/gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h
+++ b/gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h
@@ -51,6 +51,22 @@
     out->suggested_xchroma_offset = data.suggested_xchroma_offset();
     out->suggested_ychroma_offset = data.suggested_ychroma_offset();
     out->format_features = data.format_features();
+
+    // Values from Vulkan definitions, because we can't easy depend on vulkan
+    // here.
+    // https://source.chromium.org/chromium/chromium/src/+/main:third_party/vulkan-headers/src/include/vulkan/vulkan_core.h;drc=f6a6f7ab165cedbfa2a7d0c93fe27a2d01ce09c8;l=5438
+    const uint32_t VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4;
+    const uint32_t VK_CHROMA_LOCATION_MIDPOINT = 1;
+    const uint32_t VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1;
+
+    if (out->suggested_ycbcr_model >
+            VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 ||
+        out->suggested_ycbcr_range > VK_SAMPLER_YCBCR_RANGE_ITU_NARROW ||
+        out->suggested_xchroma_offset > VK_CHROMA_LOCATION_MIDPOINT ||
+        out->suggested_ychroma_offset > VK_CHROMA_LOCATION_MIDPOINT) {
+      return false;
+    }
+
     return true;
   }
 };
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential Sandbox Escape via Bit-Packing Overflow in Skia Graphite Dawn YCbCr Descriptor

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A compromised renderer can send an out-of-bounds VulkanYCbCrInfo.suggested_ycbcr_model value to the GPU process. This value overflows during bit-packing in Skia’s Dawn backend, corrupting the vkChromaFilter field and bypassing Dawn’s validation. This results in undefined behavior when constructing a Vulkan sampler, potentially leading to a sandbox escape in the graphics driver.

Affected files:

  • third_party/skia/src/gpu/graphite/dawn/DawnGraphiteUtils.cpp
  • third_party/dawn/src/dawn/native/vulkan/UtilsVulkan.cpp
  • third_party/dawn/src/dawn/native/Sampler.cpp
  • third_party/skia/src/gpu/graphite/dawn/DawnSampler.cpp
  • gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc

Estimated timestamp from git blame: 2026-02-25

Summary

A bit-packing overflow vulnerability exists in Skia’s Graphite Dawn backend when processing YCbCr descriptors. A compromised renderer process can send a malicious VulkanYCbCrInfo struct via IPC to the GPU process, containing an out-of-bounds suggested_ycbcr_model value. This value is assigned to a Dawn descriptor and passed to Skia without proper validation. During serialization, Skia shifts this value into a bitfield, overflowing its intended bits and corrupting an adjacent field (vkChromaFilter). This invalid filter mode bypasses Dawn’s validation logic, leading to compiler-level undefined behavior when Dawn attempts to convert it to a Vulkan enum. The resulting out-of-bounds Vulkan enum is passed to the highly privileged Vulkan driver, potentially triggering an out-of-bounds array access and arbitrary memory corruption within the driver, constituting a sandbox escape.

Note: These are potential steps as the AI agent doesn’t yet have the ability to run a working proof of concept to verify the full exploit chain.

Root Cause Analysis

  1. Missing IPC Validation: The VulkanYCbCrInfo struct is deserialized in the GPU process via gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h. The Read method copies the fields, including suggested_ycbcr_model, without any bounds checking.
  2. Unvalidated Conversion: This malicious value (e.g., 0xFF) is stored in a viz::TransferableResource and later copied directly into the vkYCbCrModel field of a wgpu::YCbCrVkDescriptor inside gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc:740 (ToDawnYCbCrVkDescriptor).
  3. SkASSERT Bypass: Skia receives this descriptor and attempts to validate the input in third_party/skia/src/gpu/graphite/dawn/DawnGraphiteUtils.cpp:301: SkASSERT(desc.vkYCbCrModel < (1u << kYcbcrModelBits));. However, SkASSERT compiles to a no-op in release builds, so the oversized 0xFF value passes through.
  4. Bit-Packing Overflow: The function DawnDescriptorToImmutableSamplerInfo packs the descriptor fields into a uint32_t. It shifts the oversized model value: ((uint32_t)(desc.vkYCbCrModel) << kYcbcrModelShift). kYcbcrModelShift is 1, and vkYCbCrModel is only supposed to occupy 3 bits. Shifting 0xFF left by 1 produces 0x1FE, which overwrites bits 1 through 8.
  5. Adjacent Field Corruption: The vkChromaFilter field occupies bits 7-8. The overflow from the model shift writes 11 into these bits, completely corrupting the filter mode and setting it to the invalid value 3 (valid values are 0 to 2).

Exploit Path

  1. Reconstruction: Skia later unpacks the corrupted value from the bitfield using DawnDescriptorFromImmutableSamplerInfo, extracting the invalid wgpu::FilterMode of 3.
  2. Validation Bypass: This invalid descriptor is passed back to Dawn to create a sampler. In third_party/dawn/src/dawn/native/Sampler.cpp:74, Dawn validates the descriptor but crucially fails to check the ycbcr->vkChromaFilter field.
  3. Undefined Behavior Sink: When Dawn prepares to call the Vulkan driver, it converts the wgpu::FilterMode to a VkFilter using ToVulkanSamplerFilter (third_party/dawn/src/dawn/native/vulkan/UtilsVulkan.cpp:90). This switch statement does not have a case for 3 and falls through to DAWN_UNREACHABLE(), which expands to __builtin_unreachable() in release builds.
  4. Driver Exploitation: Hitting __builtin_unreachable() invokes compiler-level undefined behavior. The compiler will optimize the code assuming this path is never taken, typically resulting in an invalid VkFilter value (like 2 or 3) being returned and assigned to vulkanYCbCrCreateInfo.chromaFilter. At line 447, Dawn passes this invalid struct to the Vulkan graphics driver via vkCreateSamplerYcbcrConversion. The driver will attempt to use this out-of-bounds enum, likely triggering an out-of-bounds array access within the highly privileged Vulkan driver, leading to a sandbox escape.

Suggested Fix

  1. IPC Validation: Add proper bounds checking to the VulkanYCbCrInfo deserializer in gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h. Ensure all enum-like fields, including suggested_ycbcr_model, are within their expected valid ranges.
  2. Bit-Packing Masking: In third_party/skia/src/gpu/graphite/dawn/DawnGraphiteUtils.cpp, update DawnDescriptorToImmutableSamplerInfo to explicitly mask all input values before bitwise shifting them into the packed integer, preventing any out-of-bounds value from clobbering adjacent fields (e.g., (desc.vkYCbCrModel & ((1u << kYcbcrModelBits) - 1)) << kYcbcrModelShift).
  3. Dawn Validation: Add validation for the ycbcr->vkChromaFilter field within Dawn’s ValidateSamplerDescriptor function.

Evaluated with Chrome root at commit: 0eb4855bda702feaaa8b899336664f97e3df88b8


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. Please feel free to reach out to me if you have concerns or feedback.

View on issue tracker