Closed Bug 788950 (CVE-2012-4182) Opened 12 years ago Closed 12 years ago

Heap-use-after-free in nsTextEditRules::WillInsert

Categories

(Core :: DOM: Editor, defect)

x86_64
All
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla18
Tracking Status
firefox16 + fixed
firefox17 + fixed
firefox18 + fixed
firefox-esr10 16+ fixed

People

(Reporter: inferno, Assigned: ayg)

Details

(5 keywords, Whiteboard: [asan][advisory-tracking+])

Attachments

(2 files)

Reproduces on trunk, testcase coming.

=================================================================
==8725== ERROR: AddressSanitizer heap-use-after-free on address 0x7fc077a478c8 at pc 0x7fc0968060e3 bp 0x7fffd39b4db0 sp 0x7fffd39b4da8
READ of size 8 at 0x7fc077a478c8 thread T0
    #0 0x7fc0968060e2 in nsCOMPtr_base::assign_assuming_AddRef(nsISupports*) src/../../../dist/include/nsCOMPtr.h:435
    #1 0x7fc0a2fbef23 in nsCOMPtr_base::assign_with_AddRef(nsISupports*) src/objdir-ff-asan-sym/xpcom/build/nsCOMPtr.cpp:49
    #2 0x7fc09833dd72 in nsCOMPtr<nsIDOMNode>::operator=(nsIDOMNode*) src/../../../dist/include/nsCOMPtr.h:622
    #3 0x7fc09c964e46 in nsTextEditRules::WillInsert(nsISelection*, bool*) src/editor/libeditor/text/nsTextEditRules.cpp:327
    #4 0x7fc09d002775 in nsHTMLEditRules::WillInsert(nsISelection*, bool*) src/editor/libeditor/html/nsHTMLEditRules.cpp:1187
    #5 0x7fc09cfb5e12 in nsHTMLEditRules::WillDoAction(mozilla::Selection*, nsRulesInfo*, bool*, bool*) src/editor/libeditor/html/nsHTMLEditRules.cpp:618
    #6 0x7fc09ce3358b in nsHTMLEditor::DoInsertHTMLWithContext(nsAString_internal const&, nsAString_internal const&, nsAString_internal const&, nsAString_internal const&, nsIDOMDocument*, nsIDOMNode*, int, bool, bool) src/editor/libeditor/html/nsHTMLDataTransfer.cpp:391
    #7 0x7fc09ce2eb7e in nsHTMLEditor::InsertHTMLWithContext(nsAString_internal const&, nsAString_internal const&, nsAString_internal const&, nsAString_internal const&, nsIDOMDocument*, nsIDOMNode*, int, bool) src/editor/libeditor/html/nsHTMLDataTransfer.cpp:229
    #8 0x7fc09ce2e42c in nsHTMLEditor::InsertHTML(nsAString_internal const&) src/editor/libeditor/html/nsHTMLDataTransfer.cpp:214
    #9 0x7fc09ce2e4ee in non-virtual thunk to nsHTMLEditor::InsertHTML(nsAString_internal const&) src/gfx/cairo/cairo/src/cairo-surface-subsurface.c:0
    #10 0x7fc0a04c52d9 in nsInsertHTMLCommand::DoCommandParams(char const*, nsICommandParams*, nsISupports*) src/editor/composer/src/nsComposerCommands.cpp:1335
    #11 0x7fc09fd13f91 in nsControllerCommandTable::DoCommandParams(char const*, nsICommandParams*, nsISupports*) src/embedding/components/commandhandler/src/nsControllerCommandTable.cpp:175
    #12 0x7fc09fce7262 in nsBaseCommandController::DoCommandWithParams(char const*, nsICommandParams*) src/embedding/components/commandhandler/src/nsBaseCommandController.cpp:153
    #13 0x7fc09fce7536 in non-virtual thunk to nsBaseCommandController::DoCommandWithParams(char const*, nsICommandParams*) src/gfx/cairo/cairo/src/cairo-surface-subsurface.c:0
    #14 0x7fc09fcfdb4f in nsCommandManager::DoCommand(char const*, nsICommandParams*, nsIDOMWindow*) src/embedding/components/commandhandler/src/nsCommandManager.cpp:234
    #15 0x7fc09b2a7418 in nsHTMLDocument::ExecCommand(nsAString_internal const&, bool, nsAString_internal const&, bool*) src/content/html/document/src/nsHTMLDocument.cpp:3232
    #16 0x7fc09b2a8d6d in non-virtual thunk to nsHTMLDocument::ExecCommand(nsAString_internal const&, bool, nsAString_internal const&, bool*) src/gfx/cairo/cairo/src/cairo-surface-subsurface.c:0
    #17 0x7fc0a345e807 in NS_InvokeByIndex_P src/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp:162
    #18 0x7fc09e8bae7e in CallMethodHelper::Invoke() src/js/xpconnect/src/XPCWrappedNative.cpp:3105
    #19 0x7fc09e91d995 in XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) src/js/xpconnect/src/XPCWrappedNativeJSOps.cpp:1470
    #20 0x7fc0a9a40051 in js::CallJSNative(JSContext*, int (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) src/js/src/jscntxtinlines.h:372
    #21 0x7fc0a99cd281 in js::Interpret(JSContext*, js::StackFrame*, js::InterpMode) src/js/src/jsinterp.cpp:2405
    #22 0x7fc0a99342c2 in js::RunScript(JSContext*, JSScript*, js::StackFrame*) src/js/src/jsinterp.cpp:301
    #23 0x7fc0a9a4d386 in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value const&, js::ExecuteType, js::StackFrame*, JS::Value*) src/js/src/jsinterp.cpp:486
    #24 0x7fc0a9a4f33e in js::Execute(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value*) src/js/src/jsinterp.cpp:523
    #25 0x7fc0a91a14b4 in JS::Evaluate(JSContext*, JS::Handle<JSObject*>, JS::CompileOptions, unsigned short const*, unsigned long, JS::Value*) src/js/src/jsapi.cpp:5702
    #26 0x7fc09ba3f85d in nsJSContext::EvaluateString(nsAString_internal const&, JSObject*, nsIPrincipal*, nsIPrincipal*, char const*, unsigned int, JSVersion, nsAString_internal*, bool*) src/dom/base/nsJSEnvironment.cpp:1499
    #27 0x7fc09bbef6cf in nsGlobalWindow::RunTimeoutHandler(nsTimeout*, nsIScriptContext*) src/dom/base/nsGlobalWindow.cpp:9590
    #28 0x7fc09bba7049 in nsGlobalWindow::RunTimeout(nsTimeout*) src/dom/base/nsGlobalWindow.cpp:9851
    #29 0x7fc09bbed72a in nsGlobalWindow::TimerCallback(nsITimer*, void*) src/dom/base/nsGlobalWindow.cpp:10118
    #30 0x7fc0a33a0af2 in nsTimerImpl::Fire() src/xpcom/threads/nsTimerImpl.cpp:473
    #31 0x7fc0a33a23a8 in nsTimerEvent::Run() src/xpcom/threads/nsTimerImpl.cpp:556
    #32 0x7fc0a336578e in nsThread::ProcessNextEvent(bool, bool*) src/xpcom/threads/nsThread.cpp:624
    #33 0x7fc0a3006b67 in NS_ProcessNextEvent_P(nsIThread*, bool) src/objdir-ff-asan-sym/xpcom/build/nsThreadUtils.cpp:220
    #34 0x7fc0a1dc3625 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) src/ipc/glue/MessagePump.cpp:82
    #35 0x7fc0a3610389 in MessageLoop::RunInternal() src/ipc/chromium/src/base/message_loop.cc:208
    #36 0x7fc0a36101d2 in MessageLoop::RunHandler() src/ipc/chromium/src/base/message_loop.cc:201
    #37 0x7fc0a36100b7 in MessageLoop::Run() src/ipc/chromium/src/base/message_loop.cc:175
    #38 0x7fc0a12884ce in nsBaseAppShell::Run() src/widget/xpwidgets/nsBaseAppShell.cpp:163
    #39 0x7fc09fee89b8 in nsAppStartup::Run() src/toolkit/components/startup/nsAppStartup.cpp:273
    #40 0x7fc0966e81a0 in XREMain::XRE_mainRun() src/toolkit/xre/nsAppRunner.cpp:3835
    #41 0x7fc0966ee414 in XREMain::XRE_main(int, char**, nsXREAppData const*) src/toolkit/xre/nsAppRunner.cpp:3912
    #42 0x7fc0966f14de in XRE_main src/toolkit/xre/nsAppRunner.cpp:3988
    #43 0x40c5bb in do_main(int, char**) src/browser/app/nsBrowserApp.cpp:174
    #44 0x409e1f in main src/browser/app/nsBrowserApp.cpp:279
    #45 0x7fc0b322bc4d in ?? ??:0
