Closed Bug 1722083 (CVE-2021-29985) Opened 1 year ago Closed 1 year ago

TALOS-2021-1345 - Mozilla Firefox MediaCacheStream::NotifyDataReceived use-after-free vulnerability

Categories

(Core :: Audio/Video: Playback, defect, P2)

Firefox 90
defect

Tracking

()

RESOLVED FIXED
92 Branch
Tracking Status
firefox-esr78 91+ fixed
firefox-esr91 91+ fixed
firefox90 --- wontfix
firefox91 + fixed
firefox92 + fixed

People

(Reporter: vulndiscovery, Assigned: alwu)

Details

(Keywords: csectype-uaf, sec-moderate, Whiteboard: [adv-main91+][adv-esr78.13+])

Attachments

(4 files, 2 obsolete files)

Attached file UAF_StreamBuffering.zip (obsolete) —

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0

Steps to reproduce:

None (published patch date)
TALOS-2021-1345

Mozilla Firefox MediaCacheStream::NotifyDataReceived use-after-free vulnerability

Summary

An potential remote code execution vulnerability exists in the MediaCacheStream::NotifyDataReceived method of Mozilla Firefox 89.0.3 x64. A specially crafted web page can cause a use-after-free vulnerability potentially resulting in a code execution. A victim needs to visit a malicious webpage to trigger this vulnerability.

Tested Versions

Mozilla Firefox Mozilla Firefox 89.0.3 x64

Product URLs

https://www.mozilla.org/en-US/firefox/new

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-416 - Use After Free

Details

Mozilla Firefox is one of the most popular web browsers on the world available for a variety of the different platforms : Windows, Linux, OSX, Android and more. Its active development ensure support for the newest web technologies like HTML5 or CSS3.

This vulnerability is related with the nsBufferedStream component which is part of the Stream buffering functionality.
A malicious web page can lead to a race condition situation which can cause a use-after-free vulnerability and potential remote code execution.

Tracking an nsBufferedStream object life cycle we can notice that there is an allocation made :

previously allocated by thread T0 (Web Content) here:
	#0 0x55eb6b69ca7d in malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
	#1 0x7f031b4f9e2e in operator new[] /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:47:10
	#2 0x7f031b4f9e2e in nsBufferedStream::Init(nsISupports*, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:73:13
	#3 0x7f031b4fc05c in nsBufferedInputStream::Init(nsIInputStream*, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:335:35
	#4 0x7f031b5303ba in NS_NewBufferedInputStream(nsIInputStream**, already_AddRefed<nsIInputStream>, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsNetUtil.cpp:1330:14
	#5 0x7f031b52c483 in nsInputStreamPump::CreateBufferedStreamIfNeeded() /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:672:17
	#6 0x7f031b52c0c8 in nsInputStreamPump::PeekStream(void (*)(void*, unsigned char const*, unsigned int), void*) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:94:17
	#7 0x7f031b4ed088 in nsBaseChannel::OnStartRequest(nsIRequest*) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp:827:14
	#8 0x7f031b52ec0e in nsInputStreamPump::OnStateStart() /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:481:21
	#9 0x7f031b52e337 in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:390:21
	#10 0x7f03208e4d63 in mozilla::dom::BlobURLInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/dom/file/uri/BlobURLInputStream.cpp:271:20
	#11 0x7f03208d8f84 in mozilla::(anonymous namespace)::InputStreamCallbackRunnable::Run() /builds/worker/checkouts/gecko/dom/file/ipc/RemoteLazyInputStream.cpp:54:16
	#12 0x7f031b2439cc in mozilla::SchedulerGroup::Runnable::Run() /builds/worker/checkouts/gecko/xpcom/threads/SchedulerGroup.cpp:143:20
	#13 0x7f031b24d16a in mozilla::RunnableTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:473:16
	#14 0x7f031b24a4f8 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:757:26
	#15 0x7f031b248837 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:612:15
	#16 0x7f031b248c8d in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:396:36
	#17 0x7f031b253471 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:135:37
	#18 0x7f031b253471 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_3>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:534:5
	#19 0x7f031b26cb31 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1155:16
	#20 0x7f031b27649c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:548:10
	#21 0x7f031c44968f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:87:21

Which is caused by a call to URL.createObjectURL inside the MediaRecorder_onstop event handler:

Line 1	function MediaRecorder_onstop(e)
Line 2	{
Line 3		let blob = new Blob(chunks,{ 'type' : 'audio/ogg; codecs=opus' });
Line 4		audioElement.src = URL.createObjectURL(blob);
Line 5		audioElement.play(); 
Line 6	}	

Further this nsBufferedStream object gets deallocated:

