CVE-2026-5902
Overview
Files Changed
media/gpu/android/ndk_video_encode_accelerator.cc
Patch
From cf230cf0cda34477afd4c14096ffc6692fa79994 Mon Sep 17 00:00:00 2001
From: Eugene Zemtsov <eugene@chromium.org>
Date: Wed, 11 Feb 2026 14:34:45 -0800
Subject: [PATCH] media: Fix race condition in NDK VEA's temporal scalability parsing
Previously, the encoder copied bitstream data to shared memory and then
read it back for metadata parsing. This created a race window where a
compromised renderer could modify the shared memory before the browser
parsed it.
Bug: 483109205
Change-Id: Ic6aec49b840c03fed1b01e2f9c2e553e44eec158
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7567414
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1583529}
---
diff --git a/media/gpu/android/ndk_video_encode_accelerator.cc b/media/gpu/android/ndk_video_encode_accelerator.cc
index 30bd5ca..1287329 100644
--- a/media/gpu/android/ndk_video_encode_accelerator.cc
+++ b/media/gpu/android/ndk_video_encode_accelerator.cc
@@ -1484,8 +1484,8 @@
}
TemporalScalabilityIdExtractor::BitstreamMetadata bits_md;
- if (!svc_parser_->ParseChunk(output_dst.first(mc_buffer_size),
- input_since_keyframe_count_, bits_md)) {
+ if (!svc_parser_->ParseChunk(out_buffer_data, input_since_keyframe_count_,
+ bits_md)) {
NotifyErrorStatus({EncoderStatus::Codes::kEncoderHardwareDriverError,
"Parse bitstream failed"});
return;
Original Bug Report
TOCTOU in NdkVideoEncodeAccelerator: shared memory re-read after write allows attacker-controlled bitstream parsing
VULNERABILITY DETAILS
The Android NDK Video Encode Accelerator (NdkVideoEncodeAccelerator) writes encoded bitstream data into an UnsafeSharedMemoryRegion, then re-reads from that same shared memory to parse temporal scalability metadata. The renderer retains write access to this region. A compromised renderer can mutate the buffer contents between the encoder’s write and the metadata parse, feeding attacker-controlled bitstream data to H.264, HEVC, VP9, and AV1 parsers running in the GPU process.
The vulnerable code is in media/gpu/android/ndk_video_encode_accelerator.cc:
- Line 1460: Encoder output copied into shared memory via output_dst.copy_prefix_from
- Line 1487: svc_parser_->ParseChunk() re-reads from the same shared memory span
Between these two lines, the renderer can overwrite the buffer with crafted NALUs/OBUs. The parsers (H264Parser, H265NaluParser, Vp9Parser, libgav1 ObuParser) were not designed to handle adversarial input on this code path. They expect trusted encoder output.
Other platform encoders are not affected. VAAPI derives metadata from encoder-internal state (vaapi_video_encode_accelerator.cc:524-556). V4L2 parses from its kernel mmap’d capture buffer before copying to shared memory (v4l2_video_encode_accelerator.cc:1467-1485). MediaFoundation parses from its MF COM buffer (media_foundation_video_encode_accelerator_win.cc:2398-2413). Only the NDK path parses from the shared memory span after writing to it.
The fix is to move the ParseChunk() call to operate on the MediaCodec output buffer (out_buffer_data) before copying to shared memory, matching the pattern used by V4L2 and MediaFoundation.
VERSION
Chrome Version: trunk (verified against current main branch) Operating System: Android (all versions using NDK MediaCodec encoder)
REPRODUCTION CASE
A standalone PoC demonstrates the race condition by simulating the GPU and renderer threads operating on the same UnsafeSharedMemoryRegion. Results: 1.9 million race wins out of 62 million iterations (3.06% hit rate) in 2 seconds.
The PoC is attached. It can also be built as a Chromium unit test.
The race window exists between ndk_video_encode_accelerator.cc lines 1460 and 1487. In real exploitation, the attacker substitutes arbitrary H.264/VP9/AV1 bitstream data, feeding crafted input to TemporalScalabilityIdExtractor::ParseChunk() (media/parsers/temporal_scalability_id_extractor.cc:56), which dispatches to:
- ParseH264 (line 77): H264Parser::AdvanceToNextNALU on attacker data
- ParseHEVC (line 108): H265NaluParser::AdvanceToNextNALU on attacker data
- ParseVP9 (line 132): Vp9Parser::ParseNextFrame on attacker data, reads ref_frame_idx[] used to index into vp9_ref_buffer_[kVp9NumRefFrames=8]
- ParseAV1 (line 175): libgav1::ObuParser::ParseOneFrame on attacker data, complex parser touching DecoderState and BufferPool
The VP9 and AV1 paths maintain persistent reference frame state across frames, so corrupted state cascades to subsequent frames.
FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION
Type of crash: GPU process. Attacker-controlled data reaches bitstream parsers. Impact depends on parser robustness to adversarial input. Potential outcomes include wrong metadata propagation, parser state corruption, and possible out-of-bounds reads in complex parsers (especially libgav1).
CREDIT INFORMATION
Reporter credit: Luke Francis