CVE-2026-17750
Overview
Files Changed
src/libANGLE/renderer/vulkan/ContextVk.cpp
Patch
From 464cb960322f4bef1a189b7d1b525349eea4ca13 Mon Sep 17 00:00:00 2001 From: Shahbaz Youssefi <[email protected]> Date: Thu, 04 Jun 2026 11:07:32 -0400 Subject: [PATCH] Vulkan: Don't ignore `finish()` result on destroy If `finish()` fails, treat it as a device loss before cleaning up. This is a theoretical fix for unlikely scenarios such as OOM during context destruction. Bug: chromium:500560234 Change-Id: I579b929afcfdca96a9b933d6b86806af5beb434a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7903240 Reviewed-by: Charlie Lao <[email protected]> Commit-Queue: Shahbaz Youssefi <[email protected]> --- diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp index d7b9bde..a9aef50 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp @@ -1251,10 +1251,10 @@ mIncompleteTextures.onDestroy(context); // Flush and complete current outstanding work before destruction. - (void)finishImpl(QueueSubmitReason::ContextDestruction); + const angle::Result finishResult = finishImpl(QueueSubmitReason::ContextDestruction); // The finish call could also generate device loss. - if (mRenderer->isDeviceLost()) + if (mRenderer->isDeviceLost() || finishResult != angle::Result::Continue) { mRenderer->handleDeviceLost(); }
Original Bug Report
Driver-side UAF in ANGLE Vulkan via unchecked ContextVk::onDestroy OOM errors
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 logic flaw in ANGLE’s Vulkan backend allows GPU context destruction to proceed without proper synchronization if an Out-Of-Memory error occurs. Because ContextVk::onDestroy discards the error returned by finishImpl and the device is not marked as lost, Vulkan objects are destroyed while the GPU is still actively using them. This leads to a potential driver-side Use-After-Free in the GPU process, which bypasses MiraclePtr and could allow a sandbox escape.
Affected files:
third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cppthird_party/angle/src/libANGLE/renderer/vulkan/CommandQueue.cppthird_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cppthird_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.cppthird_party/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp
Estimated timestamp from git blame: 2025-12-15
Summary
There is a potential Use-After-Free (UAF) vulnerability in ANGLE’s Vulkan backend during context destruction. If an Out-Of-Memory (OOM) error occurs while flushing the remaining commands during teardown, the synchronization step is skipped. Since the failure is discarded and the device is not marked as “lost”, ANGLE immediately destroys Vulkan resources (like VkQueryPool) that the GPU is still actively writing to, leading to a driver-level memory corruption.
Technical Details
- In
ContextVk.cpp,ContextVk::onDestroyinitiates teardown by calling(void)finishImpl(QueueSubmitReason::ContextDestruction). The(void)cast explicitly discards any returned errors. finishImplattempts to flush commands (flushAndSubmitCommands) and wait for the GPU to finish using context resources (mRenderer->finishResourceUse).- If a Vulkan call within these operations fails due to an OOM (e.g.,
VK_ERROR_OUT_OF_HOST_MEMORY), theANGLE_VK_TRYmacro triggersContextVk::handleErrorand returnsangle::Result::Stop. ContextVk::handleErrorlogs the OOM error but crucially does not callhandleDeviceLost()or set themDeviceLostflag, because the error is not explicitlyVK_ERROR_DEVICE_LOST.- The
angle::Result::Stoperror propagates back up but is discarded by the(void)cast inonDestroy. onDestroythen checksif (mRenderer->isDeviceLost()). Since the OOM error did not set this flag, the check evaluates tofalse, bypassingmRenderer->handleDeviceLost(). (If executed, this fallback would have calledmQueueMap.waitAllQueuesIdle()to safely sync the GPU).- In release builds, the subsequent
ASSERT(mRenderer->hasResourceUseFinished(...))is a no-op. - Without waiting for the GPU,
onDestroyiterates and destroys Vulkan objects likeVkQueryPoolandVkCommandPoolvia their respective driver calls (vkDestroyQueryPool, etc.). - The Vulkan driver frees the host-memory allocations backing these objects while the asynchronous GPU operations from prior flushes are still running.
Impact
This causes a UAF in the GPU process. Because the memory backing Vulkan objects like query pools is managed by the proprietary Vulkan driver rather than Chromium’s PartitionAlloc, mitigations like MiraclePtr (BackupRefPtr) do not apply. An attacker could exploit this memory corruption to achieve Remote Code Execution (RCE) in the GPU process, effectively escaping the Renderer sandbox.
Potential Trigger Steps
Note: These are suggested steps to trigger the vulnerability. Our tooling agent does not currently have the capability to execute code to provide a working Proof of Concept.
- Setup: From a malicious webpage, initialize a WebGL2 context (using the ANGLE Vulkan backend).
- Begin Query: Start a WebGL occlusion query (
gl.beginQuery) to allocate tracking structures in aVkQueryPool. - Queue Heavy Workload: Dispatch a massive draw call (e.g., millions of vertices) while the query is active to ensure the GPU will be busy for an extended period, and call
gl.flush(). - Induce Memory Pressure: Rapidly allocate large textures or buffers via WebGL to exhaust available GPU/host memory, ensuring subsequent Vulkan allocations will fail with an OOM error.
- Trigger UAF: Destroy the WebGL context (e.g., by navigating away).
finishImplwill hit an OOM, skip the GPU wait, and the host will free theVkQueryPool. The GPU, still executing the heavy draw call, will eventually write its query results into the now-freed host memory.
Suggested Fix
Do not silently discard the result of finishImpl in ContextVk::onDestroy. If finishImpl returns an error (such as angle::Result::Stop), ensure that the renderer explicitly forces a GPU synchronization (e.g., via mQueueMap.waitAllQueuesIdle()) before destroying any Vulkan objects. Alternatively, update ContextVk::handleError to treat teardown-time OOMs as a fatal device loss to ensure the fallback sync path is always taken.
Evaluated with Chrome root at commit: 137d451a126685dd5010e6609db9f6d4a78d8234
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.