Closed Bug 774548 (CVE-2012-3957) Opened 12 years ago Closed 12 years ago

Heap-buffer-overflow in nsBlockFrame::MarkLineDirty

Categories

(Core :: Layout: Block and Inline, defect)

x86_64
All
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla17
Tracking Status
firefox15 + fixed
firefox16 + fixed
firefox17 + fixed
firefox-esr10 15+ fixed

People

(Reporter: inferno, Assigned: MatsPalmgren_bugz)

Details

(Keywords: crash, csectype-bounds, sec-critical, Whiteboard: [asan][advisory-tracking+][qa?])

Attachments

(3 files, 1 obsolete file)

Attached file Testcase
Reproduces on trunk.

=================================================================
==25348== ERROR: AddressSanitizer heap-buffer-overflow on address 0x7f07b3382ab4 at pc 0x7f07e1f45e62 bp 0x7fff73ddf550 sp 0x7fff73ddf548
READ of size 4 at 0x7f07b3382ab4 thread T0
    #0 0x7f07e1f45e62 in nsLineBox::IsInline() const asn1cmn.c:0
    #1 0x7f07e1f45647 in nsBlockFrame::MarkLineDirty(nsLineList_iterator, nsLineList const*) layout/generic/nsBlockFrame.cpp:1562
    #2 0x7f07e1f82d34 in nsBlockFrame::AddFrames(nsFrameList&, nsIFrame*) layout/generic/nsBlockFrame.cpp:4990
    #3 0x7f07e1f8089d in nsBlockFrame::InsertFrames(mozilla::layout::FrameChildListID, nsIFrame*, nsFrameList&) layout/generic/nsBlockFrame.cpp:4838
    #4 0x7f07e1b38e92 in nsFrameManager::InsertFrames(nsIFrame*, mozilla::layout::FrameChildListID, nsIFrame*, nsFrameList&) layout/base/nsFrameManager.cpp:463
    #5 0x7f07e18a76f0 in nsCSSFrameConstructor::ContentRangeInserted(nsIContent*, nsIContent*, nsIContent*, nsILayoutHistoryState*, bool) layout/base/nsCSSFrameConstructor.cpp:7332
    #6 0x7f07e18a06a9 in nsCSSFrameConstructor::ContentInserted(nsIContent*, nsIContent*, nsILayoutHistoryState*, bool) layout/base/nsCSSFrameConstructor.cpp:6814
    #7 0x7f07e1890a69 in nsCSSFrameConstructor::RecreateFramesForContent(nsIContent*, bool) layout/base/nsCSSFrameConstructor.cpp:9263
    #8 0x7f07e18c0772 in nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList&) layout/base/nsCSSFrameConstructor.cpp:8008
    #9 0x7f07e18c6afd in nsCSSFrameConstructor::RestyleElement(mozilla::dom::Element*, nsIFrame*, nsChangeHint, mozilla::css::RestyleTracker&, bool) layout/base/nsCSSFrameConstructor.cpp:8162
    #10 0x7f07e181129d in mozilla::css::RestyleTracker::ProcessOneRestyle(mozilla::dom::Element*, nsRestyleHint, nsChangeHint) layout/base/RestyleTracker.cpp:125
    #11 0x7f07e180b8d6 in mozilla::css::RestyleTracker::DoProcessRestyles() layout/base/RestyleTracker.cpp:210
    #12 0x7f07e18ee7ba in mozilla::css::RestyleTracker::ProcessRestyles() layout/base/RestyleTracker.h:70
    #13 0x7f07e18ee2ee in nsCSSFrameConstructor::ProcessPendingRestyles() layout/base/nsCSSFrameConstructor.cpp:11996
    #14 0x7f07e1cc088e in PresShell::FlushPendingNotifications(mozFlushType) layout/base/nsPresShell.cpp:3814
    #15 0x7f07e21a5d0c in nsGfxScrollFrameInner::AsyncScrollPortEvent::Run() layout/generic/nsGfxScrollFrame.cpp:2990
    #16 0x7f07e1c4ea65 in nsRootPresContext::FlushWillPaintObservers() layout/base/nsPresContext.cpp:2807
    #17 0x7f07e1c621b9 in nsRootPresContext::RunWillPaintObservers::Run() layout/base/nsPresContext.h:1381
    #18 0x7f07ecd040dd in nsThread::ProcessNextEvent(bool, bool*) xpcom/threads/nsThread.cpp:625
    #19 0x7f07ec992e8d in NS_ProcessNextEvent_P(nsIThread*, bool) objdir-ff-asan-sym/xpcom/build/nsThreadUtils.cpp:217
    #20 0x7f07eb980ea6 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) ipc/glue/MessagePump.cpp:82
    #21 0x7f07ecfb80ba in MessageLoop::RunInternal() ipc/chromium/src/base/message_loop.cc:209
    #22 0x7f07ecfb7f03 in MessageLoop::RunHandler() ipc/chromium/src/base/message_loop.cc:202
    #23 0x7f07ecfb7de8 in MessageLoop::Run() ipc/chromium/src/base/message_loop.cc:176
    #24 0x7f07eae9161e in nsBaseAppShell::Run() widget/xpwidgets/nsBaseAppShell.cpp:165
    #25 0x7f07e9ae0f78 in nsAppStartup::Run() toolkit/components/startup/nsAppStartup.cpp:257
    #26 0x7f07e025e2a0 in XREMain::XRE_mainRun() toolkit/xre/nsAppRunner.cpp:3787
    #27 0x7f07e0264c42 in XREMain::XRE_main(int, char**, nsXREAppData const*) toolkit/xre/nsAppRunner.cpp:3864
    #28 0x7f07e0268112 in XRE_main toolkit/xre/nsAppRunner.cpp:3940
    #29 0x40c28f in do_main(int, char**) browser/app/nsBrowserApp.cpp:160
    #30 0x409cbd in main browser/app/nsBrowserApp.cpp:298
    #31 0x7f07fcc21c4d in ?? ??:0
0x7f07b3382ab4 is located 20 bytes to the right of 32-byte region [0x7f07b3382a80,0x7f07b3382aa0)
allocated by thread T0 here:
    #0 0x4a4452 in __interceptor_malloc ??:0
    #1 0x7f07f9aad717 in moz_xmalloc memory/mozalloc/mozalloc.cpp:54
    #2 0x7f07e1f66f4b in nsBlockFrame::PushLines(nsBlockReflowState&, nsLineList_iterator) layout/generic/nsBlockFrame.cpp:4414
    #3 0x7f07e1f7630c in nsBlockFrame::PlaceLine(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFloatManager::SavedState*, nsRect&, int&, bool*) layout/generic/nsBlockFrame.cpp:4325
    #4 0x7f07e1f6cb5e in nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, bool*, LineReflowStatus*, bool) layout/generic/nsBlockFrame.cpp:3764
    #5 0x7f07e1f5d897 in nsBlockFrame::ReflowInlineFrames(nsBlockReflowState&, nsLineList_iterator, bool*) layout/generic/nsBlockFrame.cpp:3482
    #6 0x7f07e1f4c24c in nsBlockFrame::ReflowLine(nsBlockReflowState&, nsLineList_iterator, bool*) layout/generic/nsBlockFrame.cpp:2570
    #7 0x7f07e1f316b1 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) layout/generic/nsBlockFrame.cpp:2020
    #8 0x7f07e1f2514f in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) layout/generic/nsBlockFrame.cpp:1069
    #9 0x7f07e2014c27 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, int, int, unsigned int, unsigned int&, nsOverflowContinuationTracker*) layout/generic/nsContainerFrame.cpp:906
    #10 0x7f07e1ff6b35 in nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&, nsColumnSetFrame::ReflowConfig const&, bool, nsCollapsingMargin*, nsColumnSetFrame::ColumnBalanceData&) layout/generic/nsColumnSetFrame.cpp:665
    #11 0x7f07e1ffdcd7 in nsColumnSetFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) layout/generic/nsColumnSetFrame.cpp:920
    #12 0x7f07e1fb53bb in nsBlockReflowContext::ReflowBlock(nsRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, nsHTMLReflowState&, unsigned int&, nsBlockReflowState&) layout/generic/nsBlockReflowContext.cpp:262
    #13 0x7f07e1f566b7 in nsBlockFrame::ReflowBlockFrame(nsBlockReflowState&, nsLineList_iterator, bool*) layout/generic/nsBlockFrame.cpp:3206
    #14 0x7f07e1f4bda6 in nsBlockFrame::ReflowLine(nsBlockReflowState&, nsLineList_iterator, bool*) layout/generic/nsBlockFrame.cpp:2514
    #15 0x7f07e1f316b1 in nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&) layout/generic/nsBlockFrame.cpp:2020
    #16 0x7f07e1f2514f in nsBlockFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) layout/generic/nsBlockFrame.cpp:1069
    #17 0x7f07e2014c27 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, int, int, unsigned int, unsigned int&, nsOverflowContinuationTracker*) layout/generic/nsContainerFrame.cpp:906
    #18 0x7f07e1ff6b35 in nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&, nsColumnSetFrame::ReflowConfig const&, bool, nsCollapsingMargin*, nsColumnSetFrame::ColumnBalanceData&) layout/generic/nsColumnSetFrame.cpp:665
    #19 0x7f07e1ffdcd7 in nsColumnSetFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) layout/generic/nsColumnSetFrame.cpp:920
    #20 0x7f07e2014c27 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, int, int, unsigned int, unsigned int&, nsOverflowContinuationTracker*) layout/generic/nsContainerFrame.cpp:906
    #21 0x7f07e21e5eb7 in nsCanvasFrame::Reflow(nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, unsigned int&) layout/generic/nsCanvasFrame.cpp:429
    #22 0x7f07e2014c27 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, nsHTMLReflowMetrics&, nsHTMLReflowState const&, int, int, unsigned int, unsigned int&, nsOverflowContinuationTracker*) layout/generic/nsContainerFrame.cpp:906
    #23 0x7f07e215f54e in nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowState*, bool, bool, nsHTMLReflowMetrics*, bool) layout/generic/nsGfxScrollFrame.cpp:518
    #24 0x7f07e2159c72 in nsHTMLScrollFrame::TryLayout(ScrollReflowState*, nsHTMLReflowMetrics*, bool, bool, bool, unsigned int*) layout/generic/nsGfxScrollFrame.cpp:363
