High chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in Dawn
DescriptionUninitialized Use in Dawn
ComponentDawn
Bug ClassUninitialized Memory
Tracker513209610
Fix commite7eb019e0d82 (dawn) +14/-4
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Files Changed

  • src/dawn/native/Blob.cpp
  • src/dawn/native/Blob.h
  • src/dawn/native/vulkan/PipelineCacheVk.cpp
From e7eb019e0d8237395c80b6df7790085d09591105 Mon Sep 17 00:00:00 2001
From: Kyle Charbonneau <[email protected]>
Date: Fri, 15 May 2026 07:40:37 -0700
Subject: [PATCH] Trim data returned for VkPipelineCache

vkCreateGraphicsPipeline() can write less data than the allocated blob
stores. If that happens shrink the blob to match the size written.

Also if VulkanIncompletePipelineCacheWorkaround is triggered then ensure
it's not stored into the cache. The data is suspected to be corrupted if
the workaround triggers.

Bug: 513209610
Change-Id: I4490dcecdd2a5a18d3118557d8fe233f37ac2ac8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/308856
Commit-Queue: Kyle Charbonneau <[email protected]>
Reviewed-by: Loko Kung <[email protected]>
---

diff --git a/src/dawn/native/Blob.cpp b/src/dawn/native/Blob.cpp
index 1c6072d..784a0f4 100644
--- a/src/dawn/native/Blob.cpp
+++ b/src/dawn/native/Blob.cpp
@@ -53,8 +53,8 @@
 }
 
 // static