0x7fc077a478c8 is located 72 bytes inside of 1096-byte region [0x7fc077a47880,0x7fc077a47cc8)
freed by thread T0 here:
    #0 0x4c3e30 in free ??:0
    #1 0x7fc0b00c9572 in moz_free src/memory/mozalloc/mozalloc.cpp:51
    #2 0x7fc09cf911c5 in operator delete(void*) src/../../../dist/include/mozilla/mozalloc.h:224
    #3 0x7fc09c94e627 in nsTextEditRules::Release() src/editor/libeditor/text/nsTextEditRules.cpp:93
    #4 0x7fc09cf918d3 in nsHTMLEditRules::Release() src/editor/libeditor/html/nsHTMLEditRules.cpp:220
    #5 0x7fc096806070 in nsCOMPtr_base::assign_assuming_AddRef(nsISupports*) src/../../dist/include/nsCOMPtr.h:440
    #6 0x7fc0a2fbef23 in nsCOMPtr_base::assign_with_AddRef(nsISupports*) src/objdir-ff-asan-sym/xpcom/build/nsCOMPtr.cpp:49
    #7 0x7fc09c917a42 in nsCOMPtr<nsIEditRules>::operator=(nsIEditRules*) src/../../../dist/include/nsCOMPtr.h:622
    #8 0x7fc09cea5c29 in nsHTMLEditor::InitRules() src/editor/libeditor/html/nsHTMLEditor.cpp:488
    #9 0x7fc09c91a35f in nsPlaintextEditor::EndEditorInit() src/editor/libeditor/text/nsPlaintextEditor.cpp:200
    #10 0x7fc09c94ba3d in ~nsAutoEditInitRulesTrigger src/editor/libeditor/text/nsTextEditUtils.cpp:94
    #11 0x7fc09cea0e60 in nsHTMLEditor::Init(nsIDOMDocument*, nsIContent*, nsISelectionController*, unsigned int) src/editor/libeditor/html/nsHTMLEditor.cpp:289
    #12 0x7fc0a04f6b0e in nsEditingSession::SetupEditorOnWindow(nsIDOMWindow*) src/editor/composer/src/nsEditingSession.cpp:460
    #13 0x7fc0a04ec567 in nsEditingSession::MakeWindowEditable(nsIDOMWindow*, char const*, bool, bool, bool) src/editor/composer/src/nsEditingSession.cpp:173
    #14 0x7fc09b277320 in nsHTMLDocument::EditingStateChanged() src/content/html/document/src/nsHTMLDocument.cpp:2693
    #15 0x7fc09b274859 in nsHTMLDocument::BeginLoad() src/content/html/document/src/nsHTMLDocument.cpp:880
    #16 0x7fc09cd0ac82 in nsHtml5TreeOpExecutor::WillBuildModel(nsDTDMode) src/parser/html/nsHtml5TreeOpExecutor.cpp:116
    #17 0x7fc09cafcd0b in nsHtml5Parser::Parse(nsAString_internal const&, void*, nsACString_internal const&, bool, nsDTDMode) src/parser/html/nsHtml5Parser.cpp:231
    #18 0x7fc09b28eb20 in nsHTMLDocument::WriteCommon(JSContext*, nsAString_internal const&, bool) src/content/html/document/src/nsHTMLDocument.cpp:1736
    #19 0x7fc09b28fa95 in nsHTMLDocument::Write(nsAString_internal const&, JSContext*) src/content/html/document/src/nsHTMLDocument.cpp:1749
    #20 0x7fc09eb0f571 in nsIDOMHTMLDocument_Write(JSContext*, unsigned int, JS::Value*) src/objdir-ff-asan-sym/js/xpconnect/src/dom_quickstubs.cpp:13713
    #21 0x7fc0a9a40051 in js::CallJSNative(JSContext*, int (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) src/js/src/jscntxtinlines.h:372
    #22 0x7fc0a92d143c in js::Invoke(JSContext*, js::InvokeArgsGuard&, js::MaybeConstruct) src/js/src/jsinterp.h:119
    #23 0x7fc0a9a45a0b in js::Invoke(JSContext*, JS::Value const&, JS::Value const&, unsigned int, JS::Value*, JS::Value*) src/js/src/jsinterp.cpp:388
    #24 0x7fc0a9eb7877 in js::IndirectProxyHandler::call(JSContext*, JSObject*, unsigned int, JS::Value*) src/js/src/jsproxy.cpp:451
    #25 0x7fc0aa6d01c0 in js::DirectWrapper::call(JSContext*, JSObject*, unsigned int, JS::Value*) src/js/src/jswrapper.cpp:316
    #26 0x7fc0aa6e1385 in js::CrossCompartmentWrapper::call(JSContext*, JSObject*, unsigned int, JS::Value*) src/js/src/jswrapper.cpp:648
    #27 0x7fc0aa6e1a54 in non-virtual thunk to js::CrossCompartmentWrapper::call(JSContext*, JSObject*, unsigned int, JS::Value*) ??:0
    #28 0x7fc0a9f428bd in js::Proxy::call(JSContext*, JSObject*, unsigned int, JS::Value*) src/js/src/jsproxy.cpp:2457
    #29 0x7fc0a9f5cbcd in proxy_Call(JSContext*, unsigned int, JS::Value*) src/js/src/jsproxy.cpp:2990
previously allocated by thread T0 here:
    #0 0x4c3ef0 in __interceptor_malloc ??:0
    #1 0x7fc0b00c96c6 in moz_xmalloc src/memory/mozalloc/mozalloc.cpp:57
    #2 0x7fc09cea5c0a in operator new(unsigned long) src/../../../dist/include/mozilla/mozalloc.h:200
    #3 0x7fc09c91a35f in nsPlaintextEditor::EndEditorInit() src/editor/libeditor/text/nsPlaintextEditor.cpp:200
    #4 0x7fc09c94ba3d in ~nsAutoEditInitRulesTrigger src/editor/libeditor/text/nsTextEditUtils.cpp:94
    #5 0x7fc09cea0e60 in nsHTMLEditor::Init(nsIDOMDocument*, nsIContent*, nsISelectionController*, unsigned int) src/editor/libeditor/html/nsHTMLEditor.cpp:289
    #6 0x7fc0a04f6b0e in nsEditingSession::SetupEditorOnWindow(nsIDOMWindow*) src/editor/composer/src/nsEditingSession.cpp:460
    #7 0x7fc0a04ec567 in nsEditingSession::MakeWindowEditable(nsIDOMWindow*, char const*, bool, bool, bool) src/editor/composer/src/nsEditingSession.cpp:173
    #8 0x7fc09b277320 in nsHTMLDocument::EditingStateChanged() src/content/html/document/src/nsHTMLDocument.cpp:2693
    #9 0x7fc09b29ad34 in nsHTMLDocument::MaybeEditingStateChanged() src/content/html/document/src/nsHTMLDocument.cpp:2339
    #10 0x7fc09b29b4e5 in nsHTMLDocument::EndUpdate(unsigned int) src/content/html/document/src/nsHTMLDocument.cpp:2352
    #11 0x7fc09cd0c35e in nsHtml5TreeOpExecutor::EndDocUpdate() src/parser/html/nsHtml5TreeOpExecutor.h:248
    #12 0x7fc09cd0b9a4 in nsHtml5TreeOpExecutor::DidBuildModel(bool) src/parser/html/nsHtml5TreeOpExecutor.cpp:131
    #13 0x7fc09ccf736a in nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor*, nsIContent**) src/parser/html/nsHtml5TreeOperation.cpp:627
    #14 0x7fc09cd0fd9a in nsHtml5TreeOpExecutor::RunFlushLoop() src/parser/html/nsHtml5TreeOpExecutor.cpp:564
    #15 0x7fc09cd4a905 in nsHtml5ExecutorFlusher::Run() src/parser/html/nsHtml5StreamParser.cpp:127
    #16 0x7fc0a336578e in nsThread::ProcessNextEvent(bool, bool*) src/xpcom/threads/nsThread.cpp:624
    #17 0x7fc0a3006b67 in NS_ProcessNextEvent_P(nsIThread*, bool) src/objdir-ff-asan-sym/xpcom/build/nsThreadUtils.cpp:220
    #18 0x7fc0a1dc3625 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) src/ipc/glue/MessagePump.cpp:82
    #19 0x7fc0a3610389 in MessageLoop::RunInternal() src/ipc/chromium/src/base/message_loop.cc:208
    #20 0x7fc0a36101d2 in MessageLoop::RunHandler() src/ipc/chromium/src/base/message_loop.cc:201
    #21 0x7fc0a36100b7 in MessageLoop::Run() src/ipc/chromium/src/base/message_loop.cc:175
    #22 0x7fc0a12884ce in nsBaseAppShell::Run() src/widget/xpwidgets/nsBaseAppShell.cpp:163
    #23 0x7fc09fee89b8 in nsAppStartup::Run() src/toolkit/components/startup/nsAppStartup.cpp:273
    #24 0x7fc0966e81a1 in XREMain::XRE_mainRun() src/toolkit/xre/nsAppRunner.cpp:3835