0x62100323e900 is located 0 bytes inside of 4096-byte region [0x62100323e900,0x62100323f900)
freed by thread T0 (Web Content) here:
	#0 0x55eb6b69c7fd in free /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:123:3
	#1 0x7f031b4f9bbd in operator delete[] /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:60:10
	#2 0x7f031b4f9bbd in nsBufferedStream::Close() /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:84:5
	#3 0x7f031b4fec52 in Close /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:391:21
	#4 0x7f031b4fec52 in CloseWithStatus /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:671:67
	#5 0x7f031b4fec52 in non-virtual thunk to nsBufferedInputStream::CloseWithStatus(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp
	#6 0x7f031b52d41d in nsInputStreamPump::Cancel(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:210:19
	#7 0x7f031b4e9618 in nsBaseChannel::Cancel(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp:399:15
	#8 0x7f031b4e968c in non-virtual thunk to nsBaseChannel::Cancel(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp
	#9 0x7f0320bec2bd in mozilla::ChannelMediaResource::CloseChannel() /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:631:15
	#10 0x7f0320befe92 in mozilla::ChannelMediaResource::Close() /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:575:5
	#11 0x7f0320be55ef in mozilla::ChannelMediaDecoder::Shutdown() /builds/worker/checkouts/gecko/dom/media/ChannelMediaDecoder.cpp:224:40
	#12 0x7f0320a2d7c0 in mozilla::dom::HTMLMediaElement::ShutdownDecoder() /builds/worker/checkouts/gecko/dom/html/HTMLMediaElement.cpp:2206:13
	#13 0x7f0320a4ba06 in mozilla::dom::HTMLMediaElement::~HTMLMediaElement() /builds/worker/checkouts/gecko/dom/html/HTMLMediaElement.cpp:4208:5
	#14 0x7f032097ca0d in mozilla::dom::HTMLAudioElement::~HTMLAudioElement() /builds/worker/checkouts/gecko/dom/html/HTMLAudioElement.cpp:58:1
	#15 0x7f031e5e92fd in nsIContent::Destroy() /builds/worker/checkouts/gecko/dom/base/FragmentOrElement.cpp:150:1
	#16 0x7f031b0bef72 in SnowWhiteKiller::~SnowWhiteKiller() /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2417:7
	#17 0x7f031b0bd73b in nsPurpleBuffer::RemoveSkippable(nsCycleCollector*, js::SliceBudget&, bool, bool, void (*)()) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2585:1
	#18 0x7f031b0bf79f in nsCycleCollector::ForgetSkippable(js::SliceBudget&, bool, bool) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2653:14
	#19 0x7f031b0c7f6d in nsCycleCollector_forgetSkippable(js::SliceBudget&, bool, bool) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3865:21
	#20 0x7f031e816e79 in FireForgetSkippable(bool, mozilla::TimeStamp) /builds/worker/checkouts/gecko/dom/base/nsJSEnvironment.cpp:1141:3
	#21 0x7f031e81831c in CCRunnerFired(mozilla::TimeStamp) /builds/worker/checkouts/gecko/dom/base/nsJSEnvironment.cpp:1644:9
	#22 0x7f031b2364ea in operator() /builds/worker/fetches/clang/bin/../lib/gcc/x86_64-unknown-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/std_function.h:706:14
	#23 0x7f031b2364ea in mozilla::IdleTaskRunner::Run() /builds/worker/checkouts/gecko/xpcom/threads/IdleTaskRunner.cpp:109:14

Notice that nsBufferedStream gets deallocated through the HTMLAudioElement element destruction (audioElement in our code) which might by triggered by one of our fuzzing fuctions or "page switch/reload".

Because of bad referencing handling the nsBufferedStream object gets reused during the mozilla::MediaCacheStream::NotifyDataReceived method call:

