Closed Bug 894348 Opened 11 years ago Closed 11 years ago

MediaRecorder use-after-free crash [@mozilla::MediaStream::GraphImpl]

Categories

(Core :: Audio/Video: Recording, defect)

x86_64
macOS
defect
Not set
critical

Tracking

()

VERIFIED FIXED
mozilla25
Tracking Status
firefox22 --- unaffected
firefox23 --- unaffected
firefox24 --- unaffected
firefox25 --- fixed
firefox-esr17 --- unaffected
b2g18 --- unaffected
b2g18-v1.0.0 --- unaffected
b2g18-v1.0.1 --- unaffected
b2g-v1.1hd --- unaffected

People

(Reporter: posidron, Assigned: rlin)

References

Details

(4 keywords)

Attachments

(3 files, 3 obsolete files)

Attached file testcase
alloc & free: dom/bindings/MediaRecorderBinding.cpp:356

  static bool
  start(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::MediaRecorder* self, const JSJitMethodCallArgs& args)
  {
    Optional<int32_t > arg0;
    if (0 < args.length()) {
      arg0.Construct();
      if (!ValueToPrimitive<int32_t, eDefault>(cx, args.handleAt(0), &arg0.Value())) {
        return false;
      }
    }
    ErrorResult rv;
*   self->Start(Constify(arg0), rv);
[...]


re-use: content/media/MediaStreamGraph.cpp:1495

  MediaStream::GraphImpl()
  {
*    return mGraph;
  }


Tested with http://hg.mozilla.org/integration/mozilla-inbound/rev/860f92c88a13
Attached file callstack
Keywords: sec-critical
Hi Christoph, 
It seems like a F5 reload stress test, right?
Attached patch patch v1 with test case (obsolete) — Splinter Review
oh, wrong usage of poniter....
BTW, Do you know how to test this behavior with mochitest?
Attachment #777631 - Flags: feedback?(roc)
(In reply to Randy Lin [:rlin] from comment #3)
> BTW, Do you know how to test this behavior with mochitest?

Not really, let's Cc Jason Smith.
(In reply to Randy Lin [:rlin] from comment #2)
> Hi Christoph, 
> It seems like a F5 reload stress test, right?

In my tries, only one reload was necessary.
Comment on attachment 777631 [details] [diff] [review]
patch v1 with test case

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

The code change is correct (ew!) but the test doesn't work since it will constantly reload.

You could try making the reference to the MediaRecorder be a local variable in a function that you call once. After the function is called, do SpecialPowers.gc() and that should destroy the ProcessedMediaStream too early. Hopefully that would make us crash most of the time.
Attachment #777631 - Flags: feedback?(roc) → feedback+
Blocks: 803414
Blocks: 894413
(In reply to Robert O'Callahan (:roc) (Mozilla Corporation) from comment #6)
> Comment on attachment 777631 [details] [diff] [review]
> patch v1 with test case
> 
> Review of attachment 777631 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> The code change is correct (ew!) but the test doesn't work since it will
> constantly reload.
> 
> You could try making the reference to the MediaRecorder be a local variable
> in a function that you call once. After the function is called, do
> SpecialPowers.gc() and that should destroy the ProcessedMediaStream too
> early. Hopefully that would make us crash most of the time.

Another idea I have would be to do this with a crash test and local storage to re-run the same crashtest a few times on each reload.

See http://hg.mozilla.org/mozilla-central/file/16375716cc69/dom/media/tests/crashtests/801227.html as an example of a crashtest that demonstrated a way to do this.
Nice work. Does this affect any branches?
(In reply to David Bolter [:davidb] from comment #8)
> Nice work. Does this affect any branches?

Should only be affecting trunk. The Media Recorder API landed in the Firefox 25 timeframe.
Attached patch patvh v2 (obsolete) — Splinter Review
Use for loop and force gc to capture this crash.
Attachment #777631 - Attachment is obsolete: true
Attachment #778248 - Flags: review?(roc)
Comment on attachment 778248 [details] [diff] [review]
patvh v2

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

Can kick off a try run with this? This is the first time we are checking in a MediaRecorder test into the tree, so there potentially could be other failures we might see on try.

::: content/media/test/test-MediaRecorder-reload.html
@@ +28,5 @@
> +    try { o1 = o0.mozCaptureStreamUntilEnded(); } catch(e) { }
> +    try { o2 = new MediaRecorder(o1) } catch(e) { }
> +    try { o2.start(2048) } catch(e) { }
> +    try { o2.start(0) } catch(e) { }
> +    SpecialPowers.gc();

Did you confirm this test invokes the crash without your fix applied?

@@ +30,5 @@
> +    try { o2.start(2048) } catch(e) { }
> +    try { o2.start(0) } catch(e) { }
> +    SpecialPowers.gc();
> +  }
> +  ok(true, "pass the crash test");

If you are intending to do a crashtest, why not actually use the framework here?
Attachment #778248 - Flags: review+ → review?(roc)
Comment on attachment 778248 [details] [diff] [review]
patvh v2

Ack. Bugzilla conflict. Sorry about that.
Attachment #778248 - Flags: review?(roc) → review+
(In reply to Jason Smith [:jsmith] from comment #11)
> Comment on attachment 778248 [details] [diff] [review]
> patvh v2
> 
> Review of attachment 778248 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> Can kick off a try run with this? This is the first time we are checking in
> a MediaRecorder test into the tree, so there potentially could be other
> failures we might see on try.
> 
> ::: content/media/test/test-MediaRecorder-reload.html
> @@ +28,5 @@
> > +    try { o1 = o0.mozCaptureStreamUntilEnded(); } catch(e) { }
> > +    try { o2 = new MediaRecorder(o1) } catch(e) { }
> > +    try { o2.start(2048) } catch(e) { }
> > +    try { o2.start(0) } catch(e) { }
> > +    SpecialPowers.gc();
> 
> Did you confirm this test invokes the crash without your fix applied?
> 
> @@ +30,5 @@
> > +    try { o2.start(2048) } catch(e) { }
> > +    try { o2.start(0) } catch(e) { }
> > +    SpecialPowers.gc();
> > +  }
> > +  ok(true, "pass the crash test");
> 
> If you are intending to do a crashtest, why not actually use the framework
> here?

I have tested this before apply the fix and can capture this crash.
Oh, more crash was found after run test case on different platform, I will fix it also.
https://tbpl.mozilla.org/?tree=Try&rev=919b234f6115
Thanks for doing that try run - good to see we found more crashes.

Crash info from try run:

PROCESS-CRASH | Shutdown | application crashed [@ nsTArray_Impl<nsAutoPtr<mozilla::DOMMediaStream::OnTracksAvailableCallback>, nsTArrayInfallibleAllocator>::Clear()]

03:52:59 WARNING - PROCESS-CRASH | Shutdown | application crashed [@ mozilla::DOMMediaStream::NotifyMediaStreamGraphShutdown()]

04:13:36 WARNING - PROCESS-CRASH | Shutdown | application crashed [@ nsAutoPtr<mozilla::DOMMediaStream::OnTracksAvailableCallback>::`scalar deleting destructor'(unsigned int) + 0xc] 

03:19:18 WARNING - PROCESS-CRASH | Shutdown | application crashed [@ 0x7b68404a]

03:50:37 WARNING - PROCESS-CRASH | Shutdown | application crashed [@ nsTArray_Impl<nsAutoPtr<mozilla::DOMMediaStream::OnTracksAvailableCallback>, nsTArrayInfallibleAllocator>::RemoveElementsAt(unsigned int, unsigned int)]
Attached patch patch v3 (obsolete) — Splinter Review
Fix crash, also fix memory leaks problem.
try result.
https://tbpl.mozilla.org/?tree=Try&rev=9a3bea311de9
Attachment #778248 - Attachment is obsolete: true
Attachment #778862 - Flags: review?(roc)
Comment on attachment 778862 [details] [diff] [review]
patch v3

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

::: content/media/MediaRecorder.cpp
@@ +115,5 @@
>  
>  MediaRecorder::~MediaRecorder()
>  {
> +  if (mTrackUnionStream)
> +    mTrackUnionStream->Destroy();

{}
Attachment #778862 - Flags: review?(roc) → review+
Attached patch check-in.patchSplinter Review
carry reviewer, fix nits.
Attachment #778862 - Attachment is obsolete: true
This needs sec-approval, no?
Keywords: checkin-needed
(In reply to Ryan VanderMeulen [:RyanVM UTC-4] from comment #19)
> This needs sec-approval, no?

MediaRecorder currently only exists on trunk. According to my understanding of <https://wiki.mozilla.org/Security/Bug_Approval_Process>, that means it does not need sec-approval. I'll leave it up to rlin if he wants to ask for it anyway.
Confirmed that with dveditz. I'll land next time I get a chance.
Keywords: checkin-needed
Thanks Timothy, The mediaRecorder only affect the trunk right now.
No longer blocks: 803414
https://hg.mozilla.org/mozilla-central/rev/2e6ca2dc655e
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla25
Verified via mochitest on landing.
Status: RESOLVED → VERIFIED
Component: Video/Audio → Video/Audio: Recording
No longer blocks: MediaRecording
Group: core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: