CVE-2026-15771
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifmedia/gpu/windows/media_foundation_video_encode_accelerator_win.cc |
modified |
Files Changed
media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
Patch
From e156270a01df9c66dca76380e1c7796783d3394c Mon Sep 17 00:00:00 2001 From: Eugene Zemtsov <[email protected]> Date: Sun, 28 Jun 2026 23:17:50 -0700 Subject: [PATCH] media: Validate source texture format in PerformD3DCopy Unfortunately ID3D11DeviceContext::CopySubresourceRegion silently drops copies between incompatible formats. This change adds an explicit check in PerformD3DCopy to ensure the source texture is DXGI_FORMAT_NV12 before copying. Bug: 525177160 Change-Id: I262079c23c553938c08cdc381b8f6d5b2b86d3ff Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8013291 Reviewed-by: Ted (Chromium) Meyer <[email protected]> Commit-Queue: Eugene Zemtsov <[email protected]> Cr-Commit-Position: refs/heads/main@{#1653876} --- diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc index 64bfb8fd..719978306 100644 --- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc +++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc @@ -3111,6 +3111,12 @@ D3D11_TEXTURE2D_DESC input_desc; input_texture->GetDesc(&input_desc); + if (input_desc.Format != DXGI_FORMAT_NV12) { + LOG(ERROR) << "Format mismatch: source format " << input_desc.Format + << " is not DXGI_FORMAT_NV12"; + return E_INVALIDARG; + } + if (visible_rect.x() < 0 || visible_rect.y() < 0 || visible_rect.right() > static_cast<int>(input_desc.Width) || visible_rect.bottom() > static_cast<int>(input_desc.Height)) {
Original Bug Report
Potential uninitialized GPU memory disclosure in MFVEA via D3D11 format mismatch
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 vulnerability in MediaFoundationVideoEncodeAccelerator on Windows allows a compromised renderer to leak uninitialized GPU memory. By supplying a non-NV12 DXGI shared handle under NV12 metadata, a format mismatch occurs that causes CopySubresourceRegion to be silently dropped. The resulting uninitialized destination texture is then encoded and returned to the renderer.
Affected files:
media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
Estimated timestamp from git blame: 2023-07-07
Root Cause Analysis
In MediaFoundationVideoEncodeAccelerator::InitializeD3DCopying (located in media/gpu/windows/media_foundation_video_encode_accelerator_win.cc), a temporary texture copied_d3d11_texture_ is allocated with a hardcoded format of DXGI_FORMAT_NV12 and no initial data (uninitialized GPU VRAM):
// media/gpu/windows/media_foundation_video_encode_accelerator_win.cc:3054-3067
D3D11_TEXTURE2D_DESC copy_desc = {
.Width = static_cast<UINT>(input_visible_size_.width()),
.Height = static_cast<UINT>(input_visible_size_.height()),
.MipLevels = 1,
.ArraySize = 1,
.Format = DXGI_FORMAT_NV12, // <-- Hardcoded format
...};
HRESULT hr = texture_device->CreateTexture2D(©_desc, nullptr, // <-- nullptr initialization (uninitialized VRAM)
&copied_d3d11_texture);
When copying the input texture in PerformD3DCopy, the code queries the input texture’s description but only validates that its dimensions are within bounds. It does not validate that the source texture format (input_desc.Format) is compatible with the destination texture format (DXGI_FORMAT_NV12):
// media/gpu/windows/media_foundation_video_encode_accelerator_win.cc:3111-3130
D3D11_TEXTURE2D_DESC input_desc;
input_texture->GetDesc(&input_desc);
if (visible_rect.x() < 0 || visible_rect.y() < 0 ||
visible_rect.right() > static_cast<int>(input_desc.Width) ||
visible_rect.bottom() > static_cast<int>(input_desc.Height)) {
...
return E_INVALIDARG;
}
D3D11_BOX src_box = {...};
device_context->CopySubresourceRegion(copied_d3d11_texture_.Get(), 0, 0, 0,
0, input_texture, 0, &src_box); // Silent drop on mismatch
Per D3D11 specifications, CopySubresourceRegion requires source and destination formats to be compatible (either identical or within the same type-less group). If a compromised renderer supplies a texture of an incompatible format (e.g., DXGI_FORMAT_B8G8R8A8_UNORM), the D3D11 runtime silently drops the copy command in production/release builds. As a result, copied_d3d11_texture_ remains populated with uninitialized GPU memory. This uninitialized frame is subsequently wrapped, sent to the hardware encoder, compressed, and returned to the renderer.
This behavior is especially hazardous because Windows Mojo deserialization traits (in media/mojo/mojom/video_frame_mojom_traits.cc) lack format cross-verification between the ExportedSharedImage metadata and the underlying GpuMemoryBufferHandle (the validation is conditionally compiled only for Linux/ChromeOS platforms).
Potential Attack Scenario
An attacker controlling a compromised renderer could potentially trigger this issue via the following steps:
- Request a shared image with a non-NV12 format (e.g.,
SinglePlaneFormat::kBGRA_8888) from the GPU process, obtaining a validgfx::DXGIHandlepointing to aDXGI_FORMAT_B8G8R8A8_UNORMtexture. - Forge a
media.mojom.VideoFramewhose metadata lies and claims aPIXEL_FORMAT_NV12format, but populate the backingGpuMemoryBufferHandlewith the non-NV12 handle acquired in Step 1. - Submit this forged frame to the GPU process via
media.mojom.VideoEncodeAccelerator::Encode. - Because the metadata claims
NV12, the frame passes initial format verification checks. - In
PerformD3DCopy,CopySubresourceRegionis called with the incompatible formats (destinationNV12vs sourceBGRA8), resulting in a silent drop of the copy by the D3D11 runtime. - The uninitialized destination VRAM is compressed by the hardware encoder and returned to the renderer, exposing potential cross-origin VRAM contents.
Note: The steps above represent a potential attack vector derived through meticulous manual static analysis of the source code. Our analysis tooling does not currently have the capability to execute live code or run automated proof-of-concept exploits.
Proposed Fix
In media/gpu/windows/media_foundation_video_encode_accelerator_win.cc::PerformD3DCopy, validate that input_desc.Format matches the expected format or is compatible with the destination format before proceeding with CopySubresourceRegion. For example:
D3D11_TEXTURE2D_DESC input_desc;
input_texture->GetDesc(&input_desc);
if (input_desc.Format != DXGI_FORMAT_NV12) {
LOG(ERROR) << "Incompatible input texture format: " << input_desc.Format;
return E_INVALIDARG;
}
Evaluated with Chrome root at commit: 75203b87cbf6681eb7c7dda8e1d0bf781538c76a
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.