==54405==ERROR: AddressSanitizer: heap-use-after-free on address 0x62100323e900 at pc 0x55eb6b69bed7 bp 0x7f03072b6a70 sp 0x7f03072b6238
READ of size 4096 at 0x62100323e900 thread T22 (MediaCache)
	#0 0x55eb6b69bed6 in __asan_memcpy /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3
	#1 0x7f0320c6d37c in mozilla::MediaCacheStream::NotifyDataReceived(unsigned int, unsigned int, unsigned char const*) /builds/worker/checkouts/gecko/dom/media/MediaCache.cpp:2027:7
	#2 0x7f0320bee366 in mozilla::ChannelMediaResource::CopySegmentToCache(nsIInputStream*, void*, char const*, unsigned int, unsigned int, unsigned int*) /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:409:18
	#3 0x7f031b4fd0ae in nsBufferedInputStream::ReadSegments(nsresult (*)(nsIInputStream*, void*, char const*, unsigned int, unsigned int, unsigned int*), void*, unsigned int, unsigned int*) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:453:12
	#4 0x7f0320bebad5 in OnDataAvailable /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:437:18
	#5 0x7f0320bebad5 in mozilla::ChannelMediaResource::Listener::OnDataAvailable(nsIRequest*, nsIInputStream*, unsigned long, unsigned int) /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:84:21
	#6 0x7f031b4ee028 in nsBaseChannel::OnDataAvailable(nsIRequest*, nsIInputStream*, unsigned long, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp:872:28
	#7 0x7f031b52f2fb in nsInputStreamPump::OnStateTransfer() /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:548:23
	#8 0x7f031b52e347 in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:393:21
	#9 0x7f031b4ff23b in nsBufferedInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:724:20
	#10 0x7f03208e4d63 in mozilla::dom::BlobURLInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/dom/file/uri/BlobURLInputStream.cpp:271:20
	#11 0x7f03208d8f84 in mozilla::(anonymous namespace)::InputStreamCallbackRunnable::Run() /builds/worker/checkouts/gecko/dom/file/ipc/RemoteLazyInputStream.cpp:54:16
	#12 0x7f031b26d379 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1149:16
	#13 0x7f031b27649c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:548:10
	#14 0x7f031c44ac0a in mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:302:20
	#15 0x7f031c35ff11 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:335:10
	#16 0x7f031c35ff11 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:328:3
	#17 0x7f031c35ff11 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:310:3
	#18 0x7f031b267c59 in nsThread::ThreadFunc(void*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:391:10
	#19 0x7f03373bb28e in _pt_root /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:201:5
	#20 0x7f033acc158f in start_thread nptl/pthread_create.c:463:8
	#21 0x7f033a889222 in clone misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Proper heap grooming can give an attacker full control of this use-after-free vulnerability and as a result could allow it to be turned into arbitrary code execution.

Crash Information

[ 4:29:44 AM ] :: AudioBufferSourceNode_handler
[ 4:29:44 AM ] :: MediaStreamAudioDestinationNode_handler
[ 4:29:44 AM ] :: Before setTimeout
[ 4:29:44 AM ] :: SEED g_mainRandom: 2102332452
[ 4:29:45 AM ] :: Its fuzzing time!!!!
[ 4:29:45 AM ] :: SEED : g_fuzzRandom : 146570576
[ 4:29:45 AM ] :: [fuzz_nodes] :: Amount of mutation : 1
[ 4:29:45 AM ] :: Chosen function : fuzz_deleteHTMLElement
[ 4:29:45 AM ] :: ()=>{ document.querySelector("audio").src = document.querySelector("audio").src; }
[ 4:29:46 AM ] :: MediaRecorder_ondataavailable
[ 4:29:46 AM ] :: Its fuzzing time!!!!
[ 4:29:46 AM ] :: SEED : g_fuzzRandom : 650240019
[ 4:29:46 AM ] :: [fuzz_nodes] :: Amount of mutation : 1
[ 4:29:46 AM ] :: Chosen function : fuzz_spin
[ 4:29:46 AM ] :: MediaRecorder_ondataavailable
[ 4:29:46 AM ] :: Its fuzzing time!!!!
[ 4:29:46 AM ] :: SEED : g_fuzzRandom : 1849907680
[ 4:29:46 AM ] :: [fuzz_nodes] :: Amount of mutation : 1
[ 4:29:46 AM ] :: Chosen function : fuzz_deleteHTMLElement
[ 4:29:46 AM ] :: ()=>{ document.body.removeChild(document.querySelector("audio")) }
[ 4:29:46 AM ] :: MediaRecorder_onstop
[ 4:29:46 AM ] :: Its fuzzing time!!!!
[ 4:29:46 AM ] :: SEED : g_fuzzRandom : 1240099704
[ 4:29:46 AM ] :: [fuzz_nodes] :: Amount of mutation : 3
[ 4:29:46 AM ] :: Chosen function : fuzz_deleteRandomNode
[ 4:29:46 AM ] :: Deleting object : AudioBufferSourceNode
[ 4:29:46 AM ] :: Chosen function : fuzz_spin
[ 4:29:46 AM ] :: eventhandler5
[ 4:29:46 AM ] :: [5] Caller name : fuzz_spin
[ 4:29:46 AM ] :: [object Event]
[ 4:29:46 AM ] :: ended
[ 4:29:47 AM ] :: Chosen function : fuzz_deleteHTMLElement
[ 4:29:47 AM ] :: ()=>{ document.querySelector("audio").src = randStr(); }
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: [object AnimationPlaybackEvent]
[ 4:29:47 AM ] :: finish
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: [object AnimationPlaybackEvent]
[ 4:29:47 AM ] :: finish
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: [object AnimationPlaybackEvent]
[ 4:29:47 AM ] :: finish
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: [object AnimationPlaybackEvent]
[ 4:29:47 AM ] :: finish
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: [object AnimationPlaybackEvent]
[ 4:29:47 AM ] :: finish
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: [object AnimationPlaybackEvent]
[ 4:29:47 AM ] :: finish
[ 4:29:47 AM ] :: eventhandler5
[ 4:29:47 AM ] :: [object AnimationPlaybackEvent]
[ 4:29:47 AM ] :: finish
[ 4:29:47 AM ] :: eventhandler2
[ 4:29:47 AM ] :: [object IntersectionObserverEntry]
[ 4:29:47 AM ] :: undefined
[ 4:29:47 AM ] :: eventhandler2