==25348== ABORTING
Stats: 152M malloced (168M for red zones) by 363291 calls
Stats: 39M realloced by 19415 calls
Stats: 109M freed by 231030 calls
Stats: 0M really freed by 0 calls
Stats: 344M (88112 full pages) mmaped in 86 calls
  mmaps   by size class: 8:294894; 9:49146; 10:20475; 11:18423; 12:3072; 13:2048; 14:1536; 15:384; 16:576; 17:128; 18:176; 19:40; 20:12;
  mallocs by size class: 8:274461; 9:47542; 10:16571; 11:17710; 12:2504; 13:1857; 14:1429; 15:321; 16:571; 17:101; 18:172; 19:40; 20:12;
  frees   by size class: 8:162364; 9:36580; 10:13056; 11:14376; 12:1553; 13:942; 14:1230; 15:269; 16:470; 17:91; 18:52; 19:38; 20:9;
  rfrees  by size class:
Stats: malloc large: 325 small slow: 1903
Shadow byte and word:
  0x1fe0f6670556: fb
  0x1fe0f6670550: 00 00 00 00 fb fb fb fb
More shadow bytes:
  0x1fe0f6670530: fd fd fd fd fd fd fd fd
  0x1fe0f6670538: fd fd fd fd fd fd fd fd
  0x1fe0f6670540: fa fa fa fa fa fa fa fa
  0x1fe0f6670548: fa fa fa fa fa fa fa fa
