CVE-2026-11095
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
formedia/mojo/services/mojo_video_encode_accelerator_service.cc |
modified |
Files Changed
media/mojo/services/mojo_video_encode_accelerator_service.cc
Patch
From a9f6714ee0a6c3707a8d625d246c71762e0f3d7f Mon Sep 17 00:00:00 2001 From: Daniel Angulo <[email protected]> Date: Wed, 15 Apr 2026 19:47:59 -0700 Subject: [PATCH] validate that each layer's width and height do not exceed limits this is a quick fix for a potential security issue Bug: 500293394 Change-Id: Ib4f48953c5c72592863580335cdc8a664466faa6 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7758245 Reviewed-by: Dale Curtis <[email protected]> Commit-Queue: Kalvin Lee <[email protected]> Auto-Submit: Daniel Angulo <[email protected]> Reviewed-by: Kalvin Lee <[email protected]> Cr-Commit-Position: refs/heads/main@{#1615594} --- diff --git a/media/mojo/services/mojo_video_encode_accelerator_service.cc b/media/mojo/services/mojo_video_encode_accelerator_service.cc index dcaa64f..6b9ff3c 100644 --- a/media/mojo/services/mojo_video_encode_accelerator_service.cc +++ b/media/mojo/services/mojo_video_encode_accelerator_service.cc @@ -134,6 +134,21 @@ return; } + for (const auto& spatial_layer : config.spatial_layers) { + if (spatial_layer.width > limits::kMaxDimension || + spatial_layer.height > limits::kMaxDimension || + base::CheckMul<uint64_t>(spatial_layer.width, spatial_layer.height) + .ValueOrDefault(std::numeric_limits<uint64_t>::max()) > + limits::kMaxCanvas) { + MEDIA_LOG(ERROR, media_log_.get()) + << __func__ << "too large spatial_layer " << spatial_layer.width + << "x" << spatial_layer.height; + std::move(success_callback) + .Run({EncoderStatus::Codes::kEncoderInitializationError}); + return; + } + } + encoder_.reset(); auto encoder_or_error = std::move(create_vea_callback_)
Original Bug Report
Potential Heap OOB Write in GPU process via unvalidated VP9 VA-API spatial layers
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 compromised renderer can bypass Mojo dimension checks by supplying a small base resolution and maliciously large spatial layer resolutions in the VideoEncodeAccelerator config. This causes the VA-API hardware driver to allocate a small context but process a massive frame, leading to a potential heap out-of-bounds write in the GPU process.
Affected files:
media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.ccmedia/gpu/vaapi/vaapi_video_encode_accelerator.ccmedia/mojo/mojom/video_encode_accelerator_mojom_traits.ccmedia/mojo/services/mojo_video_encode_accelerator_service.ccmedia/gpu/vaapi/vaapi_wrapper.cc
Estimated timestamp from git blame: 2025-03-26
Description
A vulnerability exists in the VP9 VA-API video encoding implementation where a compromised renderer can potentially trigger a heap out-of-bounds (OOB) write in the GPU process. The issue arises from a failure to validate the dimensions of spatial_layers provided by the renderer during encoder initialization.
Technical Details
- Validation Bypass: In
media/mojo/services/mojo_video_encode_accelerator_service.cc,MojoVideoEncodeAcceleratorService::Initializevalidatesconfig.input_visible_sizeagainstmedia::limits::kMaxDimensionandlimits::kMaxCanvas. However, it does not perform any validation on the dimensions of the elements within theconfig.spatial_layersarray. - Hardware Profile Bypass: Similarly,
VaapiVideoEncodeAccelerator::Initializeverifies thatspatial_layersare sorted by size but fails to check their individual dimensions against the maximum supported resolution of the hardware profile. - Mismatched Initialization:
VP9VaapiVideoEncoderDelegate::Initializeextracts these unvalidatedspatial_layersdimensions. The encoder then creates a VA-API context and allocates output buffers sized according to the small, validatedinput_visible_size. - Implicit Truncation and OOB: During frame submission,
VP9VaapiVideoEncoderDelegate::SubmitFrameParameterscopies the spatial layer dimensions to theVAEncPictureParameterBufferVP9fields (frame_width_src,frame_height_src, etc.). Because the attacker can provide anint32_tvalue likeINT_MAX, and the VA-API parameter fields areuint16_t, the value is truncated (e.g.,INT_MAXbecomes65535). The VA-API driver is then instructed to process a massive 65535x65535 frame within internal context buffers allocated for a much smaller resolution (e.g., 320x240), causing a potential GPU heap out-of-bounds write.
Suggested Attacker Steps
Note: These are potential steps for triggering the vulnerability, as our tooling agent currently lacks the ability to execute code or build a working proof of concept.
- From a compromised renderer process on a platform utilizing VA-API (e.g., ChromeOS, Linux), request a
mojom::VideoEncodeAcceleratorinterface. - Call the
Initializemethod with a maliciously craftedVideoEncodeAcceleratorConfig. - Set
input_visible_sizeto a completely valid, small resolution (e.g., 320x240) to bypass Mojo’s base dimension checks. - Add a single element to the
spatial_layersarray. Because it is a single element, it easily bypasses thestd::ranges::is_sortedcheck in the GPU process. - Set the
widthandheightof this spatial layer to0x7FFFFFFF(INT_MAX). - Submit a video frame for encoding. The VA-API driver will receive picture parameters for a 65535x65535 frame but will execute the encode on a 320x240 heap context.
Suggested Fix
- Mojo Service Validation: In
MojoVideoEncodeAcceleratorService::Initialize, iterate overconfig.spatial_layersand validate that each layer’swidthandheightdo not exceedlimits::kMaxDimension, and that the calculated area does not exceedlimits::kMaxCanvas. - VEA Validation: In
VaapiVideoEncodeAccelerator::Initialize, ensure that all provided spatial layer dimensions are less than or equal to the selected profile’smax_resolution. - Ensure spatial layer dimensions are strictly constrained by and validated against the base
input_visible_sizewhere appropriate.
Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad
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.