(....)

==54405==ERROR: AddressSanitizer: heap-use-after-free on address 0x62100323e900 at pc 0x55eb6b69bed7 bp 0x7f03072b6a70 sp 0x7f03072b6238
READ of size 4096 at 0x62100323e900 thread T22 (MediaCache)
	#0 0x55eb6b69bed6 in __asan_memcpy /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3
	#1 0x7f0320c6d37c in mozilla::MediaCacheStream::NotifyDataReceived(unsigned int, unsigned int, unsigned char const*) /builds/worker/checkouts/gecko/dom/media/MediaCache.cpp:2027:7
	#2 0x7f0320bee366 in mozilla::ChannelMediaResource::CopySegmentToCache(nsIInputStream*, void*, char const*, unsigned int, unsigned int, unsigned int*) /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:409:18
	#3 0x7f031b4fd0ae in nsBufferedInputStream::ReadSegments(nsresult (*)(nsIInputStream*, void*, char const*, unsigned int, unsigned int, unsigned int*), void*, unsigned int, unsigned int*) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:453:12
	#4 0x7f0320bebad5 in OnDataAvailable /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:437:18
	#5 0x7f0320bebad5 in mozilla::ChannelMediaResource::Listener::OnDataAvailable(nsIRequest*, nsIInputStream*, unsigned long, unsigned int) /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:84:21
	#6 0x7f031b4ee028 in nsBaseChannel::OnDataAvailable(nsIRequest*, nsIInputStream*, unsigned long, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp:872:28
	#7 0x7f031b52f2fb in nsInputStreamPump::OnStateTransfer() /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:548:23
	#8 0x7f031b52e347 in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:393:21
	#9 0x7f031b4ff23b in nsBufferedInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:724:20
	#10 0x7f03208e4d63 in mozilla::dom::BlobURLInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/dom/file/uri/BlobURLInputStream.cpp:271:20
	#11 0x7f03208d8f84 in mozilla::(anonymous namespace)::InputStreamCallbackRunnable::Run() /builds/worker/checkouts/gecko/dom/file/ipc/RemoteLazyInputStream.cpp:54:16
	#12 0x7f031b26d379 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1149:16
	#13 0x7f031b27649c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:548:10
	#14 0x7f031c44ac0a in mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:302:20
	#15 0x7f031c35ff11 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:335:10
	#16 0x7f031c35ff11 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:328:3
	#17 0x7f031c35ff11 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:310:3
	#18 0x7f031b267c59 in nsThread::ThreadFunc(void*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:391:10
	#19 0x7f03373bb28e in _pt_root /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:201:5
	#20 0x7f033acc158f in start_thread nptl/pthread_create.c:463:8
	#21 0x7f033a889222 in clone misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

0x62100323e900 is located 0 bytes inside of 4096-byte region [0x62100323e900,0x62100323f900)
freed by thread T0 (Web Content) here:
	#0 0x55eb6b69c7fd in free /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:123:3
	#1 0x7f031b4f9bbd in operator delete[] /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:60:10
	#2 0x7f031b4f9bbd in nsBufferedStream::Close() /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:84:5
	#3 0x7f031b4fec52 in Close /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:391:21
	#4 0x7f031b4fec52 in CloseWithStatus /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:671:67
	#5 0x7f031b4fec52 in non-virtual thunk to nsBufferedInputStream::CloseWithStatus(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp
	#6 0x7f031b52d41d in nsInputStreamPump::Cancel(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:210:19
	#7 0x7f031b4e9618 in nsBaseChannel::Cancel(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp:399:15
	#8 0x7f031b4e968c in non-virtual thunk to nsBaseChannel::Cancel(nsresult) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp
	#9 0x7f0320bec2bd in mozilla::ChannelMediaResource::CloseChannel() /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:631:15
	#10 0x7f0320befe92 in mozilla::ChannelMediaResource::Close() /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:575:5
	#11 0x7f0320be55ef in mozilla::ChannelMediaDecoder::Shutdown() /builds/worker/checkouts/gecko/dom/media/ChannelMediaDecoder.cpp:224:40
	#12 0x7f0320a2d7c0 in mozilla::dom::HTMLMediaElement::ShutdownDecoder() /builds/worker/checkouts/gecko/dom/html/HTMLMediaElement.cpp:2206:13
	#13 0x7f0320a4ba06 in mozilla::dom::HTMLMediaElement::~HTMLMediaElement() /builds/worker/checkouts/gecko/dom/html/HTMLMediaElement.cpp:4208:5
	#14 0x7f032097ca0d in mozilla::dom::HTMLAudioElement::~HTMLAudioElement() /builds/worker/checkouts/gecko/dom/html/HTMLAudioElement.cpp:58:1
	#15 0x7f031e5e92fd in nsIContent::Destroy() /builds/worker/checkouts/gecko/dom/base/FragmentOrElement.cpp:150:1
	#16 0x7f031b0bef72 in SnowWhiteKiller::~SnowWhiteKiller() /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2417:7
	#17 0x7f031b0bd73b in nsPurpleBuffer::RemoveSkippable(nsCycleCollector*, js::SliceBudget&, bool, bool, void (*)()) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2585:1
	#18 0x7f031b0bf79f in nsCycleCollector::ForgetSkippable(js::SliceBudget&, bool, bool) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2653:14
	#19 0x7f031b0c7f6d in nsCycleCollector_forgetSkippable(js::SliceBudget&, bool, bool) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3865:21
	#20 0x7f031e816e79 in FireForgetSkippable(bool, mozilla::TimeStamp) /builds/worker/checkouts/gecko/dom/base/nsJSEnvironment.cpp:1141:3
	#21 0x7f031e81831c in CCRunnerFired(mozilla::TimeStamp) /builds/worker/checkouts/gecko/dom/base/nsJSEnvironment.cpp:1644:9
	#22 0x7f031b2364ea in operator() /builds/worker/fetches/clang/bin/../lib/gcc/x86_64-unknown-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/std_function.h:706:14
	#23 0x7f031b2364ea in mozilla::IdleTaskRunner::Run() /builds/worker/checkouts/gecko/xpcom/threads/IdleTaskRunner.cpp:109:14