Shadow byte and word:
  0x1ff80ef48f19: fd
  0x1ff80ef48f18: fd fd fd fd fd fd fd fd
More shadow bytes:
  0x1ff80ef48ef8: fa fa fa fa fa fa fa fa
  0x1ff80ef48f00: fa fa fa fa fa fa fa fa
  0x1ff80ef48f08: fa fa fa fa fa fa fa fa
  0x1ff80ef48f10: fd fd fd fd fd fd fd fd
=>0x1ff80ef48f18: fd fd fd fd fd fd fd fd
  0x1ff80ef48f20: fd fd fd fd fd fd fd fd
  0x1ff80ef48f28: fd fd fd fd fd fd fd fd
  0x1ff80ef48f30: fd fd fd fd fd fd fd fd
  0x1ff80ef48f38: fd fd fd fd fd fd fd fd
Stats: 228M malloced (246M for red zones) by 405498 calls
Stats: 43M realloced by 15549 calls
Stats: 200M freed by 193168 calls
Stats: 64M really freed by 120477 calls
Stats: 432M (110668 full pages) mmaped in 108 calls
  mmaps   by size class: 8:245745; 9:40955; 10:16380; 11:16376; 12:2048; 13:1536; 14:1280; 15:256; 16:320; 17:1280; 18:144; 19:40; 20:20;
  mallocs by size class: 8:317776; 9:46531; 10:16128; 11:17241; 12:2334; 13:1738; 14:1479; 15:332; 16:400; 17:1309; 18:172; 19:41; 20:17;
  frees   by size class: 8:121716; 9:37588; 10:13105; 11:14230; 12:1542; 13:1565; 14:1305; 15:291; 16:328; 17:1296; 18:150; 19:38; 20:14;
  rfrees  by size class: 8:80367; 9:20243; 10:8280; 11:9424; 12:628; 13:487; 14:388; 15:151; 16:188; 17:287; 18:28; 19:5; 20:1;
