CVE-2025-8578
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcomponents/mirroring/service/openscreen_session_host.cc |
modified |
Files Changed
components/mirroring/service/openscreen_session_host.cccomponents/mirroring/service/openscreen_session_host.h
Patch
From e67cd45088c4d1eb50ac0f4a66b428e320531b97 Mon Sep 17 00:00:00 2001
From: Jordan Bayles <jophba@chromium.org>
Date: Thu, 12 Jun 2025 15:17:38 -0700
Subject: [PATCH] [Cast Streaming] Fix UaF caused by binding a view object
This patch fixes a use-after-free issue in the
OpenscreenSessionHost::ReportAndLogError method caused by using
a locally allocated string with a function that takes a string_view
and is wrapped in base::BindPostTaskToCurrentDefault.
The solution is to change the callback and function signatures to
own the std::string instance. Since this instance is an error message
generated for this callback specifically, this should not result in
any superfluous copies.
Bug: 423387026
Change-Id: Ib2e897a65c26b7780171470bad20d56782a81d7e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6635890
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Muyao Xu <muyaoxu@google.com>
Cr-Commit-Position: refs/heads/main@{#1473218}
---
diff --git a/components/mirroring/service/openscreen_session_host.cc b/components/mirroring/service/openscreen_session_host.cc
index c9775e33..7277c5b 100644
--- a/components/mirroring/service/openscreen_session_host.cc
+++ b/components/mirroring/service/openscreen_session_host.cc
@@ -193,7 +193,10 @@
using AudioDataCallback =
base::RepeatingCallback<void(std::unique_ptr<media::AudioBus> audio_bus,
base::TimeTicks recorded_time)>;
- using ErrorCallback = base::OnceCallback<void(std::string_view)>;
+
+ // NOTE: the caller is expected to take ownership of the error message, since
+ // we cannot otherwise make any guarantees about its lifetime.
+ using ErrorCallback = base::OnceCallback<void(std::string)>;
AudioCapturingCallback(AudioDataCallback audio_data_callback,
ErrorCallback error_callback,
mojo::Remote<mojom::SessionObserver>& observer)
@@ -232,11 +235,11 @@
void OnCaptureError(media::AudioCapturerSource::ErrorCode code,
const std::string& message) override {
- std::string error_message = base::StrCat(
- {"AudioCaptureError occurred, code: ",
- base::NumberToString(static_cast<int>(code)), ", message: ", message});
- if (!error_callback_.is_null()) {
- std::move(error_callback_).Run(error_message);
+ if (error_callback_) {
+ std::move(error_callback_)
+ .Run(base::StrCat({"AudioCaptureError occurred, code: ",
+ base::NumberToString(static_cast<int>(code)),
+ ", message: ", message}));
}
}
@@ -736,7 +739,7 @@
}
void OpenscreenSessionHost::ReportAndLogError(SessionError error,
- std::string_view message) {
+ std::string message) {
base::UmaHistogramEnumeration("MediaRouter.MirroringService.SessionError",
error);
logger_.LogError(error, message);
diff --git a/components/mirroring/service/openscreen_session_host.h b/components/mirroring/service/openscreen_session_host.h
index 7c093ad..f1caa444 100644
--- a/components/mirroring/service/openscreen_session_host.h
+++ b/components/mirroring/service/openscreen_session_host.h
@@ -150,7 +150,11 @@
void OnAsyncInitialized(const SupportedProfiles& profiles);
// Notify `observer_` that error occurred and close the session.
- void ReportAndLogError(mojom::SessionError error, std::string_view message);
+ //
+ // NOTE: since this method is used with base::Callback, it takes ownership
+ // of the `message` to avoid lifetime issues, especially when posted to a task
+ // runner.
+ void ReportAndLogError(mojom::SessionError error, std::string message);
// Stops the current streaming session. If not called from StopSession(), a
// new streaming session will start later after exchanging OFFER/ANSWER
Original Bug Report
Likely UAF in OpenscreenSessionHost::ReportAndLogError
VULNERABILITY DETAILS
The issue is reported via a GWP-ASan cab.
Allocation stack trace size: 27 Deallocation stack trace size: 23 Allocation address: 6ec00e5efa0 Allocation size: 60 Error type: Use After Free Region start: 6ec00003000 Region size: 1041000 Allocator Type: Malloc GWP-ASan Mode: Classic Allocation Thread ID: 5288
Allocation Stack Trace:
0 0x7fff548de0f5 [msedge!base::debug::CollectStackTrace at base/debug/stack_trace_win.cc:326] 1 0x7fff548de0b5 [msedge!gwp_asan::internal::AllocationInfo::GetStackTrace at components/gwp_asan/common/allocation_info.cc:27] 2 0x7fff53cba3b9 [msedge!gwp_asan::internal::GuardedPageAllocator::Allocate at components/gwp_asan/client/guarded_page_allocator.cc:324] 3 0x7fff51de7326 [msedge!gwp_asan::internal::`anonymous namespace’::AllocFn at components/gwp_asan/client/sampling_malloc_shims.cc:56] 4 0x7fff52ff1fdf [msedge!malloc at base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_ucrt_symbols_win.h:94] 5 0x7fff55d50817 [msedge!operator new at vctools/crt/vcstartup/src/heap/new_scalar.cpp:36] 6 0x7fff548c2ed9 [msedge!base::StrCat at base/strings/strcat.cc:15] 7 0x7fff5e6e26bc [msedge!mirroring::OpenscreenSessionHost::AudioCapturingCallback::OnCaptureError at components/mirroring/service/openscreen_session_host.cc:237] 8 0x7fff56a3b988 [msedge!media::AudioInputDevice::DetectedDeadInputStream at media/audio/audio_input_device.cc:378] 9 0x7fff5486b125 [msedge!base::RepeatingCallback<void ()>::Run at base/functional/callback.h:345] 10 0x7fff56a38f20 [msedge!media::AliveChecker::CheckIfAlive at media/audio/alive_checker.cc:143] 11 0x7fff54c8f898 [msedge!base::RepeatingTimer::RunUserTask at base/timer/timer.cc:215] 12 0x7fff52171c4f [msedge!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork at base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:332] 13 0x7fff52fc358f [msedge!base::MessagePumpDefault::Run at base/message_loop/message_pump_default.cc:43] 14 0x7fff53d1418e [msedge!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run at base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:634] 15 0x7fff53d12a5f [msedge!base::RunLoop::Run at base/run_loop.cc:139] 16 0x7fff56156e81 [msedge!content::UtilityMain at content/utility/utility_main.cc:626] 17 0x7fff51edb917 [msedge!content::RunOtherNamedProcessTypeMain at content/app/content_main_runner_impl.cc:791] 18 0x7fff51eda690 [msedge!content::ContentMainRunnerImpl::Run at content/app/content_main_runner_impl.cc:1171] 19 0x7fff51ed9cfa [msedge!content::RunContentProcess at content/app/content_main.cc:419] 20 0x7fff51ed8fda [msedge!content::ContentMain at content/app/content_main.cc:432] 21 0x7fff51ed8969 [msedge!ChromeMain at chrome/app/chrome_main.cc:340] 22 0x7ff635e17ce6 [msedge_exe!MainDllLoader::Launch at chrome/app/main_dll_loader_win.cc:241] 23 0x7ff635e15597 [msedge_exe!wWinMain at chrome/app/chrome_exe_main_win.cc:804] 24 0x7ff635ef94c2 [msedge_exe!__scrt_common_main_seh at vctools/crt/vcstartup/src/startup/exe_common.inl:288] 25 0x7fffd8eb259d [kernel32!BaseThreadInitThunk at clientcore/base/win32/client/thread.c:75] 26 0x7fffda7eaf58 [ntdll!RtlUserThreadStart at minkernel/ntdll/rtlstrt.c:1166]
Deallocation Thread ID: 5288
Deallocation Stack Trace:
0 0x7fff548de0f5 [msedge!base::debug::CollectStackTrace at base/debug/stack_trace_win.cc:326] 1 0x7fff548de0b5 [msedge!gwp_asan::internal::AllocationInfo::GetStackTrace at components/gwp_asan/common/allocation_info.cc:27] 2 0x7fff53d54451 [msedge!gwp_asan::internal::GuardedPageAllocator::Deallocate at components/gwp_asan/client/guarded_page_allocator.cc:364] 3 0x7fff5e6e272a [msedge!mirroring::OpenscreenSessionHost::AudioCapturingCallback::OnCaptureError at components/mirroring/service/openscreen_session_host.cc:243] 4 0x7fff56a3b988 [msedge!media::AudioInputDevice::DetectedDeadInputStream at media/audio/audio_input_device.cc:378] 5 0x7fff5486b125 [msedge!base::RepeatingCallback<void ()>::Run at base/functional/callback.h:345] 6 0x7fff56a38f20 [msedge!media::AliveChecker::CheckIfAlive at media/audio/alive_checker.cc:143] 7 0x7fff54c8f898 [msedge!base::RepeatingTimer::RunUserTask at base/timer/timer.cc:215] 8 0x7fff52171c4f [msedge!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork at base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:332] 9 0x7fff52fc358f [msedge!base::MessagePumpDefault::Run at base/message_loop/message_pump_default.cc:43] 10 0x7fff53d1418e [msedge!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run at base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:634] 11 0x7fff53d12a5f [msedge!base::RunLoop::Run at base/run_loop.cc:139] 12 0x7fff56156e81 [msedge!content::UtilityMain at content/utility/utility_main.cc:626] 13 0x7fff51edb917 [msedge!content::RunOtherNamedProcessTypeMain at content/app/content_main_runner_impl.cc:791] 14 0x7fff51eda690 [msedge!content::ContentMainRunnerImpl::Run at content/app/content_main_runner_impl.cc:1171] 15 0x7fff51ed9cfa [msedge!content::RunContentProcess at content/app/content_main.cc:419] 16 0x7fff51ed8fda [msedge!content::ContentMain at content/app/content_main.cc:432] 17 0x7fff51ed8969 [msedge!ChromeMain at chrome/app/chrome_main.cc:340] 18 0x7ff635e17ce6 [msedge_exe!MainDllLoader::Launch at chrome/app/main_dll_loader_win.cc:241] 19 0x7ff635e15597 [msedge_exe!wWinMain at chrome/app/chrome_exe_main_win.cc:804] 20 0x7ff635ef94c2 [msedge_exe!__scrt_common_main_seh at vctools/crt/vcstartup/src/startup/exe_common.inl:288] 21 0x7fffd8eb259d [kernel32!BaseThreadInitThunk at clientcore/base/win32/client/thread.c:75] 22 0x7fffda7eaf58 [ntdll!RtlUserThreadStart at minkernel/ntdll/rtlstrt.c:1166]
Posted from:
msedge!mirroring::OpenscreenSessionHost::StartCapturingAudio+0x7e (00007fff5e6de894) [D:\a\_work\e\src\components\mirroring\service\openscreen_session_host.cc @ 1126] task backtrace: [1] msedge!media::AliveChecker::Start+0x85 (00007fff56a38de1) [D:\a_work\e\src\media\audio\alive_checker.cc @ 97]
[2] msedge!media::AliveChecker::Start+0x85 (00007fff56a38de1) [D:\a\_work\e\src\media\audio\alive_checker.cc @ 97] [3] msedge!media::AliveChecker::Start+0x85 (00007fff56a38de1) [D:\a_work\e\src\media\audio\alive_checker.cc @ 97]
[4] msedge!mojo::core::ipcz_driver::MojoTrap::TrapEventHandler+0x6ae (00007fff`548a172e) [D:\a_work\e\src\mojo\core\ipcz_driver\mojo_trap.cc @ 400]
@$task_trace()
The task was posted from msedge!mirroring::OpenscreenSessionHost::StartCapturingAudio
audio_capturing_callback_ = std::make_unique<AudioCapturingCallback>( base::BindPostTaskToCurrentDefault(base::BindRepeating( &AudioRtpStream::InsertAudio, audio_stream_->AsWeakPtr())), base::BindPostTaskToCurrentDefault(base::BindOnce( &OpenscreenSessionHost::ReportAndLogError, weak_factory_.GetWeakPtr(), SessionError::AUDIO_CAPTURE_ERROR)), observer_);
Based on the allocation and deallocation stack the error_message is destructed which is being passed as a string_view to .
void OnCaptureError(media::AudioCapturerSource::ErrorCode code, const std::string& message) override { std::string error_message = base::StrCat( {“AudioCaptureError occurred, code: “, base::NumberToString(static_cast<int>(code)), “, message: “, message}); if (!error_callback_.is_null()) { std::move(error_callback_).Run(error_message); } }
The error_message is passed as a string_view to ReportAndLogError as message which is already destructed.
0:000> dq 0x000006ec00e5efa0 ——–> message
000006ec00e5efa0 ???????????????? ???????????????? 000006ec00e5efb0 ???????????????? ????????????????
000006ec00e5efc0 ???????????????? ???????????????? 000006ec00e5efd0 ???????????????? ????????????????
000006ec00e5efe0 ???????????????? ???????????????? 000006ec00e5eff0 ???????????????? ????????????????
000006ec00e5f000 ???????????????? ???????????????? 000006ec00e5f010 ???????????????? ????????????????
0:000> dq 0x000006ec022f1900 —–> OpenscreenSessionHost
000006ec022f1900 00007fff5fad7df0 00007fff5fad7e10 000006ec022f1910 00007fff5fad7e30 1264a8c000000002
000006ec022f1920 00000000007fff55 0000000400000000 000006ec022f1930 0032746f6f74686b 0000000000000000
000006ec022f1940 0700000000000000 000006ec0220a670 000006ec022f1950 0000000000000024 8000000000000028
000006ec022f1960 312d7265646e6573 0000003130343335 000006ec022f1970 0d00000000000000 00000000ffffff00
void OpenscreenSessionHost::ReportAndLogError(SessionError error, std::string_view message) { base::UmaHistogramEnumeration(“MediaRouter.MirroringService.SessionError”, error); logger_.LogError(error, message);
This could be caused if the error_callback_ was posted on a different thread due to the usage of BindPostTaskToCurrentDefault
VERSION Chrome Version: M137 Operating System: Windows
REPRODUCTION CASE This is a GWP-ASan bug. Attached the details above.
FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION Type of crash: [tab, browser, etc.] Crash State: [see link above: stack trace with symbols, registers, exception record] Client ID (if relevant): [see link above]
CREDIT INFORMATION Externally reported security bugs may appear in Chrome release notes. If this bug is included, how would you like to be credited? Reporter credit: Fayez