previously allocated by thread T0 (Web Content) here:
	#0 0x55eb6b69ca7d in malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
	#1 0x7f031b4f9e2e in operator new[] /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:47:10
	#2 0x7f031b4f9e2e in nsBufferedStream::Init(nsISupports*, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:73:13
	#3 0x7f031b4fc05c in nsBufferedInputStream::Init(nsIInputStream*, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:335:35
	#4 0x7f031b5303ba in NS_NewBufferedInputStream(nsIInputStream**, already_AddRefed<nsIInputStream>, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsNetUtil.cpp:1330:14
	#5 0x7f031b52c483 in nsInputStreamPump::CreateBufferedStreamIfNeeded() /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:672:17
	#6 0x7f031b52c0c8 in nsInputStreamPump::PeekStream(void (*)(void*, unsigned char const*, unsigned int), void*) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:94:17
	#7 0x7f031b4ed088 in nsBaseChannel::OnStartRequest(nsIRequest*) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp:827:14
	#8 0x7f031b52ec0e in nsInputStreamPump::OnStateStart() /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:481:21
	#9 0x7f031b52e337 in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:390:21
	#10 0x7f03208e4d63 in mozilla::dom::BlobURLInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/dom/file/uri/BlobURLInputStream.cpp:271:20
	#11 0x7f03208d8f84 in mozilla::(anonymous namespace)::InputStreamCallbackRunnable::Run() /builds/worker/checkouts/gecko/dom/file/ipc/RemoteLazyInputStream.cpp:54:16
	#12 0x7f031b2439cc in mozilla::SchedulerGroup::Runnable::Run() /builds/worker/checkouts/gecko/xpcom/threads/SchedulerGroup.cpp:143:20
	#13 0x7f031b24d16a in mozilla::RunnableTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:473:16
	#14 0x7f031b24a4f8 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:757:26
	#15 0x7f031b248837 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:612:15
	#16 0x7f031b248c8d in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:396:36
	#17 0x7f031b253471 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:135:37
	#18 0x7f031b253471 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_3>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:534:5
	#19 0x7f031b26cb31 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1155:16
	#20 0x7f031b27649c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:548:10
	#21 0x7f031c44968f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:87:21

