diff --git a/chrome/browser/media/cast_mirroring_service_host.cc b/chrome/browser/media/cast_mirroring_service_host.cc index 0b48c9ea61519..2bb91dbec5e88 100644 --- a/chrome/browser/media/cast_mirroring_service_host.cc +++ b/chrome/browser/media/cast_mirroring_service_host.cc @@ -97,21 +97,31 @@ CreateVideoCaptureHostOnIO( std::move(receiver)); } -void PauseVideoCaptureHostOnIO(media::mojom::VideoCaptureHost* host, - base::UnguessableToken device_id, - base::OnceClosure on_paused_callback) { +void PauseVideoCaptureHostOnIO( + mojo::SelfOwnedReceiverRef host, + base::UnguessableToken device_id, + base::OnceClosure on_paused_callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - host->Pause(device_id); + // The SelfOwnedReceiver lives on the IO sequence and may have been destroyed + // by a pipe disconnect from the (potentially compromised) mirroring service + // utility before this task ran. Dereference the WeakPtr on its owning + // sequence to avoid a use-after-free. + if (host) { + host->impl()->Pause(device_id); + } std::move(on_paused_callback).Run(); } -void ResumeVideoCaptureHostOnIO(media::mojom::VideoCaptureHost* host, - base::UnguessableToken device_id, - base::UnguessableToken session_id, - media::VideoCaptureParams params, - base::OnceClosure on_resumed_callback) { +void ResumeVideoCaptureHostOnIO( + mojo::SelfOwnedReceiverRef host, + base::UnguessableToken device_id, + base::UnguessableToken session_id, + media::VideoCaptureParams params, + base::OnceClosure on_resumed_callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - host->Resume(device_id, session_id, params); + if (host) { + host->impl()->Resume(device_id, session_id, params); + } std::move(on_resumed_callback).Run(); } @@ -611,23 +621,23 @@ void CastMirroringServiceHost::OpenOffscreenTab( void CastMirroringServiceHost::Pause(base::OnceClosure on_paused_callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (video_capture_host_) { - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&PauseVideoCaptureHostOnIO, video_capture_host_->impl(), - ignored_token_, std::move(on_paused_callback))); - } + // `video_capture_host_` is a WeakPtr to an object owned on the IO sequence. + // Do not dereference it here; copy it into the posted task and dereference on + // IO to avoid a cross-thread WeakPtr violation and a UAF if the underlying + // SelfOwnedReceiver is destroyed by a pipe disconnect. + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&PauseVideoCaptureHostOnIO, video_capture_host_, + ignored_token_, std::move(on_paused_callback))); } void CastMirroringServiceHost::Resume(base::OnceClosure on_resumed_callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (video_capture_host_) { - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&ResumeVideoCaptureHostOnIO, video_capture_host_->impl(), - ignored_token_, ignored_token_, ignored_params_, - std::move(on_resumed_callback))); - } + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&ResumeVideoCaptureHostOnIO, video_capture_host_, + ignored_token_, ignored_token_, ignored_params_, + std::move(on_resumed_callback))); } void CastMirroringServiceHost::GetMirroringStats(