CVE-2026-12029
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifmedia/gpu/windows/d3d12_video_encode_accelerator.cc |
modified |
Files Changed
media/gpu/windows/d3d12_video_encode_accelerator.cc
Patch
From 5f731169915a1d6e0509af5b5b2d7ab4db265ba8 Mon Sep 17 00:00:00 2001 From: Qiu Jianlin <[email protected]> Date: Mon, 01 Jun 2026 16:12:04 -0700 Subject: [PATCH] Avoid UAF of texture resources by D3D12 accelerator on destruction. The input/upload texutre might be released before we destroy the copy command wrapper. Make sure the copy command wrapper finish copy before those resources are released. Bug: 518002958 Change-Id: I3567d293f61e579b4dafec1759b11a5fb9f9fcbe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7886292 Reviewed-by: Dale Curtis <[email protected]> Auto-Submit: Qiu, Jianlin <[email protected]> Commit-Queue: Qiu, Jianlin <[email protected]> Cr-Commit-Position: refs/heads/main@{#1639755} --- diff --git a/media/gpu/windows/d3d12_video_encode_accelerator.cc b/media/gpu/windows/d3d12_video_encode_accelerator.cc index c63ff71..ef4e5e067 100644 --- a/media/gpu/windows/d3d12_video_encode_accelerator.cc +++ b/media/gpu/windows/d3d12_video_encode_accelerator.cc @@ -413,6 +413,14 @@ VLOGF(2); DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_); + // Wait for any in-flight copy to complete before the members are destroyed, + // so that the resources backing the copy (e.g. `upload_buffer_`, + // `input_texture_`) are not released while the GPU may still be reading from + // or writing to them. + if (copy_command_queue_) { + copy_command_queue_->WaitSync(); + } + if (!error_occurred_ && encoded_at_least_one_frame_) { base::UmaHistogramEnumeration( GetEncoderStatusHistogramName(config_.output_profile),
Original Bug Report
Potential GPU Use-After-Free in D3D12VideoEncodeAccelerator due to member destruction order
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 potential Use-After-Free (UAF) / lifetime issue exists in D3D12VideoEncodeAccelerator on Windows because the persistent D3D12 resources are destroyed before the copy command queue blocks on GPU synchronization. Under specific conditions such as early validation failures or abrupt teardown, an active copy operation may still be executing on the GPU while the backing resources are freed. This can allow an attacker-controlled copy operation to read or write to released GPU memory heaps, potentially corrupting other GPU process allocations.
Affected files:
media/gpu/windows/d3d12_video_encode_accelerator.hmedia/gpu/windows/d3d12_video_encode_accelerator.cc
Estimated timestamp from git blame: 2025-12-11
Summary
A potential Use-After-Free (UAF) / lifetime issue exists in D3D12VideoEncodeAccelerator on Windows due to the C++ declaration order of its member variables. When the accelerator is destroyed, the persistent resources input_texture_ and upload_buffer_ are released on the CPU before ~D3D12CopyCommandQueueWrapper() blocks on the GPU sync fence (WaitSync()). As a result, the GPU’s asynchronous COPY engine may still be reading from or writing to the underlying memory heaps of these resources after they are freed.
Root Cause Analysis
In media/gpu/windows/d3d12_video_encode_accelerator.h, the member variables are declared in the following order:
std::unique_ptr<D3D12CopyCommandQueueWrapper> copy_command_queue_
GUARDED_BY_CONTEXT(encoder_sequence_checker_);
...
// Persistent D3D12 resources for if the input frame needs to be copied from
// shared memory.
Microsoft::WRL::ComPtr<ID3D12Resource> upload_buffer_
GUARDED_BY_CONTEXT(encoder_sequence_checker_);
Microsoft::WRL::ComPtr<ID3D12Resource> input_texture_
GUARDED_BY_CONTEXT(encoder_sequence_checker_);
Under C++ rules, non-static class members are destroyed in the reverse order of their declaration. During the destruction of D3D12VideoEncodeAccelerator, input_texture_ (line 240) and upload_buffer_ (line 238) are released first. Only afterwards is copy_command_queue_ (line 210) destroyed, which triggers its destructor to wait on the CPU for the GPU copy operation to complete via WaitSync():
D3D12CopyCommandQueueWrapper::~D3D12CopyCommandQueueWrapper() {
WaitSync();
}
Because the ID3D12Resource pointers are released before the wait is executed, their COM reference counts can drop to zero, prompting the D3D12 driver to immediately free or recycle the underlyingDEFAULT/UPLOAD memory heaps while the GPU COPY engine is still actively reading/writing to them.
Suggested / Potential Trigger Path
Because our automated tooling agent cannot run code, we do not have a working proof of concept, and the following is a potential trigger path:
- Initiate Encode: A compromised renderer sends an
Encode()request containing a shared-memory–backedVideoFrame(STORAGE_SHMEM). This forces the GPU process to executeCreateResourceForSharedMemoryVideoFrame()(media/gpu/windows/d3d12_video_encode_accelerator.ccline 751). - Execute Copy: The accelerator calls
copy_command_queue_->CopyBufferToNV12Textureand executes it viacopy_command_queue_->Execute()(line 832). This queues an asynchronous DMA transfer on the GPU’s COPY engine, reading fromupload_buffer_and writing toinput_texture_. - Early Rejection: If the renderer supplies invalid
EncodeOptions(such as out-of-bounds reference buffers), the validation check insideD3D12VideoEncodeDelegate::Encodefails (line 277). It returnskBadReferenceBufferearly without calling the actual video encoder wrapper. This bypasses the typicalSignalAndWaitCPU()call that would synchronize the GPU and CPU threads. - Immediate Destruction: Simultaneously, the renderer closes the Mojo IPC pipe, which schedules a
DestroyTaskon the child sequence. This task executesdelete thisonD3D12VideoEncodeAccelerator. - GPU UAF / Corruption: The destructor runs. Due to reverse destruction order,
input_texture_andupload_buffer_are released. The GPU COPY engine continues to access the freed memory, causing a use-after-free on the GPU.
Proposed Remediation
This issue can be fixed by either:
- Reordering the member declarations in
media/gpu/windows/d3d12_video_encode_accelerator.hso thatcopy_command_queue_is declared afterupload_buffer_andinput_texture_. This ensures~D3D12CopyCommandQueueWrapper()executes its GPU wait block before the resources are destroyed. - Alternatively, explicitly calling
copy_command_queue_->WaitSync()inside the destructor~D3D12VideoEncodeAccelerator()before any other members are released.
Evaluated with Chrome root at commit: fb72408a8493c46bc75fae1c70d03daec96b3040
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.