Thread T22 (MediaCache) created by T0 (Web Content) here:
	#0 0x55eb6b6874ea in pthread_create /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cpp:214:3
	#1 0x7f03373ab5b4 in _PR_CreateThread /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:458:14
	#2 0x7f033739c66e in PR_CreateThread /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:533:12
	#3 0x7f031b26a09c in nsThread::Init(nsTSubstring<char> const&) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:609:18
	#4 0x7f031b2741b8 in nsThreadManager::NewNamedThread(nsTSubstring<char> const&, unsigned int, nsIThread**) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadManager.cpp:555:12
	#5 0x7f031b27e421 in NS_NewNamedThread(nsTSubstring<char> const&, nsIThread**, already_AddRefed<nsIRunnable>, unsigned int) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:169:57
	#6 0x7f0320c6181d in NS_NewNamedThread<11> /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:85:10
	#7 0x7f0320c6181d in mozilla::MediaCache::GetMediaCache(long, bool) /builds/worker/checkouts/gecko/dom/media/MediaCache.cpp:761:19
	#8 0x7f0320c738a0 in mozilla::MediaCacheStream::Init(long) /builds/worker/checkouts/gecko/dom/media/MediaCache.cpp:2675:17
	#9 0x7f0320bef521 in mozilla::ChannelMediaResource::Open(nsIStreamListener**) /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:500:30
	#10 0x7f0320be5fac in mozilla::ChannelMediaDecoder::Load(nsIChannel*, bool, nsIStreamListener**) /builds/worker/checkouts/gecko/dom/media/ChannelMediaDecoder.cpp:260:19
	#11 0x7f0320a526cb in nsresult mozilla::dom::HTMLMediaElement::SetupDecoder<mozilla::ChannelMediaDecoder, nsIChannel*&, bool&, nsIStreamListener**&>(mozilla::ChannelMediaDecoder*, nsIChannel*&, bool&, nsIStreamListener**&) /builds/worker/checkouts/gecko/dom/html/HTMLMediaElement.cpp:4844:27
	#12 0x7f0320a264cd in mozilla::dom::HTMLMediaElement::InitializeDecoderForChannel(nsIChannel*, nsIStreamListener**) /builds/worker/checkouts/gecko/dom/html/HTMLMediaElement.cpp:4927:10
	#13 0x7f0320a249ab in mozilla::dom::HTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest*) /builds/worker/checkouts/gecko/dom/html/HTMLMediaElement.cpp:1320:7
	#14 0x7f031be4e996 in mozilla::net::HttpChannelChild::DoOnStartRequest(nsIRequest*, nsISupports*) /builds/worker/checkouts/gecko/netwerk/protocol/http/HttpChannelChild.cpp:594:20
	#15 0x7f031be4d89f in mozilla::net::HttpChannelChild::OnStartRequest(mozilla::net::nsHttpResponseHead const&, bool const&, mozilla::net::nsHttpHeaderArray const&, mozilla::net::HttpChannelOnStartRequestArgs const&) /builds/worker/checkouts/gecko/netwerk/protocol/http/HttpChannelChild.cpp:525:3
	#16 0x7f031c136cd5 in mozilla::net::ChannelEventQueue::FlushQueue() /builds/worker/checkouts/gecko/netwerk/ipc/ChannelEventQueue.cpp:90:12
	#17 0x7f031c183537 in mozilla::net::ChannelEventQueue::ResumeInternal()::CompleteResumeRunnable::Run() /builds/worker/checkouts/gecko/netwerk/ipc/ChannelEventQueue.cpp:148:17
	#18 0x7f031b2439cc in mozilla::SchedulerGroup::Runnable::Run() /builds/worker/checkouts/gecko/xpcom/threads/SchedulerGroup.cpp:143:20
	#19 0x7f031b24d16a in mozilla::RunnableTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:473:16
	#20 0x7f031b24a4f8 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:757:26
	#21 0x7f031b248837 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:612:15
	#22 0x7f031b248c8d in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:396:36
	#23 0x7f031b2534a4 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:138:37
	#24 0x7f031b2534a4 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_4>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:534:5
	#25 0x7f031b26cb31 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1155:16
	#26 0x7f031b27649c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:548:10
	#27 0x7f031c449684 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:109:5
	#28 0x7f031c35ff11 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:335:10
	#29 0x7f031c35ff11 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:328:3
	#30 0x7f031c35ff11 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:310:3
	#31 0x7f0322781f37 in nsBaseAppShell::Run() /builds/worker/checkouts/gecko/widget/nsBaseAppShell.cpp:137:27
	#32 0x7f0326145f4f in XRE_RunAppShell() /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:906:20
	#33 0x7f031c35ff11 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:335:10
	#34 0x7f031c35ff11 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:328:3
	#35 0x7f031c35ff11 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:310:3
	#36 0x7f0326145813 in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:738:34
	#37 0x55eb6b6cf24d in content_process_main(mozilla::Bootstrap*, int, char**) /builds/worker/checkouts/gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
	#38 0x55eb6b6cf671 in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:309:18
	#39 0x7f033a798cb1 in __libc_start_main csu/../csu/libc-start.c:314:16

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c428063fcd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c428063fce0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c428063fcf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c428063fd00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c428063fd10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c428063fd20:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c428063fd30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c428063fd40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c428063fd50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c428063fd60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c428063fd70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==54405==ABORTING

Exploit Proof of Concept

Execute server.py script and navigate with Firefox to pointed url.

Credit

Discovered by Marcin 'Icewall' Noga of Cisco Talos.

https://talosintelligence.com/vulnerability_reports/

Timeline

None - Vendor Disclosure
None - Public Release

Actual results:

See report

Expected results:

See report

Group: firefox-core-security → media-core-security
Component: Untriaged → Audio/Video: Playback
Keywords: csectype-uaf
Product: Firefox → Core

I'm trying to repro this no luck so far.

My current steps trying to recreate:

  • Create a virutalenironment for python2 and install flask and requests
  • Run the proof on concept's server.py in the venv
  • Build a --fuzzing-enalbed + ASAN Firefox build
  • Enable autoplay for audio and video in the Fx build
  • Set the fuzzing.enabled pref to true
  • Load the proof of concept

I've also tried to repro with the window.dump(format); line commented out, to see if reducing log spam helped, but it doesn't seem to.

Reporter, do you have any further suggestions for reproing this?

Flags: needinfo?(vulndiscovery)

Sylvestre, is there a fuzzing person who might be able to help Bryce figure out how to reproduce this issue? It looks like it involves web audio stuff. Thanks.

Flags: needinfo?(sledru)

I'm going to be out for the remainder of this week, but will grab this again when I return. :alwu from the media team is also familiar with this domain and is cced on this bug should anything come up while I'm out.

Assignee: nobody → bvandyk
Severity: -- → S2
Priority: -- → P2

I am also unable to reproduce the issue with the attached test case. I tested with the most recent ASan fuzzing build (m-c 20210726-0c272222c17b).

Qs for reporter:

  • Are you able to reproduce the issue on the latest mozilla-central build (report says FF 89.0.3)?
  • Was a custom prefs.js file used?
  • Is the issue consistently reproducible, if not how frequently is the issue triggered by the test case?
  • How long does it typically take to trigger the issue with the attached test case?
Flags: needinfo?(sledru)

Hi Tyler,

We have uploaded a revised poc, hopefully you are able to trigger it now. it can take a while to trigger since it's a race condition, in our runs sometimes it took 10 minutes, but it has also taken 3h and 8h to trigger. We also retested on the nightly from yesterday July 27th and it still triggers. There's more information in the README.MD in the new archive.

The prefs file was obtained via https://github.com/MozillaSecurity/prefpicker

Yves

Attachment #9232904 - Attachment is obsolete: true
Flags: needinfo?(vulndiscovery)