=>0x1fe0f6670550: 00 00 00 00 fb fb fb fb
  0x1fe0f6670558: fb fb fb fb fb fb fb fb
  0x1fe0f6670560: fa fa fa fa fa fa fa fa
  0x1fe0f6670568: fa fa fa fa fa fa fa fa
  0x1fe0f6670570: 00 00 00 00 00 00 00 00
The code where the problem was flagged hasn't changed in forever, the closest was a change a couple lines away to fix a security bug in Firefox 3.0.4 (bug 443528). Something may have changed elsewhere recently that may be part of the problem, though.

In a debug build I get

###!!! ABORT: running past end: 'mCurrent != mListLink', file /Users/daniel/dev/ffcentral/mozilla/layout/base/../generic/nsLineBox.h, line 681

... so you shouldn't need an ASan build to figure this one out or verify it later.
Component: General → Layout: Block and Inline
Keywords: sec-critical
Product: Firefox → Core
Whiteboard: [asan]
Attached file stack + frame dump
The prev sibling is on an overflow line and MarkLineDirty
assumes it's on a normal line unless an explicit aLineList
is provided.

nsBlockFrame::AddFrames already has the correct line list
and propagating it fixes the crash.
Attached patch fix (obsolete) — Splinter Review
We should probably just require the caller to provide
the line list for aLine,  or add a bit to lines saying
which list they belong to (I think we have pretty good
control over when lines are pushed/pulled and we only
do one at a time iirc).

https://tbpl.mozilla.org/?usebuildbot=1&tree=Try&rev=b0bb71a96909
Severity: normal → critical
Keywords: crash
(Note: I haven't tested the patch in an ASAN build yet)
Assignee: nobody → matspal
Attached patch fix, v2Splinter Review
The first Try run was green.  There's a call earlier in the same method
that we also should fix.  This patch is intended also for branches.

https://tbpl.mozilla.org/?usebuildbot=1&tree=Try&rev=7747fcf62833

I'll file a follow-up bug on making aLineList mandatory for MarkLineDirty and
removing the "nsnull means mLines" association, but nsBlockInFlowLineIterator
depends on the latter (b/c nsBlockInFlowLineIterator::GetLineList() returns
nsnull when mLine is a normal line).
Attachment #642952 - Attachment is obsolete: true
Attachment #643064 - Flags: review?(roc)
https://hg.mozilla.org/integration/mozilla-inbound/rev/0842d651cfa8

Filed follow-up bug 774794.
Target Milestone: --- → mozilla17
(Tested ok in Linux64 ASAN build remotely with the testcase)
https://hg.mozilla.org/mozilla-central/rev/0842d651cfa8
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Comment on attachment 643064 [details] [diff] [review]
fix, v2

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

We should take this security fix on Aurora and Beta.
Attachment #643064 - Flags: approval-mozilla-beta?
Attachment #643064 - Flags: approval-mozilla-aurora?
Comment on attachment 643064 [details] [diff] [review]
fix, v2

Low risk sec-critical crash fix.
Attachment #643064 - Flags: approval-mozilla-esr10?
Attachment #643064 - Flags: approval-mozilla-esr10?
Attachment #643064 - Flags: approval-mozilla-esr10+
Attachment #643064 - Flags: approval-mozilla-beta?
Attachment #643064 - Flags: approval-mozilla-beta+
Attachment #643064 - Flags: approval-mozilla-aurora?
Attachment #643064 - Flags: approval-mozilla-aurora+
Whiteboard: [asan] → [asan][advisory-tracking+]
Does the attached testcase need to go in-testsuite?
Whiteboard: [asan][advisory-tracking+] → [asan][advisory-tracking+][qa?]
Yes, we should land the test when the bug is public, thanks.
Flags: in-testsuite?
Alias: CVE-2012-3957
Group: core-security
Flags: sec-bounty+
You need to log in before you can comment on or make changes to this bug.