Closed Bug 1742334 (CVE-2022-22740) Opened 1 year ago Closed 1 year ago

Use-after-free of ChannelEventQueue::mOwner

Categories

(Core :: Networking: HTTP, defect, P1)

defect

Tracking

()

RESOLVED FIXED
97 Branch
Tracking Status
firefox-esr91 96+ fixed
firefox94 --- wontfix
firefox95 --- wontfix
firefox96 + fixed
firefox97 + fixed

People

(Reporter: bo13oy, Assigned: valentin)

Details

(Keywords: csectype-uaf, sec-high, Whiteboard: [reporter-external] [client-bounty-form][necko-triaged][sec-survey][adv-main96+][adv-ESR91.5+][post-critsmash-triage])

Attachments

(5 files, 1 obsolete file)

Attached file poc.7z

Tested Version: Ubuntu 64-bit memory 8G + linux64-fuzzing-asan-opt(94.0.2 (64-bit)) => linux64-fuzzing-asan-opt

Loading poc.html into the firefox browser to create a new tab(Using the grizzly tool(allow pop-ups)),I feel that this is a conditional competition vulnerability, This poc is not 100% stable, and I can only trigger it in the docker container,if it fails, please repeat more times. the crash report is as follows:

==239309==ERROR: AddressSanitizer: heap-use-after-free on address 0x61c0001c0100 at pc 0x7f44482fcb3a bp 0x7ffd9fa08970 sp 0x7ffd9fa08968
READ of size 8 at 0x61c0001c0100 thread T0 (Web Content)
    #0 0x7f44482fcb39 in nsCOMPtr /builds/worker/workspace/obj-build/dist/include/nsCOMPtr.h:928:7
    #1 0x7f44482fcb39 in CompleteResumeRunnable /builds/worker/checkouts/gecko/netwerk/ipc/ChannelEventQueue.cpp:145:13
    #2 0x7f44482fcb39 in mozilla::net::ChannelEventQueue::ResumeInternal() /builds/worker/checkouts/gecko/netwerk/ipc/ChannelEventQueue.cpp:160:34
    #3 0x7f44482fc665 in mozilla::net::ChannelEventQueue::Resume() /builds/worker/checkouts/gecko/netwerk/ipc/ChannelEventQueue.cpp:117:3
    #4 0x7f444a77a876 in mozilla::dom::Document::UnsuppressEventHandlingAndFireEvents(bool) /builds/worker/checkouts/gecko/dom/base/Document.cpp:12460:16
    #5 0x7f444a55c7d7 in nsGlobalWindowInner::FreeInnerObjects() /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowInner.cpp:1189:13
    #6 0x7f444a5b3c9c in nsGlobalWindowOuter::DetachFromDocShell(bool) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowOuter.cpp:2700:12
    #7 0x7f4452131ce6 in nsDocShell::Destroy() /builds/worker/checkouts/gecko/docshell/base/nsDocShell.cpp:4438:20
    #8 0x7f44527be8ed in nsWebBrowser::SetDocShell(nsDocShell*) /builds/worker/checkouts/gecko/toolkit/components/browser/nsWebBrowser.cpp:1122:18
    #9 0x7f44527bdc0c in nsWebBrowser::InternalDestroy() /builds/worker/checkouts/gecko/toolkit/components/browser/nsWebBrowser.cpp:175:3
    #10 0x7f44527c35ec in Destroy /builds/worker/checkouts/gecko/toolkit/components/browser/nsWebBrowser.cpp:855:3
    #11 0x7f44527c35ec in non-virtual thunk to nsWebBrowser::Destroy() /builds/worker/checkouts/gecko/toolkit/components/browser/nsWebBrowser.cpp
    #12 0x7f444e3fe510 in mozilla::dom::BrowserChild::DestroyWindow() /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:899:31
    #13 0x7f444e4168c8 in mozilla::dom::BrowserChild::RecvDestroy() /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:2632:3
    #14 0x7f44492c1a7d in mozilla::dom::PBrowserChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PBrowserChild.cpp:6620:56
    #15 0x7f4448906bfc in mozilla::dom::PContentChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PContentChild.cpp:8200:32
    #16 0x7f44486a18e9 in mozilla::ipc::MessageChannel::DispatchAsyncMessage(mozilla::ipc::ActorLifecycleProxy*, IPC::Message const&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:2043:25
    #17 0x7f444869e756 in mozilla::ipc::MessageChannel::DispatchMessage(IPC::Message&&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1968:9
    #18 0x7f444869ff22 in mozilla::ipc::MessageChannel::RunMessage(mozilla::ipc::MessageChannel::MessageTask&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1827:3
    #19 0x7f44486a0867 in mozilla::ipc::MessageChannel::MessageTask::Run() /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1855:14
    #20 0x7f444726888a in mozilla::RunnableTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:467:16
    #21 0x7f4447234f62 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:770:26
    #22 0x7f4447232798 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:606:15
    #23 0x7f4447232ec0 in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:390:36
    #24 0x7f444726ff54 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:126:37
    #25 0x7f444726ff54 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_1>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:531:5
    #26 0x7f444725150b in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1148:16
    #27 0x7f444725b42c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:467:10
    #28 0x7f444e3a02ac in bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, mozilla::dom::ContentChild::ProvideWindowCommon(mozilla::dom::BrowserChild*, nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**)::$_8>(mozilla::dom::ContentChild::ProvideWindowCommon(mozilla::dom::BrowserChild*, nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**)::$_8&&, nsIThread*) /builds/worker/workspace/obj-build/dist/include/mozilla/SpinEventLoopUntil.h:93:25
    #29 0x7f444e39d2fb in mozilla::dom::ContentChild::ProvideWindowCommon(mozilla::dom::BrowserChild*, nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/ipc/ContentChild.cpp:1227:5
    #30 0x7f444e3fd899 in mozilla::dom::BrowserChild::ProvideWindow(nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:851:14
    #31 0x7f4452cc2ff9 in nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy*, nsTSubstring<char> const&, nsTSubstring<char> const&, nsTSubstring<char> const&, bool, bool, bool, nsIArray*, bool, bool, bool, nsPIWindowWatcher::PrintKind, nsDocShellLoadState*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/toolkit/components/windowwatcher/nsWindowWatcher.cpp:842:24
    #32 0x7f4452cc7188 in nsWindowWatcher::OpenWindow2(mozIDOMWindowProxy*, nsTSubstring<char> const&, nsTSubstring<char> const&, nsTSubstring<char> const&, bool, bool, bool, nsISupports*, bool, bool, bool, nsPIWindowWatcher::PrintKind, nsDocShellLoadState*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/toolkit/components/windowwatcher/nsWindowWatcher.cpp:376:10
    #33 0x7f444a5cd0c9 in nsGlobalWindowOuter::OpenInternal(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, bool, bool, bool, bool, bool, nsIArray*, nsISupports*, nsDocShellLoadState*, bool, nsGlobalWindowOuter::PrintKind, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowOuter.cpp:7172:21
    #34 0x7f444a5d1fef in nsGlobalWindowOuter::OpenJS(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowOuter.cpp:5805:10
    #35 0x7f444a5d1b48 in nsGlobalWindowOuter::OpenOuter(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowOuter.cpp:5769:17
    #36 0x7f444a579873 in nsGlobalWindowInner::Open(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowInner.cpp:3991:3
    #37 0x7f444bc2d0c9 in mozilla::dom::Window_Binding::open(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/WindowBinding.cpp:2704:59
    #38 0x7f444c40aead in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::MaybeCrossOriginObjectThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3300:13
    #39 0x1a94d8ac48bf  (<unknown module>)

