High chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in ANGLE
DescriptionUninitialized Use in ANGLE
ComponentANGLE
Bug ClassUninitialized Memory
Tracker513922055
Fix commit97bf9e93f775 (angle/angle) +21/-2
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Changed Functions

FunctionChangeNotes
implementation modified

Files Changed

  • src/libANGLE/renderer/vulkan/vk_ref_counted_event.h
From 97bf9e93f77588818ee137203de217be316291b6 Mon Sep 17 00:00:00 2001
From: Charlie Lao <[email protected]>
Date: Fri, 29 May 2026 15:23:19 -0700
Subject: [PATCH] Vulkan: Fix stale RefCountedEventArrayWithAccessFlags::mAccessFlags

When a BufferHelper is re-initialized or orphaned (e.g., via
glBufferData), it calls initializeBarrierTracker(), which calls
mCurrentReadEvents.release(renderer). This call resolves to the base
class implementation, leaving the mAccessFlags map populated with stale
data from the buffer's previous incarnation. This may cause other
problems later on when this buffer gets used. This CL ensures we clear
mAccessFlags on release() call.

Bug: b/513922055
Change-Id: I36f1d9588280001866b73c1b71c29fab0d318ef3
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7885808
Reviewed-by: Shahbaz Youssefi <[email protected]>
Commit-Queue: Charlie Lao <[email protected]>
Reviewed-by: Amirali Abdolrashidi <[email protected]>
---

diff --git a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h
index 4a0b011..086cc4b 100644
--- a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h
+++ b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h
@@ -299,6 +299,17 @@
         ASSERT(mBitMask[eventStage]);
         return mAccessFlags[eventStage];
     }
+
+    void release(Renderer *renderer)
+    {
+        RefCountedEventArray::release(renderer);
+        mAccessFlags.fill(0);
+    }
+    void release(Context *context)
+    {
+        RefCountedEventArray::release(context);
+        mAccessFlags.fill(0);
+    }
     void releaseToEventCollector(RefCountedEventCollector *eventCollector)
     {
         for (EventStage eventStage : mBitMask)
@@ -322,8 +333,16 @@
   public:
     RefCountedEventWithAccessFlags() : mAccessFlags(0) {}
 
-    void release(Renderer *renderer) { mEvent.release(renderer); }
-    void release(Context *context) { mEvent.release(context); }
+    void release(Renderer *renderer)
+    {
+        mEvent.release(renderer);
+        mAccessFlags = 0;
+    }
+    void release(Context *context)
+    {
+        mEvent.release(context);
+        mAccessFlags = 0;
+    }
     void releaseToEventCollector(RefCountedEventCollector *eventCollector)
     {
         eventCollector->emplace_back(std::move(mEvent));
Loading diff…

Original Bug Report

reported by [email protected]

ANGLE Vulkan: Potential stale access flags in synchronization tracker cause memory barrier bypass

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 logic error in ANGLE’s Vulkan backend prevents the synchronization state of buffers from being fully cleared during re-initialization. Stale access flags from previous buffer uses can persist, causing subsequent memory barriers to be incorrectly skipped. This can lead to read-after-write hazards and potential cross-origin information leaks in the GPU process on Android.

Affected files:

  • third_party/angle/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h
  • third_party/angle/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp
  • third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cpp
  • third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
  • third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp

Estimated timestamp from git blame: 2025-02-05

Background

In ANGLE’s Vulkan backend, the RefCountedEventArrayWithAccessFlags class is used to track Vulkan events and their associated access flags (VkAccessFlags) to optimize synchronization. It inherits from RefCountedEventArray. This tracking allows the backend to skip redundant memory barriers if a specific access type has already been synchronized for a given pipeline stage.

Description

A potential vulnerability exists where RefCountedEventArrayWithAccessFlags fails to override the release(Renderer*) and release(Context*) methods from its base class. While it shadows releaseToEventCollector, the standard release methods (defined in vk_ref_counted_event.cpp, lines 135-153) only reset the mBitMask and release the underlying events, but have no knowledge of the mAccessFlags map introduced in the derived class.

When a BufferHelper is re-initialized or orphaned (e.g., via glBufferData), initializeBarrierTracker calls mCurrentReadEvents.release(renderer) (vk_helpers.cpp, line 4867). This call resolves to the base class implementation, leaving the mAccessFlags map populated with stale data from the buffer’s previous incarnation.

In the new incarnation, the first call to replaceEventAtStage for a specific stage will OR-accumulate new access flags into the stale ones: mAccessFlags[eventStage] |= accessFlags (vk_ref_counted_event.h, line 294). Subsequent calls to hasEventAndAccess then return false positives for access types that were only present in the stale data:

bool hasEventAndAccess(EventStage eventStage, VkAccessFlags accessType) const {
    return mBitMask.test(eventStage) && (mAccessFlags[eventStage] & accessType) == accessType;
}

This causes recordReadBarrier to incorrectly skip necessary Vulkan memory barriers:

if (mCurrentReadEvents.hasEventAndAccess(eventStage, readAccessType)) {
    return;    // Potential incorrect barrier skip
}

Potential Impact

This synchronization failure leads to read-after-write hazards. Specifically, it can cause the GPU to skip the barrier required for the zero-initialization write performed during robust_resource_initialization. An attacker could exploit this to read uninitialized GPU memory or data previously residing in memory allocated to other origins.

On Android, the GPU process is shared across origins and is not sandboxed by default. A compromised renderer could leverage this flaw to exfiltrate cross-origin GPU data, which constitutes a sandbox escape.

Suggested Reproducer Steps

Note: These steps are based on source code analysis; a functional PoC has not been executed.

  1. From a compromised renderer, create a GL buffer and perform read operations (e.g., uniform reads) to populate the access flag tracker.
  2. Re-initialize the buffer using glBufferData with the same size to trigger BufferHelper reuse.
  3. Perform a new operation that involves a write followed by a read with the same access type as the stale flags.
  4. Observe if the Vulkan memory barrier for the second read is omitted in the command stream, allowing the read to occur before the write (e.g., the zero-fill) is visible.

Suggested Fix

RefCountedEventArrayWithAccessFlags should override both release(Renderer *renderer) and release(Context *context) to explicitly clear the mAccessFlags map. For example:

void release(Renderer *renderer) {
    RefCountedEventArray::release(renderer);
    mAccessFlags.fill(0);
}

void release(Context *context) {
    RefCountedEventArray::release(context);
    mAccessFlags.fill(0);
}

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.

View on issue tracker