-Blob Blob::Create(Blob&& original, size_t offset) {
-    Blob result(original.mData.subspan(offset), std::move(original.mDeleter));
+Blob Blob::Create(Blob&& original, size_t offset, size_t extent) {
+    Blob result(original.mData.subspan(offset, extent), std::move(original.mDeleter));
     original.mData = {};
     original.mDeleter = nullptr;
     return result;
diff --git a/src/dawn/native/Blob.h b/src/dawn/native/Blob.h
index 195c5bf1..d398a56 100644
--- a/src/dawn/native/Blob.h
+++ b/src/dawn/native/Blob.h
@@ -47,8 +47,9 @@
     // Creates a blob of the given size.
     static Blob Create(size_t size);
 
-    // Takes ownership of the original blob, creating a new one that offsets the data by |offset|.
-    static Blob Create(Blob&& original, size_t offset);
+    // Takes ownership of the original blob, creating a new one with subspan of the original using
+    // `offset` and optionally `extent`.
+    static Blob Create(Blob&& original, size_t offset, size_t extent = std::dynamic_extent);
 
     template <typename T>
     static Blob Create(std::vector<T> vec)
diff --git a/src/dawn/native/vulkan/PipelineCacheVk.cpp b/src/dawn/native/vulkan/PipelineCacheVk.cpp
index 26ef309..bfa7fcd 100644
--- a/src/dawn/native/vulkan/PipelineCacheVk.cpp
+++ b/src/dawn/native/vulkan/PipelineCacheVk.cpp
@@ -28,6 +28,7 @@
 #include "dawn/native/vulkan/PipelineCacheVk.h"
 
 #include <memory>
+#include <utility>
 
 #include "dawn/native/Device.h"
 #include "dawn/native/Error.h"
@@ -102,10 +103,18 @@
         // store it to the blob cache and don't call vkGetPipelineCacheData() since it will return
         // corrupted data in future calls.
         mSkipSerialize = true;
+        *blob = {};
         return {};
     }
 
     DAWN_TRY(CheckVkSuccess(result, "GetPipelineCacheData"));
+
+    if (bufferSize < blob->Size()) {
+        // vkGetPipelineCacheData() returned less data than expected. Shrink the blob so
+        // uninitialized data isn't stored in cache.
+        *blob = Blob::Create(std::move(*blob), 0, bufferSize);
+    }
+
     mStoredDataSize = bufferSize;
 
     return {};
Loading diff…

Original Bug Report

reported by [email protected]

Potential uninitialized memory persistence and corruption in Dawn Vulkan pipeline cache

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: A logic error in Dawn’s Vulkan backend allows uninitialized GPU process heap memory to be persisted to the on-disk shader cache when a specific driver workaround is triggered. This occurs because the code fails to clear a previously allocated buffer after an incomplete serialization attempt. The persisted data is later reloaded and passed to the Vulkan driver, potentially leading to memory corruption.

Affected files:

  • third_party/dawn/src/dawn/native/vulkan/PipelineCacheVk.cpp
  • third_party/dawn/src/dawn/native/PipelineCache.cpp
  • third_party/dawn/src/dawn/native/Blob.cpp

Estimated timestamp from git blame: Unknown (Google3 checkout)

Description

A potential logic error exists in PipelineCache::SerializeToBlobImpl within Dawn’s Vulkan backend that can cause uninitialized heap memory to be persisted to the persistent blob cache. This occurs when the VulkanIncompletePipelineCacheWorkaround is triggered on specific hardware (e.g., Pixel 10, Samsung Xclipse).

Root Cause Analysis

In third_party/dawn/src/dawn/native/vulkan/PipelineCacheVk.cpp, the function SerializeToBlobImpl handles the serialization of the Vulkan pipeline cache:

  1. At line 95, a blob is allocated to hold the cache data: *blob = Blob::Create(bufferSize);.
  2. Blob::Create in third_party/dawn/src/dawn/native/Blob.cpp (line 46) allocates memory via new uint8_t[size], which leaves the buffer uninitialized, containing residual data from the GPU process heap.
  3. vkGetPipelineCacheData is called to fill this buffer (line 96).
  4. If the call returns VK_INCOMPLETE and the workaround is enabled (line 99), the code sets mSkipSerialize = true and returns success (return {};) at line 105.

However, the function fails to clear or reset the *blob out-parameter before returning. The caller, PipelineCacheBase::Flush() in third_party/dawn/src/dawn/native/PipelineCache.cpp, subsequently checks if (blob.Size() > 0) at line 62. Since the blob was assigned an uninitialized buffer of bufferSize, this condition is true, and the uninitialized memory is stored to the persistent cache via mCache->Store(mKey, blob); (line 65).

Potential Impact

  1. Information Leak: Sensitive residue from the GPU process heap is written to the persistent shader cache on disk.
  2. Memory Corruption: On subsequent sessions, the persisted uninitialized blob is reloaded and passed as pInitialData to vkCreatePipelineCache (line 130 of PipelineCacheVk.cpp). If the driver’s binary parser is not robust against malformed or uninitialized input, this could lead to memory corruption within the GPU process.
  3. Sandbox Escape (Android): On Android, the GPU process is typically unsandboxed by default. Memory corruption in this process could allow an attacker to achieve arbitrary code execution with the user’s full privileges.

Potential Reproduction Steps (Suggested)

Note: These steps are theoretical as they rely on specific hardware behavior and have not been validated by a running exploit.

  1. Use an affected Android device (e.g., Pixel 10 or Samsung Xclipse) with WebGPU enabled.
  2. From a web page, trigger the compilation of a new shader (e.g., via createComputePipeline).
  3. The Vulkan driver returns VK_INCOMPLETE during cache serialization.
  4. Dawn’s workaround triggers but fails to clear the blob out-parameter.
  5. The uninitialized heap memory is written to the on-disk cache.
  6. Restart the browser and re-trigger the same pipeline creation. The corrupted cache is loaded and passed to the driver’s vkCreatePipelineCache, potentially causing corruption.

Suggested Fix

Ensure the *blob out-parameter is cleared before returning in the VK_INCOMPLETE workaround path in third_party/dawn/src/dawn/native/vulkan/PipelineCacheVk.cpp:

if (result == VK_INCOMPLETE && mInvalidResultWorkaround) {
    mSkipSerialize = true;
    *blob = Blob(); // Clear the out-parameter to prevent storage
    return {};
}

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.

View on issue tracker