Stats: malloc large: 1539 small slow: 1896
==8725== ABORTING
Attached file Testcase
Reproduces reliably, just run the testcase with a couple of firefox instances at once.
Severity: normal → critical
Component: General → Editor
Product: Firefox → Core
Whiteboard: [asan]
This needs an owner.
Assignee: nobody → bugs
+cc: Aryeh Gregor

Please step through in a debugger and report your findings. Thanks!
Attached patch PatchSplinter Review
This seems to fix it, in the vein of bug 568362.  But as bug 568362 comment 7 points out, it's extremely fragile.  Is there a better way to do this?  Are there more methods we need to add this kind of guard to?  Surely there are.  How do we find them?

I don't have an exact breakdown, but I'm guessing what happens is that the nsHTMLEditRules method overwrites a bunch of document contents in the course of doing the insertHTML, which sets mRules to a new value, so "this" is no longer valid.  I can't see from the source code where exactly this happens, though.

Passes editor tests locally.
Assignee: bugs → ayg
Status: NEW → ASSIGNED
Attachment #661578 - Flags: review?(ehsan)
Attachment #661578 - Flags: review?(ehsan) → review+
Yeah, this kind of thing is fragile indeed, but unfortunately we don't have a good way of fixing these issues in a better way in face of mutation events.  :(
http://hg.mozilla.org/mozilla-central/rev/d4c559278e6d
Status: ASSIGNED → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Is 16/17/ESR10 affected as well? We believe they are, but want to confirm.
Please nominate this for uplift to Aurora 17, we can land to ESR10 after we release next week.
For anyone following Firefox patches this one screams "find use after free near here!"  We really shouldn't be landing these kinds of obvious tiny patches until we're ready to usher them into all branches and particularly the current beta.
Keywords: csec-uaf
Comment on attachment 661578 [details] [diff] [review]
Patch