0x61c0001c0100 is located 128 bytes inside of 1824-byte region [0x61c0001c0080,0x61c0001c07a0)
freed by thread T0 (Web Content) here:
    #0 0x5578b600f8a2 in free /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:127:3
    #1 0x7f4447fd266b in operator delete /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:51:10
    #2 0x7f4447fd266b in mozilla::net::HttpChannelChild::Release() /builds/worker/checkouts/gecko/netwerk/protocol/http/HttpChannelChild.cpp:199:7
    #3 0x7f444800334e in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:50:40
    #4 0x7f444800334e in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:381:36
    #5 0x7f444800334e in assign_assuming_AddRef /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:69:7
    #6 0x7f444800334e in operator= /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:168:5
    #7 0x7f444800334e in Revoke /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:760:24
    #8 0x7f444800334e in Revoke /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1214:15
    #9 0x7f444800334e in ~RunnableMethodImpl /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1174:35
    #10 0x7f444800334e in mozilla::detail::RunnableMethodImpl<mozilla::net::HttpChannelChild*, void (mozilla::net::HttpChannelChild::*)(), true, (mozilla::RunnableKind)0>::~RunnableMethodImpl() /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1174:33
    #11 0x7f444723ec85 in mozilla::Runnable::Release() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:60:1
    #12 0x7f44472688cc in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:50:40
    #13 0x7f44472688cc in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:381:36
    #14 0x7f44472688cc in assign_assuming_AddRef /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:69:7
    #15 0x7f44472688cc in operator= /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:168:5
    #16 0x7f44472688cc in mozilla::RunnableTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:468:15
    #17 0x7f4447234f62 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:770:26
    #18 0x7f4447232798 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:606:15
    #19 0x7f4447232ec0 in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:390:36
    #20 0x7f444726ff54 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:126:37
    #21 0x7f444726ff54 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_1>::Run() /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:531:5
    #22 0x7f444725150b in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1148:16
    #23 0x7f444725b42c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:467:10
    #24 0x7f444e3a02ac in bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, mozilla::dom::ContentChild::ProvideWindowCommon(mozilla::dom::BrowserChild*, nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**)::$_8>(mozilla::dom::ContentChild::ProvideWindowCommon(mozilla::dom::BrowserChild*, nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**)::$_8&&, nsIThread*) /builds/worker/workspace/obj-build/dist/include/mozilla/SpinEventLoopUntil.h:93:25
    #25 0x7f444e39d2fb in mozilla::dom::ContentChild::ProvideWindowCommon(mozilla::dom::BrowserChild*, nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/ipc/ContentChild.cpp:1227:5
    #26 0x7f444e3fd899 in mozilla::dom::BrowserChild::ProvideWindow(nsIOpenWindowInfo*, unsigned int, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, bool, nsDocShellLoadState*, bool*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:851:14
    #27 0x7f4452cc2ff9 in nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy*, nsTSubstring<char> const&, nsTSubstring<char> const&, nsTSubstring<char> const&, bool, bool, bool, nsIArray*, bool, bool, bool, nsPIWindowWatcher::PrintKind, nsDocShellLoadState*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/toolkit/components/windowwatcher/nsWindowWatcher.cpp:842:24
    #28 0x7f4452cc7188 in nsWindowWatcher::OpenWindow2(mozIDOMWindowProxy*, nsTSubstring<char> const&, nsTSubstring<char> const&, nsTSubstring<char> const&, bool, bool, bool, nsISupports*, bool, bool, bool, nsPIWindowWatcher::PrintKind, nsDocShellLoadState*, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/toolkit/components/windowwatcher/nsWindowWatcher.cpp:376:10
    #29 0x7f444a5cd0c9 in nsGlobalWindowOuter::OpenInternal(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, bool, bool, bool, bool, bool, nsIArray*, nsISupports*, nsDocShellLoadState*, bool, nsGlobalWindowOuter::PrintKind, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowOuter.cpp:7172:21
    #30 0x7f444a5d1fef in nsGlobalWindowOuter::OpenJS(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::BrowsingContext**) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowOuter.cpp:5805:10
    #31 0x7f444a5d1b48 in nsGlobalWindowOuter::OpenOuter(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowOuter.cpp:5769:17
    #32 0x7f444a579873 in nsGlobalWindowInner::Open(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowInner.cpp:3991:3

previously allocated by thread T0 (Web Content) here:
    #0 0x5578b600fb0d in malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
    #1 0x5578b6049b4d in moz_xmalloc /builds/worker/checkouts/gecko/memory/mozalloc/mozalloc.cpp:52:15
    #2 0x7f4447e943f1 in operator new /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:33:10
    #3 0x7f4447e943f1 in mozilla::net::nsHttpHandler::NewProxiedChannel(nsIURI*, nsIProxyInfo*, unsigned int, nsIURI*, nsILoadInfo*, nsIChannel**) /builds/worker/checkouts/gecko/netwerk/protocol/http/nsHttpHandler.cpp:2067:19
    #4 0x7f444754ae6a in mozilla::net::nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI*, nsIURI*, unsigned int, nsILoadInfo*, nsIChannel**) /builds/worker/checkouts/gecko/netwerk/base/nsIOService.cpp:1106:15
    #5 0x7f444754a93a in mozilla::net::nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI*, nsIURI*, unsigned int, nsINode*, nsIPrincipal*, nsIPrincipal*, mozilla::Maybe<mozilla::dom::ClientInfo> const&, mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> const&, unsigned int, nsIContentPolicy::nsContentPolicyType, unsigned int, nsIChannel**) /builds/worker/checkouts/gecko/netwerk/base/nsIOService.cpp:1078:10
    #6 0x7f444754a879 in mozilla::net::nsIOService::NewChannelFromURIWithClientAndController(nsIURI*, nsINode*, nsIPrincipal*, nsIPrincipal*, mozilla::Maybe<mozilla::dom::ClientInfo> const&, mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> const&, unsigned int, nsIContentPolicy::nsContentPolicyType, unsigned int, nsIChannel**) /builds/worker/checkouts/gecko/netwerk/base/nsIOService.cpp:1050:10
    #7 0x7f4447573ec4 in NS_NewChannelInternal(nsIChannel**, nsIURI*, nsINode*, nsIPrincipal*, nsIPrincipal*, mozilla::Maybe<mozilla::dom::ClientInfo> const&, mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> const&, unsigned int, nsIContentPolicy::nsContentPolicyType, nsICookieJarSettings*, mozilla::dom::PerformanceStorage*, nsILoadGroup*, nsIInterfaceRequestor*, unsigned int, nsIIOService*, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsNetUtil.cpp:426:20
    #8 0x7f4447574df7 in NS_NewChannel(nsIChannel**, nsIURI*, nsINode*, unsigned int, nsIContentPolicy::nsContentPolicyType, mozilla::dom::PerformanceStorage*, nsILoadGroup*, nsIInterfaceRequestor*, unsigned int, nsIIOService*, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsNetUtil.cpp:553:10
    #9 0x7f444e8d87b7 in mozilla::dom::XMLHttpRequestMainThread::CreateChannel() /builds/worker/checkouts/gecko/dom/xhr/XMLHttpRequestMainThread.cpp:2439:10
    #10 0x7f444e8d7c9b in mozilla::dom::XMLHttpRequestMainThread::Open(nsTSubstring<char> const&, nsTSubstring<char> const&, bool, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/xhr/XMLHttpRequestMainThread.cpp:1530:3
    #11 0x7f444e8d6e8f in mozilla::dom::XMLHttpRequestMainThread::Open(nsTSubstring<char> const&, nsTSubstring<char16_t> const&, bool, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/xhr/XMLHttpRequestMainThread.cpp:1385:3
    #12 0x7f444e8d6d63 in mozilla::dom::XMLHttpRequestMainThread::Open(nsTSubstring<char> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/xhr/XMLHttpRequestMainThread.cpp:1374:3
    #13 0x7f444bd2560d in mozilla::dom::XMLHttpRequest_Binding::open(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/XMLHttpRequestBinding.cpp:989:28
    #14 0x7f444c4071df in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3300:13
    #15 0x7f445305df13 in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:385:13
    #16 0x7f445305df13 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:472:12
    #17 0x7f445304a496 in CallFromStack /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:536:10
    #18 0x7f445304a496 in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3239:16
    #19 0x7f445302f845 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:354:13
    #20 0x7f445305dff9 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:504:13
    #21 0x7f445305fbeb in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:549:8
    #22 0x7f44532a8c07 in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/CallAndConstruct.cpp:117:10

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/workspace/obj-build/dist/include/nsCOMPtr.h:928:7 in nsCOMPtr
Shadow bytes around the buggy address:
  0x0c388002ffd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c388002ffe0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c388002fff0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3880030000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3880030010: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c3880030020:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3880030030: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3880030040: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3880030050: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3880030060: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3880030070: 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
