There is an out-of-bounds read in FEC processing in WebRTC. If a very short RTP packet is received, FEC will assume the packet is longer and process data outside of the allocated buffer.
This bug causes the following ASAN crash:
==109993==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61b003b7ff70 at pc 0x55e01a250cd1 bp 0x7fa3af7abc40 sp 0x7fa3af7abc38
READ of size 1 at 0x61b003b7ff70 thread T15 (Chrome_libJingl)
#0 0x55e01a250cd0 in XorPayloads third_party/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc:615:34
#1 0x55e01a250cd0 in webrtc::ForwardErrorCorrection::RecoverPacket(webrtc::ForwardErrorCorrection::ReceivedFecPacket const&, webrtc::ForwardErrorCorrection::RecoveredPacket*) third_party/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc:630
#2 0x55e01a251162 in webrtc::ForwardErrorCorrection::AttemptRecovery(std::__1::list<std::__1::unique_ptr<webrtc::ForwardErrorCorrection::RecoveredPacket, std::__1::default_delete<webrtc::ForwardErrorCorrection::RecoveredPacket> >, std::__1::allocator<std::__1::unique_ptr<webrtc::ForwardErrorCorrection::RecoveredPacket, std::__1::default_delete<webrtc::ForwardErrorCorrection::RecoveredPacket> > > >*) third_party/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc:652:12
#3 0x55e01a251b12 in webrtc::ForwardErrorCorrection::DecodeFec(webrtc::ForwardErrorCorrection::ReceivedPacket const&, std::__1::list<std::__1::unique_ptr<webrtc::ForwardErrorCorrection::RecoveredPacket, std::__1::default_delete<webrtc::ForwardErrorCorrection::RecoveredPacket> >, std::__1::allocator<std::__1::unique_ptr<webrtc::ForwardErrorCorrection::RecoveredPacket, std::__1::default_delete<webrtc::ForwardErrorCorrection::RecoveredPacket> > > >*) third_party/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc:739:3
#4 0x55e01a4c5595 in webrtc::UlpfecReceiverImpl::ProcessReceivedFec() third_party/webrtc/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc:248:11
#5 0x55e01a4a1bb9 in webrtc::RtpVideoStreamReceiver::ParseAndHandleEncapsulatingHeader(unsigned char const*, unsigned long, webrtc::RTPHeader const&) third_party/webrtc/video/rtp_video_stream_receiver.cc:419:23
#6 0x55e01a49f05b in webrtc::RtpVideoStreamReceiver::ReceivePacket(unsigned char const*, unsigned long, webrtc::RTPHeader const&) third_party/webrtc/video/rtp_video_stream_receiver.cc:390:5
#7 0x55e01a49fcf2 in webrtc::RtpVideoStreamReceiver::OnRtpPacket(webrtc::RtpPacketReceived const&) third_party/webrtc/video/rtp_video_stream_receiver.cc:290:3
#8 0x55e009a368a1 in webrtc::RtpDemuxer::OnRtpPacket(webrtc::RtpPacketReceived const&) third_party/webrtc/call/rtp_demuxer.cc:157:11
#9 0x55e009a3b6e1 in webrtc::RtpStreamReceiverController::OnRtpPacket(webrtc::RtpPacketReceived const&) third_party/webrtc/call/rtp_stream_receiver_controller.cc:55:19
#10 0x55e01a231339 in webrtc::internal::Call::DeliverRtp(webrtc::MediaType, rtc::CopyOnWriteBuffer, webrtc::PacketTime const&) third_party/webrtc/call/call.cc:1321:36
#11 0x55e01a232300 in webrtc::internal::Call::DeliverPacket(webrtc::MediaType, rtc::CopyOnWriteBuffer, webrtc::PacketTime const&) third_party/webrtc/call/call.cc:1361:10
#12 0x55e01a95d341 in cricket::WebRtcVideoChannel::OnPacketReceived(rtc::CopyOnWriteBuffer*, rtc::PacketTime const&) third_party/webrtc/media/engine/webrtcvideoengine.cc:1441:26
#13 0x55e01a1d8dc2 in cricket::BaseChannel::ProcessPacket(bool, rtc::CopyOnWriteBuffer const&, rtc::PacketTime const&) third_party/webrtc/pc/channel.cc
#14 0x55e01a1f6760 in rtc::AsyncInvoker::OnMessage(rtc::Message*) third_party/webrtc/rtc_base/asyncinvoker.cc:45:22
#15 0x55e01a0a6aa1 in jingle_glue::JingleThreadWrapper::Dispatch(rtc::Message*) jingle/glue/thread_wrapper.cc:157:22
#16 0x55e01a0a7d7e in jingle_glue::JingleThreadWrapper::RunTask(int) jingle/glue/thread_wrapper.cc:279:7
#17 0x55e00d52b6f5 in Run base/callback.h:96:12
#18 0x55e00d52b6f5 in base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*) base/debug/task_annotator.cc:101
#19 0x55e00d5881d5 in base::MessageLoop::RunTask(base::PendingTask*) base/message_loop/message_loop.cc:319:25
#20 0x55e00d589444 in DeferOrRunPendingTask base/message_loop/message_loop.cc:329:5
#21 0x55e00d589444 in base::MessageLoop::DoWork() base/message_loop/message_loop.cc:373
#22 0x55e00d591acf in base::MessagePumpDefault::Run(base::MessagePump::Delegate*) base/message_loop/message_pump_default.cc:37:31
#23 0x55e00d600551 in base::RunLoop::Run() base/run_loop.cc:102:14
#24 0x55e00d6878b4 in base::Thread::ThreadMain() base/threading/thread.cc:337:3
#25 0x55e00d73c694 in base::(anonymous namespace)::ThreadFunc(void*) base/threading/platform_thread_posix.cc:76:13
#26 0x7fa3d586f493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)
0x61b003b7ff70 is located 0 bytes to the right of 1520-byte region [0x61b003b7f980,0x61b003b7ff70)
allocated by thread T15 (Chrome_libJingl) here:
#0 0x55e00607ef92 in operator new(unsigned long) /b/build/slave/linux_upload_clang/build/src/third_party/llvm/compiler-rt/lib/asan/asan_new_delete.cc:93:3
#1 0x55e01a4c3eeb in webrtc::UlpfecReceiverImpl::AddReceivedRedPacket(webrtc::RTPHeader const&, unsigned char const*, unsigned long, unsigned char) third_party/webrtc/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc:101:26
#2 0x55e01a4a1b6f in webrtc::RtpVideoStreamReceiver::ParseAndHandleEncapsulatingHeader(unsigned char const*, unsigned long, webrtc::RTPHeader const&) third_party/webrtc/video/rtp_video_stream_receiver.cc:414:27
#3 0x55e01a49f05b in webrtc::RtpVideoStreamReceiver::ReceivePacket(unsigned char const*, unsigned long, webrtc::RTPHeader const&) third_party/webrtc/video/rtp_video_stream_receiver.cc:390:5
#4 0x55e01a49fcf2 in webrtc::RtpVideoStreamReceiver::OnRtpPacket(webrtc::RtpPacketReceived const&) third_party/webrtc/video/rtp_video_stream_receiver.cc:290:3
#5 0x55e009a368a1 in webrtc::RtpDemuxer::OnRtpPacket(webrtc::RtpPacketReceived const&) third_party/webrtc/call/rtp_demuxer.cc:157:11
#6 0x55e009a3b6e1 in webrtc::RtpStreamReceiverController::OnRtpPacket(webrtc::RtpPacketReceived const&) third_party/webrtc/call/rtp_stream_receiver_controller.cc:55:19
#7 0x55e01a231339 in webrtc::internal::Call::DeliverRtp(webrtc::MediaType, rtc::CopyOnWriteBuffer, webrtc::PacketTime const&) third_party/webrtc/call/call.cc:1321:36
#8 0x55e01a232300 in webrtc::internal::Call::DeliverPacket(webrtc::MediaType, rtc::CopyOnWriteBuffer, webrtc::PacketTime const&) third_party/webrtc/call/call.cc:1361:10
#9 0x55e01a95d341 in cricket::WebRtcVideoChannel::OnPacketReceived(rtc::CopyOnWriteBuffer*, rtc::PacketTime const&) third_party/webrtc/media/engine/webrtcvideoengine.cc:1441:26
#10 0x55e01a1d8dc2 in cricket::BaseChannel::ProcessPacket(bool, rtc::CopyOnWriteBuffer const&, rtc::PacketTime const&) third_party/webrtc/pc/channel.cc
#11 0x55e01a1f6760 in rtc::AsyncInvoker::OnMessage(rtc::Message*) third_party/webrtc/rtc_base/asyncinvoker.cc:45:22
#12 0x55e01a0a6aa1 in jingle_glue::JingleThreadWrapper::Dispatch(rtc::Message*) jingle/glue/thread_wrapper.cc:157:22
#13 0x55e01a0a7d7e in jingle_glue::JingleThreadWrapper::RunTask(int) jingle/glue/thread_wrapper.cc:279:7
#14 0x55e00d52b6f5 in Run base/callback.h:96:12
#15 0x55e00d52b6f5 in base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*) base/debug/task_annotator.cc:101
#16 0x55e00d5881d5 in base::MessageLoop::RunTask(base::PendingTask*) base/message_loop/message_loop.cc:319:25
#17 0x55e00d589444 in DeferOrRunPendingTask base/message_loop/message_loop.cc:329:5
#18 0x55e00d589444 in base::MessageLoop::DoWork() base/message_loop/message_loop.cc:373
#19 0x55e00d591acf in base::MessagePumpDefault::Run(base::MessagePump::Delegate*) base/message_loop/message_pump_default.cc:37:31
#20 0x55e00d600551 in base::RunLoop::Run() base/run_loop.cc:102:14
#21 0x55e00d6878b4 in base::Thread::ThreadMain() base/threading/thread.cc:337:3
#22 0x55e00d73c694 in base::(anonymous namespace)::ThreadFunc(void*) base/threading/platform_thread_posix.cc:76:13
#23 0x7fa3d586f493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)
Thread T15 (Chrome_libJingl) created by T0 (chrome) here:
#0 0x55e00603bb7d in __interceptor_pthread_create /b/build/slave/linux_upload_clang/build/src/third_party/llvm/compiler-rt/lib/asan/asan_interceptors.cc:210:3
#1 0x55e00d73b99e in base::(anonymous namespace)::CreateThread(unsigned long, bool, base::PlatformThread::Delegate*, base::PlatformThreadHandle*, base::ThreadPriority) base/threading/platform_thread_posix.cc:115:13
#2 0x55e00d686be9 in base::Thread::StartWithOptions(base::Thread::Options const&) base/threading/thread.cc:112:15
#3 0x55e00d68684b in base::Thread::Start() base/threading/thread.cc:75:10
#4 0x55e01a09ba37 in content::PeerConnectionDependencyFactory::CreatePeerConnectionFactory() content/renderer/media/webrtc/peer_connection_dependency_factory.cc:177:3
#5 0x55e01a09b4d0 in content::PeerConnectionDependencyFactory::GetPcFactory() content/renderer/media/webrtc/peer_connection_dependency_factory.cc:139:5
#6 0x55e01a09df09 in content::PeerConnectionDependencyFactory::CreatePeerConnection(webrtc::PeerConnectionInterface::RTCConfiguration const&, blink::WebLocalFrame*, webrtc::PeerConnectionObserver*) content/renderer/media/webrtc/peer_connection_dependency_factory.cc:340:8
#7 0x55e01aa63b1b in content::RTCPeerConnectionHandler::Initialize(blink::WebRTCConfiguration const&, blink::WebMediaConstraints const&) content/renderer/media/webrtc/rtc_peer_connection_handler.cc:1333:50
#8 0x55e01baafde2 in blink::RTCPeerConnection::RTCPeerConnection(blink::ExecutionContext*, blink::WebRTCConfiguration const&, blink::WebMediaConstraints, blink::ExceptionState&) third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc:585:23
#9 0x55e01baaaedc in blink::RTCPeerConnection::Create(blink::ExecutionContext*, blink::RTCConfiguration const&, blink::Dictionary const&, blink::ExceptionState&) third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc:518:44
#10 0x55e01bb1ad0b in constructor gen/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection.cc:1317:29
#11 0x55e01bb1ad0b in blink::V8RTCPeerConnection::constructorCallback(v8::FunctionCallbackInfo<v8::Value> const&) gen/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection.cc:1667
#12 0x55e00ab4db49 in v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo*) v8/src/api-arguments-inl.h:94:3
#13 0x55e00ab4a4c4 in v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<true>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) v8/src/builtins/builtins-api.cc:109:36
#14 0x55e00ab48eb3 in v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) v8/src/builtins/builtins-api.cc:135:5
#15 0x55e00c2fce0d (/usr/local/google/home/natashenka/chromium3/src/out/asan/chrome+0xde74e0d)
#16 0x55e00c263d3f (/usr/local/google/home/natashenka/chromium3/src/out/asan/chrome+0xdddbd3f)
#17 0x7e9c7b70dd69 (<unknown module>)
#18 0x7e9c7b68868f (<unknown module>)
#19 0x55e00c2618a5 (/usr/local/google/home/natashenka/chromium3/src/out/asan/chrome+0xddd98a5)
#20 0x55e00c263c60 (/usr/local/google/home/natashenka/chromium3/src/out/asan/chrome+0xdddbc60)
#21 0x7e9c7b70dd69 (<unknown module>)
#22 0x7e9c7b68868f (<unknown module>)
#23 0x7e9c7b68868f (<unknown module>)
#24 0x7e9c7b68868f (<unknown module>)
#25 0x55e00c2618a5 (/usr/local/google/home/natashenka/chromium3/src/out/asan/chrome+0xddd98a5)
#26 0x55e00c265722 (/usr/local/google/home/natashenka/chromium3/src/out/asan/chrome+0xdddd722)
#27 0x7e9c7b684820 (<unknown module>)
#28 0x55e00b3b4130 in Call v8/src/simulator.h:113:12
#29 0x55e00b3b4130 in v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, bool, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, v8::internal::Handle<v8::internal::Object>, v8::internal::Execution::MessageHandling, v8::internal::Execution::Target) v8/src/execution.cc:155
#30 0x55e00b3b3993 in CallInternal v8/src/execution.cc:191:10
#31 0x55e00b3b3993 in v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) v8/src/execution.cc:202
#32 0x55e00aa107b4 in v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) v8/src/api.cc:5218:7
#33 0x55e015fe0a61 in blink::V8ScriptRunner::CallFunction(v8::Local<v8::Function>, blink::ExecutionContext*, v8::Local<v8::Value>, int, v8::Local<v8::Value>*, v8::Isolate*) third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc:386:17
#34 0x55e016028398 in blink::V8EventListener::CallListenerFunction(blink::ScriptState*, v8::Local<v8::Value>, blink::Event*) third_party/blink/renderer/bindings/core/v8/v8_event_listener.cc:115:8
#35 0x55e016029a54 in blink::V8AbstractEventListener::InvokeEventHandler(blink::ScriptState*, blink::Event*, v8::Local<v8::Value>) third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc:171:20
#36 0x55e01602942b in blink::V8AbstractEventListener::HandleEvent(blink::ScriptState*, blink::Event*) third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc:120:3
#37 0x55e016029103 in blink::V8AbstractEventListener::handleEvent(blink::ExecutionContext*, blink::Event*) third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc:108:3
#38 0x55e017446ebe in blink::EventTarget::FireEventListeners(blink::Event*, blink::EventTargetData*, blink::HeapVector<blink::RegisteredEventListener, 1ul>&) third_party/blink/renderer/core/dom/events/event_target.cc:804:15
#39 0x55e017445121 in blink::EventTarget::FireEventListeners(blink::Event*) third_party/blink/renderer/core/dom/events/event_target.cc:656:29
#40 0x55e017444d5b in blink::EventTarget::DispatchEventInternal(blink::Event*) third_party/blink/renderer/core/dom/events/event_target.cc:560:41
#41 0x55e017a0de87 in Create third_party/blink/renderer/core/events/progress_event.h:44:16
#42 0x55e017a0de87 in blink::FileReader::FireEvent(WTF::AtomicString const&) third_party/blink/renderer/core/fileapi/file_reader.cc:471
#43 0x55e017a0e6d4 in blink::FileReader::DidFinishLoading() third_party/blink/renderer/core/fileapi/file_reader.cc:427:3
#44 0x55e00a9494ef in blink::mojom::blink::BlobReaderClientStubDispatch::Accept(blink::mojom::blink::BlobReaderClient*, mojo::Message*) gen/third_party/blink/public/mojom/blob/blob.mojom-blink.cc:168:13
#45 0x55e00ea14f7e in mojo::InterfaceEndpointClient::HandleValidatedMessage(mojo::Message*) mojo/public/cpp/bindings/lib/interface_endpoint_client.cc:419:32
#46 0x55e00ea258b3 in mojo::internal::MultiplexRouter::ProcessIncomingMessage(mojo::internal::MultiplexRouter::MessageWrapper*, mojo::internal::MultiplexRouter::ClientCallBehavior, base::SequencedTaskRunner*) mojo/public/cpp/bindings/lib/multiplex_router.cc:865:42
#47 0x55e00ea2409e in mojo::internal::MultiplexRouter::Accept(mojo::Message*) mojo/public/cpp/bindings/lib/multiplex_router.cc:589:38
#48 0x55e00ea0efa7 in mojo::Connector::ReadSingleMessage(unsigned int*) mojo/public/cpp/bindings/lib/connector.cc:443:51
#49 0x55e00ea1081c in mojo::Connector::ReadAllAvailableMessages() mojo/public/cpp/bindings/lib/connector.cc:472:10
#50 0x55e00ea00642 in Run base/callback.h:125:12
#51 0x55e00ea00642 in mojo::SimpleWatcher::OnHandleReady(int, unsigned int, mojo::HandleSignalsState const&) mojo/public/cpp/system/simple_watcher.cc:274
#52 0x55e00d52b6f5 in Run base/callback.h:96:12
#53 0x55e00d52b6f5 in base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*) base/debug/task_annotator.cc:101
#54 0x55e00c4afc95 in base::sequence_manager::internal::ThreadControllerImpl::DoWork(base::sequence_manager::internal::ThreadControllerImpl::WorkType) third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.cc:166:21
#55 0x55e00d52b6f5 in Run base/callback.h:96:12
#56 0x55e00d52b6f5 in base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*) base/debug/task_annotator.cc:101
#57 0x55e00d5881d5 in base::MessageLoop::RunTask(base::PendingTask*) base/message_loop/message_loop.cc:319:25
#58 0x55e00d589444 in DeferOrRunPendingTask base/message_loop/message_loop.cc:329:5
#59 0x55e00d589444 in base::MessageLoop::DoWork() base/message_loop/message_loop.cc:373
#60 0x55e00d591acf in base::MessagePumpDefault::Run(base::MessagePump::Delegate*) base/message_loop/message_pump_default.cc:37:31
#61 0x55e00d600551 in base::RunLoop::Run() base/run_loop.cc:102:14
#62 0x55e01bfb0599 in content::RendererMain(content::MainFunctionParams const&) content/renderer/renderer_main.cc:218:23
#63 0x55e00cafbca5 in content::RunZygote(content::ContentMainDelegate*) content/app/content_main_runner_impl.cc:567:14
#64 0x55e00caff751 in content::ContentMainRunnerImpl::Run() content/app/content_main_runner_impl.cc:969:10
#65 0x55e00cb1e6c3 in service_manager::Main(service_manager::MainParams const&) services/service_manager/embedder/main.cc:459:29
#66 0x55e00cafa2d0 in content::ContentMain(content::ContentMainParams const&) content/app/content_main.cc:19:10
#67 0x55e006081fe3 in ChromeMain chrome/app/chrome_main.cc:101:12
#68 0x7fa3ceac32b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
SUMMARY: AddressSanitizer: heap-buffer-overflow third_party/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc:615:34 in XorPayloads
Shadow bytes around the buggy address:
0x0c3680767f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c3680767fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c3680767fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c3680767fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c3680767fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c3680767fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa
0x0c3680767ff0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3680768000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3680768010: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3680768020: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3680768030: 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
==109993==ABORTING
To reproduce this issue:
1) Apply new.patch to a fresh WebRTC tree
2) Build video_replay
3) Download the attached files and run ./video_replay --input_file fec
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45444.zip