The risk here is very minimal.
Attachment #661578 - Flags: approval-mozilla-esr10?
Attachment #661578 - Flags: approval-mozilla-beta?
Attachment #661578 - Flags: approval-mozilla-aurora?
Comment on attachment 661578 [details] [diff] [review]
Patch

Approving for all branches now as its low risk, sec-critical and baked on m-c for a while. 

Thankfully we have the sec-approval flag now which will help prevent taking bugs on branches based upon a m-c landing .
Attachment #661578 - Flags: approval-mozilla-esr10?
Attachment #661578 - Flags: approval-mozilla-esr10+
Attachment #661578 - Flags: approval-mozilla-beta?
Attachment #661578 - Flags: approval-mozilla-beta+
Attachment #661578 - Flags: approval-mozilla-aurora?
Attachment #661578 - Flags: approval-mozilla-aurora+
Comment on attachment 661578 [details] [diff] [review]
Patch

[Security approval request comment]
How easily can the security issue be deduced from the patch? Fairly easily.

Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem? The patch itself is pretty obvious.

Which older supported branches are affected by this flaw? All.

If not all supported branches, which bug introduced the flaw? Unknown.

Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be? Should apply everywhere almost verbatim.

How likely is this patch to cause regressions; how much testing does it need? Regressions are not very likely.
Attachment #661578 - Flags: sec-approval?
Comment on attachment 661578 [details] [diff] [review]
Patch

(already landed on m-c, but approving nonetheless)
Attachment #661578 - Flags: sec-approval? → sec-approval+
Whiteboard: [asan] → [asan][advisory-tracking+]
Alias: CVE-2012-4182
Keywords: verifyme
Flags: sec-bounty?
Group: core-security
Flags: sec-bounty? → sec-bounty+
mass remove verifyme requests greater than 4 months old
Keywords: verifyme
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: