Closed Bug 875402 Opened 12 years ago Closed 11 years ago

WebAudio use-after-free crash [@mozilla::MediaInputPort::Release]

Categories

(Core :: Web Audio, defect)

x86_64
macOS
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla24
Tracking Status
firefox21 --- unaffected
firefox22 --- disabled
firefox23 - disabled
firefox24 + fixed
firefox-esr17 --- unaffected
b2g18 --- unaffected

People

(Reporter: posidron, Assigned: ehsan.akhgari)

References

Details

(4 keywords, Whiteboard: [adv-main24-])

Attachments

(6 files, 1 obsolete file)

Attached file testcase (deleted) —
If the testcase doesn't trigger at the first try, refresh the page one or two times. alloc: ./content/media/webaudio/AudioNode.cpp:174 void AudioNode::Connect(AudioNode& aDestination, uint32_t aOutput, uint32_t aInput, ErrorResult& aRv) { [...] * ps->AllocateInputPort(mStream, MediaInputPort::FLAG_BLOCK_INPUT, static_cast<uint16_t>(aInput), static_cast<uint16_t>(aOutput)); [...] free: ./content/media/MediaStreamGraph.cpp:1882 void MediaInputPort::Destroy() { class Message : public ControlMessage { public: Message(MediaInputPort* aPort) : ControlMessage(nullptr), mPort(aPort) {} virtual void Run() { mPort->Disconnect(); --mPort->GraphImpl()->mPortCount; * NS_RELEASE(mPort); } [...] } re-use: ./content/media/MediaStreamGraph.h:737 * NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaInputPort) Tested with m-i changeset: 132784:57f555f96ac9 and the patch in bug 874952
Summary: WebAudio use-after-free crash [@] → WebAudio use-after-free crash [@mozilla::MediaInputPort::Release]
Attached file callstack (deleted) —
Assignee: nobody → ehsan
OK, so MediaInputPort::Destroy::Command holds a plain pointer to MediaInputPort, and NS_RELEASES it directly, claiming that the graph is the last thing holding on to the MediaInputPort. That is completely incorrect. You can allocate an input port and hold on to it as much as you want.
And FWIW, this bug should have been discovered before by fuzzing WebRTC etc, I would have expected.
I doubt the sequence that causes this is possible in webrtc, which only uses MediaInputPorts as part of nsDOMUserMediaStream in MediaManager.cpp (aka getUserMedia). The failure paths there are minimal, and it's closely tied to the associated MediaStream/TrackUnion.
After fixing that part of the bug, I hit bug 875221 on this test case.
Depends on: 875221
(In reply to Randell Jesup [:jesup] from comment #5) > I doubt the sequence that causes this is possible in webrtc, which only uses > MediaInputPorts as part of nsDOMUserMediaStream in MediaManager.cpp (aka > getUserMedia). The failure paths there are minimal, and it's closely tied > to the associated MediaStream/TrackUnion. Hmm, actually, maybe this is only an issue for the non-realtime MSGs...
Attached patch Patch (v1) (obsolete) (deleted) — Splinter Review
Attachment #753493 - Flags: review?(roc)
Comment on attachment 753493 [details] [diff] [review] Patch (v1) Review of attachment 753493 [details] [diff] [review]: ----------------------------------------------------------------- ::: content/media/MediaStreamGraph.cpp @@ +1906,5 @@ > virtual void RunDuringShutdown() > { > Run(); > } > + nsRefPtr<MediaInputPort> mPort; This is going to leak since you're adding a reference we weren't adding before. The comment is definitely wrong, but I'm not sure why the NS_RELEASE is wrong. We need to release the MediaStreamGraph's reference to the port.
Hmm, I think you're right. For some reason the leak detector doesn't detect that. :( So perhaps the real problem here is that mConsumers holds weak pointers to MediaInputPorts, and everything else holds a strong reference to it. If we made those nsRefPtrs, we should be able to remove this NS_RELEASE and just make the ControlCommand hold a normal nsRefPtr. Does that make sense?
Flags: needinfo?(roc)
Read the comment on MediaInputPort in MediaStreamGraph.h :-) Note that in ProcessedMediaStream::AllocateInputPort, in the Run method that runs in the MediaStreamGraph thread, we have // The graph holds its reference implicitly mPort.forget(); So the already_AddRefed we throw away there is supposed to be released by the NS_RELEASE we're doing in Destroy's Run method. There shouldn't be a need to use nsRefPtrs actually inside the MediaStreamGraph. So, I don't know why this code isn't working.
Flags: needinfo?(roc)
Attached file testcase-reduced (deleted) —
OK, so the problem here is that if ProcessedMediaStream::AllocateInputPort::Command is run during shutdown, it Release()'s mPort without registering it with the graph, and then later on we NS_RELEASE the pointer because we think that the graph is holding a reference to it, while it's not.
Attached patch Patch (v2) (deleted) — Splinter Review
Attachment #753493 - Attachment is obsolete: true
Attachment #753493 - Flags: review?(roc)
Attachment #753822 - Flags: review?(roc)
Attached file callstack with patch v2 (deleted) —
With the patch v2, we seem to hit another bug with this callstack...
Christoph, can you please see if you can minimize the test case once more with this patch applied?
Flags: needinfo?(cdiehl)
:Ehsan, I have noticed something similar, see: https://bugzilla.mozilla.org/show_bug.cgi?id=875221#c6 Yes, give me a few minutes.
Flags: needinfo?(cdiehl)
Attached file testcase-reduced-after-patch-2 (deleted) —
(In reply to Christoph Diehl [:cdiehl] from comment #18) > Created attachment 753840 [details] > testcase-reduced-after-patch-2 Attached this to bug 875221.
Depends on: 875911
The leak is bug 875911.
Landed with the fix to bug 875911 and converted the test to a mochitest to use SpecialPowers instead of fuzzPriv to force GC and CC.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla24
Mass moving Web Audio bugs to the Web Audio component. Filter on duckityduck.
Component: Video/Audio → Web Audio
No longer tracking for FF23
Whiteboard: [adv-main24-]
Group: core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: