CVE-2026-11668
Overview
Files Changed
media/gpu/h265_decoder.cc
Patch
From e1a2b97103a2bb314882776699c2db64248ff8a0 Mon Sep 17 00:00:00 2001 From: Hirokazu Honda <[email protected]> Date: Wed, 27 May 2026 11:01:49 -0700 Subject: [PATCH] media/gpu: Skip storing non-decodable H.265 RASL frames in DPB Avoid storing non-decodable RASL (Random Access Skipped Leading) frames in the Decoded Picture Buffer (DPB). Storing them can pollute the DPB and keep uninitialized GPU surfaces active. Bug: 515419790 Test: ideo_decode_accelerator_tests Change-Id: Ic41db1b8c813495595bbd3b16cd6de9408abf4bf Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7874239 Reviewed-by: Andres Calderon Jaramillo <[email protected]> Commit-Queue: Hirokazu Honda <[email protected]> Cr-Commit-Position: refs/heads/main@{#1637091} --- diff --git a/media/gpu/h265_decoder.cc b/media/gpu/h265_decoder.cc index b1467fd..2b7616de 100644 --- a/media/gpu/h265_decoder.cc +++ b/media/gpu/h265_decoder.cc @@ -1181,6 +1181,15 @@ return false; } + // Non-decodable RASL frames are not stored in the DPB because the picture + // is not actually decoded so it doesn't make sense to store it. + if (curr_pic_->no_rasl_output_flag_ && + (curr_pic_->nal_unit_type_ == H265NALU::RASL_N || + curr_pic_->nal_unit_type_ == H265NALU::RASL_R)) { + DVLOG(1) << "Skipping storing non-decodable RASL frame in DPB"; + return true; + } + // Put the current pic in the DPB. dpb_.StorePicture(curr_pic_, H265Picture::kShortTermFoll); return true;
Original Bug Report
Potential Information Leak in H.265 Hardware Decoder via Uninitialized Reference Surfaces
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 the H.265 VA-API and V4L2 hardware video decoder delegates allows non-decodable RASL frames to reside in the Decoded Picture Buffer with uninitialized GPU surfaces. Subsequent frames can reference these surfaces during inter-prediction, potentially leaking stale GPU memory contents across origins. This affects Chromium-based browsers on Linux and ChromeOS utilizing hardware-accelerated H.265 decoding.
Affected files:
media/gpu/vaapi/h265_vaapi_video_decoder_delegate.ccmedia/gpu/v4l2/v4l2_video_decoder_delegate_h265.ccmedia/gpu/h265_decoder.ccmedia/gpu/h265_dpb.cc
Estimated timestamp from git blame: Unknown (Google3 checkout)
Summary
A potential vulnerability exists in the H.265 (HEVC) hardware video decoder implementation for VA-API and V4L2. The issue stems from how the decoder handles Random Access Skipped Leading (RASL) frames when they follow an Intra Random Access Point (IRAP) frame with the NoRaslOutputFlag set. While these RASL frames are correctly identified as non-decodable and “dropped” by the accelerator delegates, they remain in the Decoded Picture Buffer (DPB) associated with uninitialized GPU surfaces. Subsequent frames can then reference these uninitialized surfaces, leading to a cross-origin information leak of GPU memory.
Root Cause Analysis
In H265Decoder::Decode (media/gpu/h265_decoder.cc), when a new frame is encountered, a H265Picture and its corresponding GPU surface are allocated before the accelerator delegate evaluates whether the frame should be decoded.
When SubmitFrameMetadata is called in the VA-API or V4L2 delegates, the code checks if the frame is a RASL frame that should be skipped (per H.265 spec section 8.1.3). If so, the delegate sets a drop_frame_ flag and returns kOk:
// media/gpu/vaapi/h265_vaapi_video_decoder_delegate.cc
if (pic->no_rasl_output_flag_ &&
(slice_hdr->nal_unit_type == H265NALU::RASL_N ||
slice_hdr->nal_unit_type == H265NALU::RASL_R)) {
drop_frame_ = true;
return DecodeStatus::kOk;
}
Because the delegate returns success, the H265Decoder proceeds to store the picture in the DPB (media/gpu/h265_decoder.cc:1185). However, because drop_frame_ is true, the delegate subsequently skips SubmitSlice and SubmitDecode operations. Consequently, the GPU surface (typically a dmabuf allocated via GBM) is never written to by the hardware and remains uninitialized.
Chromium’s GPU surface allocation (e.g., via gbm_bo_create in media/gpu/chromeos/platform_video_frame_pool.cc) does not typically perform zero-filling. Stale data from previous allocations (possibly belonging to other origins or processes) may remain in the buffer.
Potential Exploitation Path
An attacker could potentially exploit this by providing a crafted HEVC bitstream:
- Provide an IRAP frame that sets
no_rasl_output_flag = 1. - Provide a RASL frame (e.g., POC 98). The decoder allocates an uninitialized surface and stores POC 98 in the DPB.
- Provide a subsequent decodable frame (e.g., a
TRAIL_Rframe at POC 101) whose Reference Picture Set (RPS) includes POC 98. - Craft the
TRAIL_Rframe to use POC 98 as a reference with zero motion vectors (e.g., P-skip blocks). This causes the hardware decoder to copy the uninitialized data from the POC 98 surface into the POC 101 output surface. - Read the resulting pixels from POC 101 using
<canvas>or theWebCodecsAPI to exfiltrate stale GPU heap data.
These steps are suggested based on code analysis; our current environment has not verified them with a live proof of concept.
Suggested Fix
When a frame is dropped by the delegate, the decoder should ensure the associated surface is either initialized (e.g., cleared to zero) or that the picture is marked as ‘invalid’ in the DPB so that subsequent frames cannot use it as a reference for inter-prediction.
Evaluated with Chrome root at commit: 29093e11cf509e3593f6229e4b1b075cca356049
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.