==239309==ABORTING

This vuln is discovered by bo13oy of Cyber Kunlun Lab.

Thanks.

Flags: sec-bounty?

--> Networking.

I also fixed some formatting in comment #0 for clarity.

Group: firefox-core-security → network-core-security
Component: Security → Networking: HTTP
Product: Firefox → Core

I haven't looked at the test case because I don't have 7zip installed, but it looks like the UAF is happening on this line in the CompleteResumeRunnable ctor: mOwner(aOwner) {}. In other words, an already-dead nsISupports has been passed in.

Here's the line from ChannelEventQueue::ResumeInternal():
RefPtr<Runnable> event = new CompleteResumeRunnable(this, mOwner);

mOwner is a weak pointer, so presumably something is going wrong what whatever is supposed to extend the lifetime enough.

The stacks look gnarly. In both the use and the free, we're spinning a nested event loop in ContentChild::ProvideWindowCommon(). I'm guessing there's some kind of race between a runnable running that destroys the channel and getting an IPC message from the parent telling us to destroy the BrowserChild which causes us to tear down a window.

Attached file poc.html
Attached image reproduce.gif

Uh, most likely we need to clear mOwner/set a flag on the ChannelEventQueue when the HttpChannelChild goes away.
All of the operations in comment 0 happen on the main thread, so there's no data race here.

Assignee: nobody → valentin.gosu
Severity: -- → S3
Type: task → defect
Priority: -- → P1
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][necko-triaged]
Keywords: sec-high
Summary: Firefox DOM XMLHttpRequest Use After Free Remote Code Execution Vulnerability → Use-after-free of ChannelEventQueue::mOwner

Comment on attachment 9252080 [details]
Bug 1742334 - Make sure to null out ChannelEventQueue::mOwner when object is released r=#necko

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Not easily. While the problem is generally obvious from the fix, going from that to an exploit seems difficult.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: Yes
  • Which older supported branches are affected by this flaw?: all
  • 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?: Should graft directly to all branches/Easy to backport.
  • How likely is this patch to cause regressions; how much testing does it need?:
Attachment #9252080 - Flags: sec-approval?

Comment on attachment 9252080 [details]
Bug 1742334 - Make sure to null out ChannelEventQueue::mOwner when object is released r=#necko

Approved to land and uplift

Attachment #9252080 - Flags: sec-approval?
Attachment #9252080 - Flags: sec-approval+
Attachment #9252080 - Flags: approval-mozilla-esr91+
Attachment #9252080 - Flags: approval-mozilla-beta+

Make sure to null out ChannelEventQueue::mOwner when object is released r=necko-reviewers,dragana
https://hg.mozilla.org/integration/autoland/rev/2c34e2c06639132ae6a00b440c8835b2a44f42ad
https://hg.mozilla.org/mozilla-central/rev/2c34e2c06639

Group: network-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 97 Branch

As part of a security bug pattern analysis, we are requesting your help with a high level analysis of this bug. It is our hope to develop static analysis (or potentially runtime/dynamic analysis) in the future to identify classes of bugs.

Please visit this google form to reply.

Flags: needinfo?(valentin.gosu)
Whiteboard: [reporter-external] [client-bounty-form] [verif?][necko-triaged] → [reporter-external] [client-bounty-form] [verif?][necko-triaged][sec-survey]

Done.

Flags: needinfo?(valentin.gosu)
Flags: qe-verify+
Flags: qe-verify+
Flags: sec-bounty? → sec-bounty+
Whiteboard: [reporter-external] [client-bounty-form] [verif?][necko-triaged][sec-survey] → [reporter-external] [client-bounty-form][necko-triaged][sec-survey][adv-main96+][adv-ESR91.5+]
Attached file advisory.txt (obsolete) —
Attached file advisory.txt

Updating reporter affiliation.

Attachment #9257665 - Attachment is obsolete: true
Alias: CVE-2022-22740
Whiteboard: [reporter-external] [client-bounty-form][necko-triaged][sec-survey][adv-main96+][adv-ESR91.5+] → [reporter-external] [client-bounty-form][necko-triaged][sec-survey][adv-main96+][adv-ESR91.5+][post-critsmash-triage]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.