(In reply to Cisco Talos from comment #6)

Created attachment 9233516 [details]
UAF_StreamBuffering_final.zip

Hi Tyler,

I mean Tyson!

I haven't reproduced the UAF yet but I did see this:

/builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:434:27: runtime error: applying non-zero offset 4096 to null pointer
    #0 0x7f226468d7f9 in nsBufferedInputStream::ReadSegments(nsresult (*)(nsIInputStream*, void*, char const*, unsigned int, unsigned int, unsigned int*), void*, unsigned int, unsigned int*) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:434:27
    #1 0x7f226a057165 in OnDataAvailable /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:437:18
    #2 0x7f226a057165 in mozilla::ChannelMediaResource::Listener::OnDataAvailable(nsIRequest*, nsIInputStream*, unsigned long, unsigned int) /builds/worker/checkouts/gecko/dom/media/ChannelMediaResource.cpp:84:21
    #3 0x7f226467cf0f in nsBaseChannel::OnDataAvailable(nsIRequest*, nsIInputStream*, unsigned long, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsBaseChannel.cpp:862:28
    #4 0x7f22646bf71e in nsInputStreamPump::OnStateTransfer() /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:532:23
    #5 0x7f22646be787 in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsInputStreamPump.cpp:377:21
    #6 0x7f226468f692 in nsBufferedInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/netwerk/base/nsBufferedStreams.cpp:704:20
    #7 0x7f2269d350a3 in mozilla::dom::BlobURLInputStream::OnInputStreamReady(nsIAsyncInputStream*) /builds/worker/checkouts/gecko/dom/file/uri/BlobURLInputStream.cpp:271:20
    #8 0x7f2269d28ce4 in mozilla::(anonymous namespace)::InputStreamCallbackRunnable::Run() /builds/worker/checkouts/gecko/dom/file/ipc/RemoteLazyInputStream.cpp:54:16
    #9 0x7f22643c796b in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1142:16
    #10 0x7f22643d1e0c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:466:10
    #11 0x7f22655f751a in mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:300:20
    #12 0x7f22654e0931 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:331:10
    #13 0x7f22654e0931 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:324:3
    #14 0x7f22654e0931 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:306:3
    #15 0x7f22643c1418 in nsThread::ThreadFunc(void*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:390:10
    #16 0x7f228d8f53fe in _pt_root /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:201:5
    #17 0x7f228d5306da in start_thread /build/glibc-S9d2JN/glibc-2.27/nptl/pthread_create.c:463
    #18 0x7f228c50e71e in clone /build/glibc-S9d2JN/glibc-2.27/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Given the difficulty of triggering the issue, I'm going to clear the sec rating for now. Maybe we can reassess once the underlying issue has been figured out some more.

Keywords: sec-high

I had no luck to reproduce that either, but I have a patch which might solve this issue. Would any of you mind to download this (find target.zip that under Artifacts, then you can find Firefox.exe after unzip the file) and see if that helps or not?
Thank you so much.

Flags: needinfo?(vulndiscovery)
Flags: needinfo?(twsmith)

Alastor, do you have a Linux build? We've been testing on Linux

Flags: needinfo?(vulndiscovery) → needinfo?(alwu)

To be specific we will need a Linux fuzzing-asan-opt build to test.

Flags: needinfo?(twsmith)

Ah sorry I used Windows build because I saw the user agent mentioned in the first comment was Windows. Here is the linux-fuzzy-asan-opt task, thank you so much.

Flags: needinfo?(alwu) → needinfo?(vulndiscovery)

With the build provided by :alwu I was only able to trigger OOMs. I was unable to reproduce the issue I was previously seeing. I'm not sure how helpful that is since I was never able to reproduce the original issue.

I will leave it to the reporter to verify.

The issue no longer triggers for us on Alastor's build.

Flags: needinfo?(vulndiscovery)

Assigning to Alastor as he has a patch to mitigate.

Assignee: bvandyk → alwu

It looks like this landed without a security rating or approval?

Flags: needinfo?(alwu)
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true

Base on this guideline, this bug doesn't have sec-* rating which seems being able to land that directly without an sec-approval. Rating was sec-high initially and was removed in comment 9 due to the difficulty of reproducing the issue, and I would consider this one as a sec-low or something.

Flags: needinfo?(alwu)

The guideline says "For security bugs with no sec- severity rating assume the worst and follow the rules for sec-critical". That's probably overkill in this case, but it is better to wait for a rating.

I'll mark it sec-moderate given that we have been unable to reproduce it, and it sounds like even for the reporter it isn't too easy to reproduce which mitigates the severity.

Keywords: sec-moderate

Sorry for causing this situation, I will wait for someone adding sec-rating next time before landing patch. Just discussed with Ryan offline and he think backout the patch doesn't help because it's also exposed to the public. And just for safe (based on the discussion by Ryan and sec-team), we decided to uplift this to release/esr91/esr78 as well and I will fill the request form for that.

Comment on attachment 9234720 [details]
Bug 1722083 - revoke the listener first.

Beta/Release Uplift Approval Request

  • User impact if declined: Malicious sites might be able to expolit the vulnerability to excute some bad program on users' computer.
  • Is this code covered by automated tests?: No
  • Has the fix been verified in Nightly?: No
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): This patch simply changes the order of how we handling the shutdown of the media resource in order to prevent UAF. Does not add any new feature or structural change.
  • String changes made/needed: no

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration: this is sec-moderate.
  • User impact if declined: Malicious sites might be able to expolit the vulnerability to excute some bad program on users' computer.
  • Fix Landed on Version: 92
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): This patch simply changes the order of how we handling the shutdown of the media resource in order to prevent UAF. Does not add any new feature or structural change.
  • String or UUID changes made by this patch: No

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Hard to see the vulnerability simply by checking the patch because the patch just changes the order of handling shutdown of the media resource. In addition, media resource is not a public web API, and just our internal low level implementation, so it's hard for other people to think of a case that using public web APIs to hit the vulnerability.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
  • Which older supported branches are affected by this flaw?: esr78
  • If not all supported branches, which bug introduced the flaw?: None
  • Do you have backports for the affected branches?: Yes
  • If not, how different, hard to create, and risky will they be?:
  • How likely is this patch to cause regressions; how much testing does it need?: The patch is about shutdown handling which means users are going to close the media so less possible to cause regression on playback. Although the reporter has submitted a test case, none of people in Mozilla can successfully reproduce that by using that test.
Attachment #9234720 - Flags: sec-approval?
Attachment #9234720 - Flags: approval-mozilla-release?
Attachment #9234720 - Flags: approval-mozilla-esr91?
Attachment #9234720 - Flags: approval-mozilla-esr78?

Comment on attachment 9234720 [details]
Bug 1722083 - revoke the listener first.

Approved for 91.0/91.0esr/78.13esr RC2.

Attachment #9234720 - Flags: approval-mozilla-release?
Attachment #9234720 - Flags: approval-mozilla-release+
Attachment #9234720 - Flags: approval-mozilla-esr91?
Attachment #9234720 - Flags: approval-mozilla-esr91+
Attachment #9234720 - Flags: approval-mozilla-esr78?
Attachment #9234720 - Flags: approval-mozilla-esr78+
Group: media-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 92 Branch
QA Whiteboard: [post-critsmash-triage]
Flags: qe-verify-
Whiteboard: [adv-main91+]
Attached file advisory.txt (obsolete) —
Alias: CVE-2021-29985
Whiteboard: [adv-main91+] → [adv-main91+][adv-esr78.13+]
Attached file advisory.txt
Attachment #9235155 - Attachment is obsolete: true

When will this release in stable?

Flags: needinfo?(tom)

We will be releasing next Tuesday the 10th.

Flags: needinfo?(tom)

Comment on attachment 9234720 [details]
Bug 1722083 - revoke the listener first.

Clearing sec-approval flag because this is already released.

Attachment #9234720 - Flags: sec-approval?
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.