Closed Bug 1234949 (CVE-2016-1959) Opened 9 years ago Closed 8 years ago

Service Worker - Memory corruption in ServiceWorkerManager::ClaimClients

Categories

(Core :: DOM: Service Workers, defect)

46 Branch
x86_64
Windows
defect
Not set
normal

Tracking

()

RESOLVED FIXED
Tracking Status
firefox44 --- wontfix
firefox45 + fixed
firefox46 + fixed
firefox47 + verified
firefox-esr38 --- unaffected

People

(Reporter: loobenyang, Assigned: bkelly)

References

Details

(Keywords: sec-critical, Whiteboard: [fixed in bug 1241531][adv-main45+][post-critsmash-triage])

Attachments

(1 file, 5 obsolete files)

Using Clients API in Service Workers can trigger memory corruption in ServiceWorkerManager::ClaimClients().


Firefox crashes by executing invalid address:

 
First-chance exception at 0x043E0FF8 (xul.dll) in firefox.exe: 0xC0000005: Access violation executing location 0x043E0FF8.
Unhandled exception at 0x043E0FF8 (xul.dll) in firefox.exe: 0xC0000005: Access violation executing location 0x043E0FF8.


Call Stack:

 	xul.dll!043e0ff8()	C++
>	xul.dll!nsQueryInterface::operator()(const nsID & aIID, void * * aAnswer) Line 19	C++
 	xul.dll!nsCOMPtr_base::assign_from_qi(const nsQueryInterface aQI, const nsID & aIID) Line 62	C++
 	xul.dll!mozilla::dom::workers::ServiceWorkerManager::ClaimClients(nsIPrincipal * aPrincipal, const nsCString & aScope, unsigned __int64 aId) Line 3687	C++
 	xul.dll!`anonymous namespace'::ClaimRunnable::Run() Line 205	C++
 	xul.dll!nsThread::ProcessNextEvent(bool aMayWait, bool * aResult) Line 964	C++
 	xul.dll!NS_ProcessNextEvent(nsIThread * aThread, bool aMayWait) Line 297	C++
 	xul.dll!mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate * aDelegate) Line 95	C++
 	xul.dll!MessageLoop::RunHandler() Line 228	C++
 	xul.dll!MessageLoop::Run() Line 202	C++
 	xul.dll!nsBaseAppShell::Run() Line 158	C++
 	xul.dll!nsAppShell::Run() Line 259	C++
 	xul.dll!nsAppStartup::Run() Line 282	C++
 	xul.dll!XREMain::XRE_mainRun() Line 4298	C++
 	xul.dll!NS_TableDrivenQI(void * aThis, const nsID & aIID, void * * aInstancePtr, const QITableEntry * aEntries) Line 18	C++
 	xul.dll!nsComponentManagerImpl::QueryInterface(const nsID & aIID, void * * aInstancePtr) Line 969	C++
 	xul.dll!nsQueryInterface::operator()(const nsID & aIID, void * * aAnswer) Line 19	C++
 	xul.dll!nsCOMPtr_base::assign_from_qi(const nsQueryInterface aQI, const nsID & aIID) Line 62	C++

	
The virtual function table was corrupted and points to an invalid address:

-		this	0x2ef11370 {mRawPtr=0x2ef01808 {...} }	const nsQueryInterface *
-		mRawPtr	0x2ef01808 {...}	nsISupports *
-		__vfptr	0x043e0ff8 {xul.dll!mozilla::dom::DOMIfaceAndProtoJSClass PrototypeClass} {0x043e4658 {xul.dll!`string'} "DOMExceptionPrototype", ...}	void * *
		[0]	0x043e4658 {xul.dll!`string'} "DOMExceptionPrototype"	void *
		[1]	0x00400000	void *
		[2]	0x00000000	void *
+		aIID	{m0=1124576232 m1=21382 m2=16420 ...}	const nsID &
+		aAnswer	0x0062f34c {0x0062f390}	void * *
In official Linux ASAN build, I got:


Firefox version: 46.0a1 (2015-12-19)


=================================================================
==15387==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7f8ed363a6e8 at pc 0x7f8ecb59ea52 bp 0x7fff0fabc6b0 sp 0x7fff0fabc6a8
READ of size 8 at 0x7f8ed363a6e8 thread T0
    #0 0x7f8ecb59ea51 in ~RefPtr /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/mozilla/RefPtr.h:55
    #1 0x7f8ecb59ea51 in Destruct /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:520
    #2 0x7f8ecb59ea51 in DestructRange /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:2010
    #3 0x7f8ecb59ea51 in RemoveElementsAt /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:1652
    #4 0x7f8ecb59ea51 in RemoveElementAt /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:1659
    #5 0x7f8ecb59ea51 in mozilla::dom::workers::ServiceWorkerJobQueue::Pop(mozilla::dom::workers::ServiceWorkerJobQueue::QueueData&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:284
    #6 0x7f8ecb4d1727 in Done /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:301
    #7 0x7f8ecb4d1727 in Done /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:384
    #8 0x7f8ecb4d1727 in mozilla::dom::workers::ServiceWorkerInstallJob::ContinueAfterInstallEvent(bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:1168
    #9 0x7f8ecb59bc38 in mozilla::dom::workers::ContinueLifecycleRunnable::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:688
    #10 0x7f8ec5eb97f4 in nsThread::ProcessNextEvent(bool, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/threads/nsThread.cpp:964
    #11 0x7f8ec5f34a7a in NS_ProcessNextEvent(nsIThread*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/glue/nsThreadUtils.cpp:297
    #12 0x7f8ec685fe39 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/glue/MessagePump.cpp:95
    #13 0x7f8ec67cd33c in RunInternal /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:234
    #14 0x7f8ec67cd33c in RunHandler /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:227
    #15 0x7f8ec67cd33c in MessageLoop::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:201
    #16 0x7f8ecba51717 in nsBaseAppShell::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/widget/nsBaseAppShell.cpp:156
    #17 0x7f8ecd87a438 in nsAppStartup::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/components/startup/nsAppStartup.cpp:281
    #18 0x7f8ecd97b587 in XREMain::XRE_mainRun() /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4277
    #19 0x7f8ecd97c53d in XREMain::XRE_main(int, char**, nsXREAppData const*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4374
    #20 0x7f8ecd97d37e in XRE_main /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4476
    #21 0x48a6c9 in do_main /builds/slave/m-cen-l64-asan-000000000000000/build/src/browser/app/nsBrowserApp.cpp:212
    #22 0x48a6c9 in main /builds/slave/m-cen-l64-asan-000000000000000/build/src/browser/app/nsBrowserApp.cpp:352
    #23 0x7f8edea21ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
    #24 0x489c3c in _start (/home/parnell/FirefoxBuilds/old/firefox/firefox+0x489c3c)

0x7f8ed363a6e8 is located 0 bytes to the right of global variable 'nsTArrayHeader::sEmptyHdr' from '/builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/xpcom/build/Unified_cpp_xpcom_build1.cpp' (0x7f8ed363a6e0) of size 8
SUMMARY: AddressSanitizer: global-buffer-overflow /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/mozilla/RefPtr.h:55 ~RefPtr
Shadow bytes around the buggy address:
  0x0ff25a6bf480: f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9
  0x0ff25a6bf490: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9
  0x0ff25a6bf4a0: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
  0x0ff25a6bf4b0: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
  0x0ff25a6bf4c0: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9
=>0x0ff25a6bf4d0: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00[f9]f9 f9
  0x0ff25a6bf4e0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 f9
  0x0ff25a6bf4f0: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9
  0x0ff25a6bf500: f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9
  0x0ff25a6bf510: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9
  0x0ff25a6bf520: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
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
  Heap right redzone:      fb
  F==15387==ABORTING
Group: core-security → dom-core-security
Flags: needinfo?(bkelly)
Looben: please attach any testcases you used that triggered this crash. Does it happen all the time? only sometimes?
Flags: needinfo?(loobenyang)
Keywords: testcase-wanted
If I had to guess, it seems maybe the job runnable is outliving the job queue somehow.
Flags: needinfo?(bkelly)
Actually, its more likely we are triggering ContinueAfterInstallEvent() twice.  Once via the runnable here:

  https://dxr.mozilla.org/mozilla-central/source/dom/workers/ServiceWorkerManager.cpp#1192

And once via synchronously calling it here:

  https://dxr.mozilla.org/mozilla-central/source/dom/workers/ServiceWorkerManager.cpp#1196

This would trigger the job getting popped off the queue twice.  If there was only a single job in the queue originally, then it could result in trying to destruct a bogus pointer.

Were assertions turned off in the build you used?
This is a patch I already have in my queue for another bug.  I think it would at least avoid the memory corruption.  I still have an assert to try to track down the double-Done() call, though.

Does this fix the problem in your test case?
Attachment #8704273 - Flags: feedback?(loobenyang)
(In reply to Daniel Veditz [:dveditz] from comment #2)
> Looben: please attach any testcases you used that triggered this crash. Does
> it happen all the time? only sometimes?

I'm still minimizing the test case, will upload it once I've done minimizing it.
Flags: needinfo?(loobenyang)
(In reply to Ben Kelly [:bkelly] from comment #4)
> Actually, its more likely we are triggering ContinueAfterInstallEvent()
> twice.  Once via the runnable here:
> 
>  
> https://dxr.mozilla.org/mozilla-central/source/dom/workers/
> ServiceWorkerManager.cpp#1192
> 
> And once via synchronously calling it here:
> 
>  
> https://dxr.mozilla.org/mozilla-central/source/dom/workers/
> ServiceWorkerManager.cpp#1196
> 
> This would trigger the job getting popped off the queue twice.  If there was
> only a single job in the queue originally, then it could result in trying to
> destruct a bogus pointer.
> 
> Were assertions turned off in the build you used?

I did not turn off any assertions. MOZ_ASSERT actually does nothing in release build, only MOZ_RELEASE_ASSERT will crash in release build.

#ifdef DEBUG
#  define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__)
#else
#  define MOZ_ASSERT(...) do { } while (0)
#endif /* DEBUG */
Assignee: nobody → bkelly
Status: NEW → ASSIGNED
(In reply to Ben Kelly [:bkelly] from comment #5)
> Created attachment 8704273 [details] [diff] [review]
> P0 Track service worker job done state. r=ehsan
> 
> This is a patch I already have in my queue for another bug.  I think it
> would at least avoid the memory corruption.  I still have an assert to try
> to track down the double-Done() call, though.
> 
> Does this fix the problem in your test case?

In debug build without any patch (), it hit the following assert. Is this the same thing you want?

    MOZ_ASSERT(!queue.mJobs.IsEmpty());


Stack:

>	xul.dll!mozilla::dom::workers::ServiceWorkerJobQueue::Done(mozilla::dom::workers::ServiceWorkerJob * aJob) Line 297	C++
 	xul.dll!mozilla::dom::workers::ServiceWorkerJob::Done(nsresult aStatus) Line 384	C++
 	xul.dll!mozilla::dom::workers::ServiceWorkerInstallJob::ContinueAfterInstallEvent(bool aInstallEventSuccess) Line 1213	C++
 	xul.dll!mozilla::dom::workers::ContinueInstallTask::ContinueAfterWorkerEvent(bool aSuccess) Line 1650	C++
 	xul.dll!mozilla::dom::workers::ContinueLifecycleRunnable::Run() Line 687	C++
 	xul.dll!nsThread::ProcessNextEvent(bool aMayWait, bool * aResult) Line 989	C++
 	xul.dll!NS_ProcessNextEvent(nsIThread * aThread, bool aMayWait) Line 297	C++
 	xul.dll!mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate * aDelegate) Line 95	C++
 	xul.dll!MessageLoop::RunInternal() Line 235	C++
 	xul.dll!MessageLoop::RunHandler() Line 228	C++
 	xul.dll!MessageLoop::Run() Line 202	C++
 	xul.dll!nsBaseAppShell::Run() Line 158	C++
 	xul.dll!nsAppShell::Run() Line 257	C++
 	xul.dll!nsAppStartup::Run() Line 281	C++
 	xul.dll!XREMain::XRE_mainRun() Line 4288	C++
 	xul.dll!XREMain::XRE_main(int argc, char * * argv, const nsXREAppData * aAppData) Line 4385	C++
 	xul.dll!XRE_main(int argc, char * * argv, const nsXREAppData * aAppData, unsigned int aFlags) Line 4487	C++
 	firefox.exe!do_main(int argc, char * * argv, nsIFile * xreDirectory) Line 212	C++
 	firefox.exe!NS_internal_main(int argc, char * * argv) Line 352	C++
 	firefox.exe!wmain(int argc, wchar_t * * argv) Line 131	C++
 	[External Code]	
 	[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]	

Variables:

+		aJob	0x1d68e830 {mType=OverwriteScript (1) }	mozilla::dom::workers::ServiceWorkerJob *
		aJob->mJobType	InstallJob (2)	mozilla::dom::workers::ServiceWorkerJob::Type
-		queue	{mJobs={...} mPopping=false }	mozilla::dom::workers::ServiceWorkerJobQueue::QueueData &
-		mJobs	{...}	nsTArray<RefPtr<mozilla::dom::workers::ServiceWorkerJob> >
-		nsTArray_Impl<RefPtr<mozilla::dom::workers::ServiceWorkerJob>,nsTArrayInfallibleAllocator>	{...}	nsTArray_Impl<RefPtr<mozilla::dom::workers::ServiceWorkerJob>,nsTArrayInfallibleAllocator>
-		nsTArray_base<nsTArrayInfallibleAllocator,nsTArray_CopyWithMemutils>	{mHdr=0x0c2abb38 {xul.dll!nsTArrayHeader nsTArrayHeader::sEmptyHdr} {mLength=0 mCapacity=0 mIsAutoArray=...} }	nsTArray_base<nsTArrayInfallibleAllocator,nsTArray_CopyWithMemutils>
-		mHdr	0x0c2abb38 {xul.dll!nsTArrayHeader nsTArrayHeader::sEmptyHdr} {mLength=0 mCapacity=0 mIsAutoArray=0 }	nsTArrayHeader *
		mLength	0	unsigned int
		mCapacity	0	unsigned int
		mIsAutoArray	0	unsigned int
+		nsTArray_TypedBase<RefPtr<mozilla::dom::workers::ServiceWorkerJob>,nsTArray_Impl<RefPtr<mozilla::dom::workers::ServiceWorkerJob>,nsTArrayInfallibleAllocator> >	{...}	nsTArray_TypedBase<RefPtr<mozilla::dom::workers::ServiceWorkerJob>,nsTArray_Impl<RefPtr<mozilla::dom::workers::ServiceWorkerJob>,nsTArrayInfallibleAllocator> >
		mPopping	false	bool
+		queue.mJobs	{...}	nsTArray<RefPtr<mozilla::dom::workers::ServiceWorkerJob> >
+		this	0x15a991a0 {mOriginAttributesSuffix={...} mRegistrationJobQueue={mJobs={...} mPopping=false } mInstallationJobQueue=...}	mozilla::dom::workers::ServiceWorkerJobQueue *
	


Before this assert, I see two job failure in the debug console:

[25476] WARNING: ServiceWorkerJob failed with error: NS_ERROR_DOM_ABORT_ERR: file f:/OpenSrcCode/firefox/dom/workers/ServiceWorkerManager.cpp, line 378
[25476] WARNING: mInstallingWorker was null.: file f:/OpenSrcCode/firefox/dom/workers/ServiceWorkerManager.cpp, line 1212
[25476] WARNING: 'NS_FAILED(aStatus)', file f:/OpenSrcCode/firefox/dom/workers/ServiceWorkerManager.cpp, line 372
[25476] WARNING: ServiceWorkerJob failed with error: NS_ERROR_DOM_ABORT_ERR: file f:/OpenSrcCode/firefox/dom/workers/ServiceWorkerManager.cpp, line 378
Assertion failure: !queue.mJobs.IsEmpty(), at f:/OpenSrcCode/firefox/dom/workers/ServiceWorkerManager.cpp:297
Comment on attachment 8704273 [details] [diff] [review]
P0 Track service worker job done state. r=ehsan

Review of attachment 8704273 [details] [diff] [review]:
-----------------------------------------------------------------

I think comment 8 clearly shows calling Done() twice is the problem.  Without a way to reproduce locally I can't track down what is triggering the second Done(), but we can at least make it not crash.

If you r+ then I will fix up the bug number in the patch.  This is not landing in the other bug.
Attachment #8704273 - Flags: review?(ehsan)
Looben, can you please upload the test case you have, even if it's not minimized yet?
Flags: needinfo?(loobenyang)
Comment on attachment 8704273 [details] [diff] [review]
P0 Track service worker job done state. r=ehsan

Ehsan pointed out that an install job does not get Cancel() called on it, but the queue is cleared.  This leaves the install job with a dangling pointer to the empty queue.
Attachment #8704273 - Flags: review?(ehsan)
Attachment #8704273 - Attachment is obsolete: true
Attachment #8704273 - Flags: feedback?(loobenyang)
Somewhat speculative without the triggering test, but I think these are all reasonable changes on their own anyway.
Attachment #8706612 - Flags: review?(ehsan)
Passes tests locally, but not sure if its ok to do a try build for a private bug.
(In reply to Ben Kelly [:bkelly] from comment #12)
> Comment on attachment 8704273 [details] [diff] [review]
> P0 Track service worker job done state. r=ehsan
> 
> Ehsan pointed out that an install job does not get Cancel() called on it,
> but the queue is cleared.  This leaves the install job with a dangling
> pointer to the empty queue.
IsRegisterOrInstallJob() returns true for InstallJobs, so we should already be canceling them. Also, job canceling requires clearing domain data, so I don't that's the problem here. Is there Something I'm missing?

Wild guess, but maybe this has something to do with claim calling StopControllingADocument on the registration while it has an installing worker:
https://dxr.mozilla.org/mozilla-central/source/dom/workers/ServiceWorkerManager.cpp#4092
It may be due to the claim path, but I still think these patches are worth doing:

1) We should prevent popping the queue from the wrong job regardless of cause.  Being defensive here is worth it given the job code complexity.
2) We still need to cancel unregister jobs so that they don't try to access mQueue after they have been removed from the queue.
Is this affecting 45 as well? If it is then we should track for 45 as well since this is sec-critical.
Flags: needinfo?(bkelly)
(In reply to Liz Henry (:lizzard) (needinfo? me) from comment #20)
> Is this affecting 45 as well? If it is then we should track for 45 as well
> since this is sec-critical.

Since we still don't have the test case from the reporter its hard to say.  I believe it is probably in 44 and 45, though.
Flags: needinfo?(bkelly)
Tracking for 44 and 45 since they are likely affected and sec-critical. We are getting close to 44 release so this may not make it in.
Personally I think we should close the holes we see by inspection now so it makes 44.  I don't see why we should leave these open even if its not directly the cause of this bug.

Ehsan?
Flags: needinfo?(ehsan)
(In reply to Ben Kelly [:bkelly] from comment #23)
> Personally I think we should close the holes we see by inspection now so it
> makes 44.  I don't see why we should leave these open even if its not
> directly the cause of this bug.

The reason why I'm hesitating here is that I don't want us to land patches in a security sensitive bug that we don't know for sure to fix the original issue.  Therefore I would like us to keep waiting on a test case...

That being said, your patches look worth taking to me.  Perhaps you should move them to a normal bug so that we can review and land them?
Flags: needinfo?(ehsan)
(In reply to :Ehsan Akhgari from comment #11)
> Looben, can you please upload the test case you have, even if it's not
> minimized yet?

Will do
Flags: needinfo?(loobenyang)
(In reply to :Ehsan Akhgari from comment #24)
> That being said, your patches look worth taking to me.  Perhaps you should
> move them to a normal bug so that we can review and land them?

Ben, please let me know how you'd like to proceed!
Flags: needinfo?(bkelly)
I plan to move the current patches to a non-sec bug.  It's next on my list.  I don't think it will be accepted in beta44 at this point though.
Flags: needinfo?(bkelly)
I'm landing the speculative patches in bug 1241531.  Please don't directly link that bug to this one as a dependency or "see also", though.
Attachment #8706607 - Attachment is obsolete: true
Attachment #8706607 - Flags: review?(ehsan)
Attachment #8706608 - Attachment is obsolete: true
Attachment #8706608 - Flags: review?(ehsan)
Attachment #8706609 - Attachment is obsolete: true
Attachment #8706609 - Flags: review?(ehsan)
Attachment #8706612 - Attachment is obsolete: true
Attachment #8706612 - Flags: review?(ehsan)
Steps to reproduce:
1. Run server side script BOF_ServiceWorkerJobQueue_Repro.js in Node.js (node BOF_ServiceWorkerJobQueue_Repro.js ).
2. Enter http://localhost:12345 in Firefox browser.
3. Firefox crashes with memory corruption.

Ran this test case BOF_ServiceWorkerJobQueue_Repro.js with official Linux ASAN build, I got:

Firefox version:  46.0a1 (2015-12-18)

=================================================================
==3427==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7fc5db985a88 at pc 0x7fc5d38f5be2 bp 0x7ffdefee6c50 sp 0x7ffdefee6c48
READ of size 8 at 0x7fc5db985a88 thread T0
    #0 0x7fc5d38f5be1 in ~RefPtr /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/mozilla/RefPtr.h:55
    #1 0x7fc5d38f5be1 in Destruct /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:520
    #2 0x7fc5d38f5be1 in DestructRange /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:2010
    #3 0x7fc5d38f5be1 in RemoveElementsAt /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:1652
    #4 0x7fc5d38f5be1 in RemoveElementAt /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/nsTArray.h:1659
    #5 0x7fc5d38f5be1 in mozilla::dom::workers::ServiceWorkerJobQueue::Pop(mozilla::dom::workers::ServiceWorkerJobQueue::QueueData&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:284
    #6 0x7fc5d38288b7 in Done /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:301
    #7 0x7fc5d38288b7 in Done /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:384
    #8 0x7fc5d38288b7 in mozilla::dom::workers::ServiceWorkerInstallJob::ContinueAfterInstallEvent(bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:1168
    #9 0x7fc5d38f2dc8 in mozilla::dom::workers::ContinueLifecycleRunnable::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:688
    #10 0x7fc5ce225b44 in nsThread::ProcessNextEvent(bool, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/threads/nsThread.cpp:964
    #11 0x7fc5ce2a0d8a in NS_ProcessNextEvent(nsIThread*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/glue/nsThreadUtils.cpp:297
    #12 0x7fc5cebcbec9 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/glue/MessagePump.cpp:95
    #13 0x7fc5ceb393cc in RunInternal /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:234
    #14 0x7fc5ceb393cc in RunHandler /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:227
    #15 0x7fc5ceb393cc in MessageLoop::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:201
    #16 0x7fc5d3da8877 in nsBaseAppShell::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/widget/nsBaseAppShell.cpp:156
    #17 0x7fc5d5bcebf8 in nsAppStartup::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/components/startup/nsAppStartup.cpp:281
    #18 0x7fc5d5ccfce7 in XREMain::XRE_mainRun() /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4277
    #19 0x7fc5d5cd0c9d in XREMain::XRE_main(int, char**, nsXREAppData const*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4374
    #20 0x7fc5d5cd1ade in XRE_main /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4476
    #21 0x48a6c9 in do_main /builds/slave/m-cen-l64-asan-000000000000000/build/src/browser/app/nsBrowserApp.cpp:212
    #22 0x48a6c9 in main /builds/slave/m-cen-l64-asan-000000000000000/build/src/browser/app/nsBrowserApp.cpp:352
    #23 0x7fc5e6c87ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
    #24 0x489c3c in _start (/home/coder/FirefoxBuilds/old/firefox/firefox+0x489c3c)

0x7fc5db985a88 is located 0 bytes to the right of global variable 'nsTArrayHeader::sEmptyHdr' from '/builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/xpcom/build/Unified_cpp_xpcom_build1.cpp' (0x7fc5db985a80) of size 8
SUMMARY: AddressSanitizer: global-buffer-overflow /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dom/workers/../../dist/include/mozilla/RefPtr.h:55 ~RefPtr
Shadow bytes around the buggy address:
  0x0ff93b728b00: 01 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728b10: 01 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728b20: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728b30: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728b40: 04 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
=>0x0ff93b728b50: 00[f9]f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00
  0x0ff93b728b60: 00 00 00 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728b70: 01 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728b80: 01 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728b90: 01 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ff93b728ba0: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
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
  Heap right redzone:      fb
  F==3427==ABORTING
I will test this to see if our speculative patches fixed it.  Probably Tuesday or so.
Flags: needinfo?(bkelly)
Flags: sec-bounty?
I spent a lot of time on Tuesday trying to reproduce with debug mac builds.  I thought I was doing so, but it was actually hitting a separate, unrelated assert.

I will try again with asan builds today now that I am back at a machine with my linux vm.
Looben, I cannot seem to reproduce the crash even on the old asan builds.  I am using the builds from:

  http://archive.mozilla.org/pub/firefox/nightly/2015/12/

I let the test run for 10 to 15 minutes with no crash.  I tried builds ranging from 12/17 to 12/19 since you reported you saw the crash with a 12/18 build.

Perhaps the timing on my machine just fails to trigger the issue.  Could you try testing with a recent nightly build to see if it still triggers for you?
Flags: needinfo?(bkelly) → needinfo?(loobenyang)
(In reply to Ben Kelly [:bkelly] from comment #32)
> Looben, I cannot seem to reproduce the crash even on the old asan builds.  I
> am using the builds from:
> 
>   http://archive.mozilla.org/pub/firefox/nightly/2015/12/
> 
> I let the test run for 10 to 15 minutes with no crash.  I tried builds
> ranging from 12/17 to 12/19 since you reported you saw the crash with a
> 12/18 build.
> 
> Perhaps the timing on my machine just fails to trigger the issue.  Could you
> try testing with a recent nightly build to see if it still triggers for you?

I can trigger the issue in 2016-01-06 ASAN build, but can NOT trigger it with latest ASAN build 47.0a1 (2016-02-09) so far.


Firefox version: 46.0a1 (2016-01-06)

=================================================================
==17107==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7fd1a583b2c8 at pc 0x7fd19d4f9e82 bp 0x7fffb79fd710 sp 0x7fffb79fd708
READ of size 8 at 0x7fd1a583b2c8 thread T0
    #0 0x7fd19d4f9e81 in ~RefPtr /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dist/include/mozilla/RefPtr.h:55
    #1 0x7fd19d4f9e81 in Destruct /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dist/include/nsTArray.h:520
    #2 0x7fd19d4f9e81 in DestructRange /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dist/include/nsTArray.h:2010
    #3 0x7fd19d4f9e81 in RemoveElementsAt /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dist/include/nsTArray.h:1652
    #4 0x7fd19d4f9e81 in RemoveElementAt /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dist/include/nsTArray.h:1659
    #5 0x7fd19d4f9e81 in mozilla::dom::workers::ServiceWorkerJobQueue::Pop(mozilla::dom::workers::ServiceWorkerJobQueue::QueueData&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:284
    #6 0x7fd19d42c95f in Done /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:301
    #7 0x7fd19d42c95f in Done /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:384
    #8 0x7fd19d42c95f in mozilla::dom::workers::ServiceWorkerInstallJob::ContinueAfterInstallEvent(bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:1215
    #9 0x7fd19d4f6b08 in mozilla::dom::workers::ContinueLifecycleRunnable::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/dom/workers/ServiceWorkerManager.cpp:688
    #10 0x7fd197dc1724 in nsThread::ProcessNextEvent(bool, bool*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/threads/nsThread.cpp:989
    #11 0x7fd197e3b31a in NS_ProcessNextEvent(nsIThread*, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/xpcom/glue/nsThreadUtils.cpp:297
    #12 0x7fd19876b149 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/glue/MessagePump.cpp:95
    #13 0x7fd1986d864c in RunInternal /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:234
    #14 0x7fd1986d864c in RunHandler /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:227
    #15 0x7fd1986d864c in MessageLoop::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/ipc/chromium/src/base/message_loop.cc:201
    #16 0x7fd19d9a2567 in nsBaseAppShell::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/widget/nsBaseAppShell.cpp:156
    #17 0x7fd19f7bac08 in nsAppStartup::Run() /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/components/startup/nsAppStartup.cpp:281
    #18 0x7fd19f8bb6ea in XREMain::XRE_mainRun() /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4288
    #19 0x7fd19f8bc95d in XREMain::XRE_main(int, char**, nsXREAppData const*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4385
    #20 0x7fd19f8bd79e in XRE_main /builds/slave/m-cen-l64-asan-000000000000000/build/src/toolkit/xre/nsAppRunner.cpp:4487
    #21 0x48a6c9 in do_main /builds/slave/m-cen-l64-asan-000000000000000/build/src/browser/app/nsBrowserApp.cpp:212
    #22 0x48a6c9 in main /builds/slave/m-cen-l64-asan-000000000000000/build/src/browser/app/nsBrowserApp.cpp:352
    #23 0x7fd1b0b3dec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
    #24 0x489c3c in _start (/home/coder/FirefoxBuilds/new/firefox/firefox+0x489c3c)

0x7fd1a583b2c8 is located 0 bytes to the right of global variable 'nsTArrayHeader::sEmptyHdr' from '/builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/xpcom/build/Unified_cpp_xpcom_build1.cpp' (0x7fd1a583b2c0) of size 8
SUMMARY: AddressSanitizer: global-buffer-overflow /builds/slave/m-cen-l64-asan-000000000000000/build/src/obj-firefox/dist/include/mozilla/RefPtr.h:55 ~RefPtr
Shadow bytes around the buggy address:
  0x0ffab4aff600: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffab4aff610: 01 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9
  0x0ffab4aff620: 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9
  0x0ffab4aff630: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffab4aff640: 00 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9
=>0x0ffab4aff650: 00 f9 f9 f9 f9 f9 f9 f9 00[f9]f9 f9 f9 f9 f9 f9
  0x0ffab4aff660: 00 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9
  0x0ffab4aff670: 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9
  0x0ffab4aff680: 01 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9
  0x0ffab4aff690: 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9
  0x0ffab4aff6a0: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
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
  Heap right redzone:      fb
  F==17107==ABORTING
coder@TheCoderPC:~/FirefoxBuilds/new/firefox$
Flags: needinfo?(loobenyang)
Thanks!  I think we can probably conclude the patches in bug 1241531 fixed the issue.  They are landed in FF45 beta and released in 4 weeks.

Not sure how to mark this bug, though, since I don't want to dupe to the non-secure bug.
Thanks everybody for looking into this.
Status: ASSIGNED → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
Whiteboard: [fixed bug 1241531]
(This was fixed by a public bug, but the issue here was reported first.)
Flags: sec-bounty? → sec-bounty+
Group: dom-core-security → core-security-release
Whiteboard: [fixed bug 1241531] → [fixed bug 1241531][adv-main45+]
Alias: CVE-2016-1959
I've been trying to reproduce the original asan crash with the poc from comment # 29 without any luck. I've been running the poc under a Ubuntu 14.04.4 x64 VM for about 20 minutes per each build that I've listed below. After running the poc for about 15 minutes per build, the following message will be spammed into the terminal:

* IPDL protocol error: [PBackgroundChild] Received an invalid file descriptor!

Once the above message starts appearing in the terminal, the tab will sometimes crash after about 5-10 minutes with the poc still running.

ASAN:SIGSEGV
=================================================================
==9622==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000048e1de sp 0x7fb7756c5d40 bp 0x7fb7756c5d50 T2)

###!!! [Parent][MessageChannel] Error: (msgtype=0x2A0081,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv

    #0 0x48e1dd in mozalloc_abort mozalloc_abort.cpp:33
    #1 0x7fb783b21a45 in Abort nsDebugImpl.cpp:452
    #2 0x7fb783b2170e in NS_DebugBreak nsDebugImpl.cpp:404
    #3 0x7fb7845ed646 in OnChannelErrorFromLink MessageChannel.cpp:1765
    #4 0x7fb7845f2320 in OnChannelError MessageLink.cpp:429
    #5 0x7fb7845b74e2 in event_process_active_single_queue event.c:1350
    #6 0x7fb7845656ac in Run message_pump_libevent.cc:362
    #7 0x7fb78456020c in RunInternal message_loop.cc:234
    #8 0x7fb784578ac3 in ThreadMain thread.cc:172
    #9 0x7fb78457a37c in ThreadFunc platform_thread_posix.cc:39
    #10 0x7fb791bc5181 in start_thread pthread_create.c:312 (discriminator 2)
    #11 0x7fb78163b47c in clone clone.S:111

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
Thread T2 (Chrome_ChildThr) created by T0 (Web Content) here:
    #0 0x461945 in __interceptor_pthread_create _asan_rtl_
    #1 0x7fb7845786a4 in CreateThread platform_thread_posix.cc:144
    #2 0x7fb7845f3fab in ProcessChild ProcessChild.cpp:22
    #3 0x7fb78b7029d0 in operator new ContentProcess.h:28
    #4 0x48d760 in content_process_main plugin-container.cpp:237
    #5 0x7fb781562ec4 in __libc_start_main libc-start.c:287

==9622==ABORTING

Looben, how long does it usually take to trigger the crash? Perhaps I'm doing something different?

Builds Used:

* https://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-linux64-asan/1452091748/
* https://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-linux64-asan/1449925892/
* https://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-linux64-asan/1450448759/
Flags: needinfo?(loobenyang)
Keywords: testcase-wanted
Forgot to mention that I marked fx47 as verified due to the confirmation in comment # 32.
(In reply to Kamil Jozwiak [:kjozwiak] from comment #37)
> I've been trying to reproduce the original asan crash with the poc from
> comment # 29 without any luck. I've been running the poc under a Ubuntu
> 14.04.4 x64 VM for about 20 minutes per each build that I've listed below.
> After running the poc for about 15 minutes per build, the following message
> will be spammed into the terminal:
> 
> * IPDL protocol error: [PBackgroundChild] Received an invalid file
> descriptor!
> 
> Once the above message starts appearing in the terminal, the tab will
> sometimes crash after about 5-10 minutes with the poc still running.
> 
> ASAN:SIGSEGV
> =================================================================
> ==9622==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
> 0x00000048e1de sp 0x7fb7756c5d40 bp 0x7fb7756c5d50 T2)
> 
> ###!!! [Parent][MessageChannel] Error:
> (msgtype=0x2A0081,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv
> 
>     #0 0x48e1dd in mozalloc_abort mozalloc_abort.cpp:33
>     #1 0x7fb783b21a45 in Abort nsDebugImpl.cpp:452
>     #2 0x7fb783b2170e in NS_DebugBreak nsDebugImpl.cpp:404
>     #3 0x7fb7845ed646 in OnChannelErrorFromLink MessageChannel.cpp:1765
>     #4 0x7fb7845f2320 in OnChannelError MessageLink.cpp:429
>     #5 0x7fb7845b74e2 in event_process_active_single_queue event.c:1350
>     #6 0x7fb7845656ac in Run message_pump_libevent.cc:362
>     #7 0x7fb78456020c in RunInternal message_loop.cc:234
>     #8 0x7fb784578ac3 in ThreadMain thread.cc:172
>     #9 0x7fb78457a37c in ThreadFunc platform_thread_posix.cc:39
>     #10 0x7fb791bc5181 in start_thread pthread_create.c:312 (discriminator 2)
>     #11 0x7fb78163b47c in clone clone.S:111
> 
> AddressSanitizer can not provide additional info.
> SUMMARY: AddressSanitizer: SEGV ??:0 ??
> Thread T2 (Chrome_ChildThr) created by T0 (Web Content) here:
>     #0 0x461945 in __interceptor_pthread_create _asan_rtl_
>     #1 0x7fb7845786a4 in CreateThread platform_thread_posix.cc:144
>     #2 0x7fb7845f3fab in ProcessChild ProcessChild.cpp:22
>     #3 0x7fb78b7029d0 in operator new ContentProcess.h:28
>     #4 0x48d760 in content_process_main plugin-container.cpp:237
>     #5 0x7fb781562ec4 in __libc_start_main libc-start.c:287
> 
> ==9622==ABORTING
> 
> Looben, how long does it usually take to trigger the crash? Perhaps I'm
> doing something different?
> 
> Builds Used:
> 
> *
> https://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-
> linux64-asan/1452091748/
> *
> https://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-
> linux64-asan/1449925892/
> *
> https://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-
> linux64-asan/1450448759/

It may take a few minutes to one hour to trigger.
Flags: needinfo?(loobenyang)
Whiteboard: [fixed bug 1241531][adv-main45+] → [fixed in bug 1241531][adv-main45+]
(In reply to Looben Yang from comment #39)
> It may take a few minutes to one hour to trigger.

I tried running the poc for several hours with the three builds that I mentioned in comment # 37. Closest thing to an asan crash that I received was the one that I mentioned in comment # 37.
I assume comment 28 no longer applies now that we've shipped this fix: setting the dependency to later bug archeology.
Depends on: 1241531
Whiteboard: [fixed in bug 1241531][adv-main45+] → [fixed in bug 1241531][adv-main45+][post-critsmash-triage]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: