Closed Bug 1145965 Opened 11 years ago Closed 11 years ago

Heap-buffer-overflow in nsSVGPathGeometryFrame, due to Ubuntu/Debian libxrender1 having been compiled with vulnerable version of libx11-dev

Categories

(Core :: SVG, defect)

x86_64
Linux
defect
Not set
normal

Tracking

()

RESOLVED DUPLICATE of bug 803762
Tracking Status
firefox39 --- affected
firefox40 --- affected

People

(Reporter: attekett, Unassigned)

References

Details

(Keywords: reporter-external, sec-vector, testcase)

Attachments

(3 files, 1 obsolete file)

Attached image repro-file.svg —
Tested on: OS: Ubuntu 14.04 Firefox: ASAN-build from https://ftp.mozilla.org/pub/mozilla.org/firefox/tinderbox-builds/mozilla-central-linux64-asan/1426899098/ Note: To reproduce the crash you have to open the repro-file in large enough window. Full screen worked for me on 1280x768 resolution. Not 100% sure if this bug falls under SVG component, so feel free to change it. ASAN-trace: ==7113==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x629000031200 at pc 0x461c8b bp 0x7fff68c672e0 sp 0x7fff68c672b0 WRITE of size 20 at 0x629000031200 thread T0 (Web Content) #0 0x461c8a in memmove /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:349 #1 0x7fe004f69cb1 in memmove /usr/include/x86_64-linux-gnu/bits/string3.h:57 #2 0x7fe004f69cb1 in XRenderCompositeTrapezoids /build/buildd/libxrender-0.9.8/build/src/../../src/Trap.c:65 #3 0x7fe010171408 in _cairo_xlib_surface_composite_trapezoids /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-xlib-surface.c:2984 #4 0x7fe01021f59a in _cairo_surface_composite_trapezoids /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-surface.c:2396 #5 0x7fe01023e62a in _composite_traps_draw_func /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-surface-fallback.c:561 #6 0x7fe010219ca9 in _clip_and_composite /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-surface-fallback.c:472 #7 0x7fe010218fa8 in _clip_and_composite_trapezoids /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-surface-fallback.c:875 #8 0x7fe01021b025 in _cairo_surface_fallback_stroke /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-surface-fallback.c:1111 #9 0x7fe010221717 in _cairo_surface_stroke /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-surface.c:2302 #10 0x7fe0101a075b in _cairo_gstate_stroke /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo-gstate.c:1166 #11 0x7fe01024321a in _moz_cairo_stroke_preserve /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/cairo/cairo/src/cairo.c:2421 #12 0x7fe00a5928a2 in mozilla::gfx::DrawTargetCairo::DrawPattern(mozilla::gfx::Pattern const&, mozilla::gfx::StrokeOptions const&, mozilla::gfx::DrawOptions const&, mozilla::gfx::DrawTargetCairo::DrawPatternType, bool) /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/2d/DrawTargetCairo.cpp:912 #13 0x7fe00a597a19 in mozilla::gfx::DrawTargetCairo::Stroke(mozilla::gfx::Path const*, mozilla::gfx::Pattern const&, mozilla::gfx::StrokeOptions const&, mozilla::gfx::DrawOptions const&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/2d/DrawTargetCairo.cpp:1115 #14 0x7fe00ebec916 in nsSVGPathGeometryFrame::Render(gfxContext*, unsigned int, gfxMatrix const&) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/svg/nsSVGPathGeometryFrame.cpp:806 #15 0x7fe00ebead9f in nsSVGPathGeometryFrame::PaintSVG(gfxContext&, gfxMatrix const&, nsIntRect const*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/svg/nsSVGPathGeometryFrame.cpp:261 #16 0x7fe00ebe9824 in nsDisplaySVGPathGeometry::Paint(nsDisplayListBuilder*, nsRenderingContext*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/svg/nsSVGPathGeometryFrame.cpp:114 #17 0x7fe00e54ffe7 in mozilla::FrameLayerBuilder::PaintItems(nsTArray<mozilla::FrameLayerBuilder::ClippedDisplayItem>&, nsIntRect const&, gfxContext*, nsRenderingContext*, nsDisplayListBuilder*, nsPresContext*, nsIntPoint const&, float, float, int) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/base/FrameLayerBuilder.cpp:4672 #18 0x7fe00e552e29 in mozilla::FrameLayerBuilder::DrawPaintedLayer(mozilla::layers::PaintedLayer*, gfxContext*, nsIntRegion const&, mozilla::layers::DrawRegionClip, nsIntRegion const&, void*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/layout/base/FrameLayerBuilder.cpp:4869 #19 0x7fe00a7fd6c9 in mozilla::layers::BasicPaintedLayer::PaintThebes(gfxContext*, mozilla::layers::Layer*, void (*)(mozilla::layers::PaintedLayer*, gfxContext*, nsIntRegion const&, mozilla::layers::DrawRegionClip, nsIntRegion const&, void*), void*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/layers/basic/BasicPaintedLayer.cpp:94 #20 0x7fe00a7f9088 in mozilla::layers::BasicLayerManager::PaintSelfOrChildren(mozilla::layers::PaintLayerContext&, gfxContext*) /builds/slave/m-cen-l64-asan-000000000000000/build/src/gfx/layers/basic/BasicLayerManager.cpp:802 . . .
Is this an SVG problem? the crash is happening down in Cairo code it looks like, the bug might be there instead. A regression range would help point the finger if we can get one (and usually fuzz-found bugs aren't ancient or the fuzzer would likely have found it earlier).
Flags: needinfo?(dholbert)
I just got a clang-with-ASAN build environment up again (hadn't had one working for a little while), and I can confirm that I get the reported issue w/ the testcase, FWIW. I'll poke around & see what I can figure out.
Here's a somewhat-cleaned-up version of the testcase. (I tried pruning out bits of the paths, but any modifications I made to the actual path data seemed to prevent the issue from occurring. So, the paths are still quite long, in terms of number-of-commands.)
Flags: needinfo?(dholbert)
(note: if it's not clear, my 'reduced' testcase is larger (in KB) than the original because I added whitespace for readability/hand-editability.)
I'm poking around in GDB, though it's giving me two forms of trouble: (1) when ASAN detects the buffer overflow & aborts, it does so in a way that GDB doesn't intercept. (so I have to break *just* before we abort) and more painful: (2) gdb says every variable value is <optimized out>, even though I built with --enable-debug --disable-optimize If anyone knows a workaround for around either of those problems, I'd love to hear it. In the meantime, I'm doing some printf debugging to try to figure out variable values around the time that the overflow happens.
(In reply to Daniel Veditz [:dveditz] from comment #1) > Is this an SVG problem? the crash is happening down in Cairo code it looks > like, the bug might be there instead. Hard to say. Could also be that we're passing bogus data into Cairo. (I'm trying to find out, but it's hard with gdb not cooperating, per comment 5.) > A regression range would help point the finger if we can get one (and > usually fuzz-found bugs aren't ancient or the fuzzer would likely have found > it earlier). Unfortunately, I can reproduce this in ASAN builds from at least as far back as Jan 2014 (when we were at version 29) -- I tried this one: http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/2014/01/2014-01-02-03-02-03-mozilla-central/ So, not a recent regression.
I'm tempted to punt to jwatt or Bas, because they know the path-drawing / draw-target / cairo code better than I do, and they're more likely to know what variables might be useful to print out here... Starting with jwatt -- any chance you have cycles to look into this? (I didn't discover anything useful in my printf debugging. My current theory is that we're drawing off the edge of the surface that's backing our draw-target, but I'm not sure how to test for that.) Facts: - The XRenderCompositeTrapezoids call (inside of which the issue happens) is here: http://mxr.mozilla.org/mozilla-central/source/gfx/cairo/cairo/src/cairo-xlib-surface.c#2984 -It looks like the points it uses are encoded in "xtraps" - num_traps is 6554 - render_src_x/y and attributes.x_offset/y_offset are all fairly tame -- (568, 36) and (0,0) respectively.
Flags: needinfo?(jwatt)
I've spent a lot of time trying to get a working ASAN build up and running on Mac, but after working through various build errors I'm now getting startup crashes due to bug 1146189.
Flags: needinfo?(jwatt)
https://developer.mozilla.org/en-US/docs/Mozilla/Testing/Firefox_and_Address_Sanitizer has known-good clang revisions -- r214699 should work on Mac, supposedly.
Yeah, that (and other revisions that I found in various bug comments that have previously worked for people) didn't work for me, which is why most recently I ended up trying the latest revision. I thought it best to at least post an update for now though. I'll try again with a Linux build soon, but I need to get my Linux VM working again first.
Let's start with sec-critical for now. The crash is reliable and writing 20 bytes is more than enough to exploit. When we find out what the actual problem is we can downgrade the rating if we find out it's going somewhere safe enough or would require a race with another thread to exploit.
Keywords: sec-critical
By way of an update, I've got a local asan build going now, but haven't yet made much more progress than Daniel did. I'm away until Tuesday, but I'll get back on this then.
(In reply to Daniel Holbert [:dholbert] from comment #5) > I'm poking around in GDB, though it's giving me two forms of trouble: > (1) when ASAN detects the buffer overflow & aborts, it does so in a way > that GDB doesn't intercept. (so I have to break *just* before we abort) (gdb) br __asan_report_error > (2) gdb says every variable value is <optimized out>, even though I built > with --enable-debug --disable-optimize Add "-mllvm -asan-stack-dynamic-alloca=1" to CFLAGS and CXXFLAGS in your mozconfig file. (works in a stock clang 3.6 anyway)
BTW, if you rebuild and it fails because 'genrb' leaks memory, then just copy that binary from one of your other builds into the asan build OBJDIR and restart the build.
(In reply to Mats Palmgren (:mats) from comment #13) > > (2) gdb says every variable value is <optimized out>, even though I built > > with --enable-debug --disable-optimize > > Add "-mllvm -asan-stack-dynamic-alloca=1" to CFLAGS and CXXFLAGS > in your mozconfig file. (works in a stock clang 3.6 anyway) Thanks! But, darn -- that option is apparently not supported in the LLVM/clang snapshot that MDN recommends using[1] (revision 200213, which is version 3.5). Maybe I should try stock 3.6. [1] https://developer.mozilla.org/en-US/docs/Mozilla/Testing/Firefox_and_Address_Sanitizer#Manual_Build
OK, I was able to build using stock clang 3.6 from http://llvm.org/apt/, and (with mats' second hint in comment 13) I am able to usefully poke around in GDB. I also grabbed the libxrender source, so I could step into XRenderCompositeTrapezoids (which we're inside when we crash). Loading the original testcase, basically what happens is: (1) XRenderCompositeTrapezoids gets called, with num_traps (last param) equal to 6554. (NOTE: If I manually reduce the value in that arg to 6552, I get no issues; we don't take the "bigreq" codepath described below.) (2) That initializes 'req' with this call: GetReq(RenderTrapezoids, req); which is a macro for: req = _XGetRequest(dpy, X_RenderTrapezoids, sizeof(xRenderTrapezoidsReq); Note that sizeof(xRenderTrapezoidsReq) is 24. (3) Then we hit this call to the SetReqLen macro, with req->length = 6 and len = 65540: SetReqLen (req, len, len); (This is still in XRenderCompositeTrapezoids) In my case right now, req is 0x6290000041e8 (3) SetReqLen (defined in /usr/include/X11/Xlibint.h) checks if the passed-in len is bigger than 65535 (it is), and calls another macro, "MakeBigReq". (4) MakeBigReq ends up setting a local var _BRlen = 5, and then calling: memmove(((char *)req) + 8, ((char *)req) + 4, (_BRlen - 1) << 2); (5) ASAN catches a buffer overflow inside of this memmove call. The memmove call *should* be a write of size 16, because "(_BRlen - 1) << 2" is 16. (Because _BRlen is 5.) This should be in-bounds, because sizeof(xRenderTrapezoidsReq) is 24, and we're writing 8 bytes into this object, and we're writing a total of 16 bytes, which should exactly hit the end of the object. But for some reason ASAN calls this a "heap-buffer-overflow on address 0x629000004200 [...] WRITE of size 20 at 0x629000004200") I don't know why memmove is writing 20 bytes (instead of 16), and why it's writing those bytes at 0x629000004200 (which is req + 24).
FWIW, _XGetRequest() impl gives us our "req" by grabbing some space off of its internal buffer, like this: > req = (xReq*)dpy->bufptr; > req->reqType = type; > req->length = len / 4; > dpy->bufptr += len; > dpy->request++; > return req; After this point, dpy->bufptr == dpy->bufmax. (So the end of our 'req' object really is the end of the buffer that it's a part of.) I'm still not clear how we end up doing a 20-byte write, though. Stepping through the assembly, it looks like we're skipping one of the "-1" subtractions for some reason. We're supposed to start with req->length, which is 6, and subtract 1 to produce "_BRlen", and then pass in "(_BRlen - 1) << 2)" to our memmove command (which is (5 - 1) << 2 = 4 << 2 = 16). But what I actually see in GDB is: we subtract 1 from 6 to produce 5 in register $rdx, and then we shift that left by 2 (producing 20), when we set up for our memmove call. If I tweak $rdx to have the value I expect right before memmove (16 instead of 20), then we complete memmove without any ASAN issues. Bottom line, this seems almost certainly like a bug in XRenderCompositeTrapezoids (in libxrender), and/or in the MakeBigReq macro (in libx11) -- specifically, there seems to be an off-by-one in the assembly of the compiled binary. And the bug doesn't seem to be present in the source code (from "apt-get source" on the library).
Fun fact: If I build libXrender locally from source (provided by "apt-get source libxrender") and swap in the resulting libXrender.so.1.3.0 for my distro-provided file, I get *no ASAN issues*. So: the default libXrender.so.1.3.0 is busted, but if you get the sources from apt and build it yourself, you get something functional. This seems suspicious/nefarious (my paranoia sense is tingling), but it could also conceivably just be a bug introduced by the particular compiler / compile options that were used on the packager's system... (I'm currently using Ubuntu 15.04 beta, btw.)
As a sanity-check, I tested the precompiled ASAN build linked in comment 0, with my locally-compiled libXrender still swapped in (in /usr/lib/x86_64-linux-gnu), and I verified that I get no issues at all.
Summary: Heap-buffer-overflow in nsSVGPathGeometryFrame → Heap-buffer-overflow in nsSVGPathGeometryFrame (bug in libxrender binary?)
There is also some crash with the repro-file and release stable Firefox 37.0 without ASAN on Ubuntu 14.04. Interesting thing is that the crash doesn't occur when you open the repro-file, but when you try to close the browser after opening the repro-file. Submitted crash report IDs: bp-4ee63f02-d2fb-4583-b1b3-293a82150407 bp-6a9a96a8-e017-4de7-8ed6-a8c2c2150407 I tried it couple of times and reproducing is pretty simple. Open the repro-file ( https://bugzilla.mozilla.org/attachment.cgi?id=8581116 ) with Firefox and shutdown Firefox. Note: If you have multiple tabs open closing the tab is not enough. I didn't try if you could reproduce the issue via JavaScript without closing down the browser, because ASAN-build shows that the BOF occurs even without additional tricks.
Here's fairly reduced source for a C++ program that triggers the same ASAN bug. (There's a bit of a preamble at the beginning -- that's to fill up the display buffer, so that we exactly hit the end of the buffer inside of our final XRenderCompositeTrapezoids call.) Compile w/ ASAN like so: CXX=clang++-3.6 FLAGS="-Wall -fsanitize=address -mllvm -asan-stack-dynamic-alloca=1" LIBS="-lXrender -lX11" $CXX $FLAGS $LIBS xrender-bug-demo.cpp -o xrender-bug-demo If I run the resulting binary, with my Ubuntu-provided /usr/lib/x86_64-linux-gnu/libXrender.so.1.3.0 file in place, then I hit the same ASAN error quoted in comment 0 here. (heap-buffer-overflow, write of size 20, 0 bytes to the right of 16384-byte region) But if I copy my own locally-compiled libXrender.so.1.3.0 file into /usr/lib/x86_64-linux-gnu/, then I get no issues.
(Here's an executable that I compiled from the previous source file, for convenience / archival purposes.)
Comment on attachment 8582741 [details] testcase 2 (partially reduced, makes tweak after 1 second) (I'm obsoleting my "testcase 2", since I haven't had as much success reproducing with it, as compared to the original testcase.)
Attachment #8582741 - Attachment is obsolete: true
(In reply to Atte Kettunen from comment #20) > There is also some crash with the repro-file and release stable Firefox 37.0 > without ASAN on Ubuntu 14.04. I can't reproduce this, but I'm willing to bet that it's caused by the same libXrender bug that ASAN is catching.
Has anyone reproduced this on a *non* Ubuntu linux system? Right now it looks like it's a mysterious bug in the compiled version of the libXrender .so on Ubuntu, which doesn't happen if you compile libXrender locally (per comment 18 and end of comment 21). I wonder if other Linux distros have the same bug, or if it's Ubuntu-specific (since the source code seems to be fine).
(In reply to Daniel Holbert [:dholbert] from comment #25) > Has anyone reproduced this on a *non* Ubuntu linux system? Answering my own question: I tested Debian 7.8.0 and a Fedora 21 Live environment, in VirtualBox. I tried the ASAN build from comment 0 with the original testcase here, and also my precompiled test C++ program. Results: - Debian 7.8.0 is affected. (I get the same ASAN errors as on Ubuntu.) - Fedora 21 is not affected. (Testcase loads, test program runs, no ASAN warnings.)
Can we stick the libxrender source in the build tree and statically link to it until this bug is fixed?
(In reply to Robert Longson from comment #27) > Can we stick the libxrender source in the build tree and statically link to > it until this bug is fixed? (I'm not sure.) Still poking around, though, and I found something that gives me a theory about what's going on here: - On Debian 7.8.0, I *can reproduce the bug* even with my own locally-built (on Debian) libxrender so file. - I think this is because the "MakeBigReq" macro, defined in /usr/include/X11/Xlibint.h, is *older and buggy* on Debian. (And I think Ubuntu's libxrender package was compiled using that old buggy version.) Here's Ubuntu 14.10 & 15.04's version of MakeBigReq, which is what I end up using when I build libxrender on Ubuntu (& can't reproduce the bug with my library): (This is in Xlibint.h, from package libx11-dev, version 2:1.6.2-2ubuntu2) > #ifdef LONG64 > #define MakeBigReq(req,n) \ > { \ > CARD64 _BRdat; \ > CARD32 _BRlen = req->length - 1; \ > req->length = 0; \ > _BRdat = ((CARD32 *)req)[_BRlen]; \ > memmove(((char *)req) + 8, ((char *)req) + 4, (_BRlen - 1) << 2); \ > ((CARD32 *)req)[1] = _BRlen + n + 2; \ > Data32(dpy, &_BRdat, 4); \ > } Here's Debian 7.8.0's version of MakeBigReq, which is what I end up using when I build libxrender on Debian (& *can* reproduce the bug): (This is in Xlibint.h, from package libx11-dev, version 2:1.5.0-1+deb7u1) > #ifdef LONG64 > #define MakeBigReq(req,n) \ > { \ > printf("****dholbert MakeBigReq LONG64\n"); \ > CARD64 _BRdat; \ > CARD32 _BRlen = req->length - 1; \ > req->length = 0; \ > _BRdat = ((CARD32 *)req)[_BRlen]; \ > memmove(((char *)req) + 8, ((char *)req) + 4, _BRlen << 2); \ > ((CARD32 *)req)[1] = _BRlen + n + 2; \ > Data32(dpy, &_BRdat, 4); \ > } Note that in Debian's version of the header, we just subtract 1 from req->length, and then shift left. Vs. on Ubuntu, there's a bonus subtraction in the call to memmove (which is what should save us from writing past the end of the array.) The Debian behavior seems to be consistent with what I observed when stepping through assembly on Ubuntu. SO: my working theory is that Ubuntu's libxrender package was compiled with an *old* version of libx11-dev, which is why it's using a broken MakeBigReq macro with insufficient subtraction. But recompiling locally gets me an updated MakeBigReq macro, which saves me from the bug. (And Debian 7.8.0 is still using an old version of libxrender and libx11-dev, so even a local compile doesn't save you there.)
(Obviously I added the printf in debian's Xlibint.h file, to make sure I was looking at the right MakeBigReq definition. Forgot to take that out before copypasting here. :))
Aha! And git blame on the Xlibint.h file shows that the "memmove" line was last touched by karlt, and the commit message mentions bug 803762, which looks very similar to this bug. Looks like there was some delay before karl's fix was incorporated, but it finally was (bug 803762 comment 19). But system libraries like libxrender apparently haven't been recompiled to incorporate the change.
Depends on: 803762
The X11 bug where karl fixed this is https://bugs.freedesktop.org/show_bug.cgi?id=56508 , FWIW. karl, can you suggest what to do, to get packages like libxrender rebuilt & linux distros to ship security updates that incorporate your patch? It's frightening that Debian Stable still doesn't have your fix in its libx11-dev package... (and that Ubuntu has vulnerable libraries, despite having a fixed "dev" package)
Flags: needinfo?(karlt)
Daniel, I think you should just go ahead and file a security bug to Ubuntu and explain the situation. I don't think they are aware that 56508 is potentially exploitable. (It looks like Karl is away so he might not be reading bug mail for another week.)
Yeah, I just noticed that karl's away. I'll go ahead & file Ubuntu & Debian bugs.
I filed https://bugs.launchpad.net/ubuntu/+source/libxrender/+bug/1441381 on Ubuntu (as a sec bug, so probably inaccessible to most/all folks here).
(In reply to Daniel Holbert [:dholbert] from comment #33) > I'll go ahead & file Ubuntu & Debian bugs. (Following up on this: I actually only filed an Ubuntu bug on Launchpad, and I CC'd some folks who've worked on the debian libxrender1 package. I opted not to file a separate Debian bug, since there's not a lot of Ubuntu/Debian-specific activity in this library that I can see. Debian also seems to want me to file bugs via email or via a command-line tool, which seems clumsy & makes it hard to know that the bug will stay secure & let me CC folks as I discover them. Debian also doesn't have much activity for this library in their bug tracker -- there are exactly 0 open bug reports: https://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=libxrender1 )
Flags: needinfo?(karlt)
Summary: Heap-buffer-overflow in nsSVGPathGeometryFrame (bug in libxrender binary?) → Heap-buffer-overflow in nsSVGPathGeometryFrame, due to Ubuntu/Debian libxrender1 having been compiled with vulnerable version of libx11-dev
If we're filing this with vendors, what are we doing with *this* bug? Can we put a check in place or something to stop this?
FYI, Ubuntu is pushing out fixed packages as we speak, so at least that distro is probably going to fix it faster than we could do.
If we wanted to write a hackaround/check, I think the only thing we could do would be to wrap cairo's own calls into XRender functions with checks for "is our display buffer nearly full", and skip the operation if so. (or flush the buffer if possible? not sure if that's something cairo can do. That could be fragile also.) I'm leaning against a hackaround, because: - It could end up preventing harmless drawing (particularly on patched systems) and causing mis-rendering. - The cairo code in question looks a bit hairy / delicate. (The _cairo_xlib_surface_composite_trapezoids function has lots of 'goto BAIL' -- which is probably what we'd use here -- and that rhymes with a recent scary apple security bug.) - There are likely many places where we'd need to add this check, to comprehensively protect against this -- basically any of cairo's calls into an XRender function can trigger this, I think. An attacker just needs an almost-filled-up X "Display" buffer, and a properly-timed call to the SetReqLen() macro (inside xrender) with the right object-size to exactly fill up the buffer. XRenderCompositeTrapezoids is the function that was used for this in the attached testcase, but there are 12 other SetReqLen calls in libxrender (not in XRenderCompositeTrapezoids), many of which are probably exposed to cairo. So given that this is difficult/fragile to safely/comprehensively hack around, and given that Ubuntu's users will be fixed soon, and that we can push to get Debian to fix as well (and any other distro that we happen to see is vulnerable): I think we should just let this be fixed by the library-update. There's a cost/benefit to trying to hack around system library vulnerabilities, and I don't think it makes sense in this case.
(Also: I did end up reaching out to Debian, using their security@debian.org email address & GPG key linked here: https://www.debian.org/security/faq#contact I'll post updates here when I hear back from them.)
(I received a reply to my Debian email, saying "Thanks for the report! We'll make sure to release an update in timely manner.")
(Also, I've now tested Debian unstable, and it seems to be unaffected by this bug. They must've rebuilt their libxrender1 package recently enough.)
This is the same underlying bug as bug 803762 so I'm resolving it as a duplicate. There's not much we can do here except reporting it upstream and hope they deploy the fix properly this time. I agree with Daniel's opinion (comment 38) that the cost/benefit of making workarounds in our code wouldn't be worth it in this case.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → DUPLICATE
(In reply to Mats Palmgren (:mats) from comment #42) > This is the same underlying bug as bug 803762 so I'm resolving it as > a duplicate. This probably makes sense, though it's interesting that the original testcase there became WFM at some point without this actually being fixed. (That may have just been luck -- it's possible that a cairo or gfx patch may have changed things a bit, so that things happened in a slightly different order, so that the perfectly-calibrated testcase there no longer triggered the issue.) One more distro-vulnerability data point: I tested the latest stable OpenSUSE (13.2) Live DVD, in VirtualBox, and verified that it's unaffected. (No ASAN error output at all, when running my minimal C++ program & when viewing the original testcase here in the ASAN firefox linked in comment 0.) I also briefly tried Arch Linux, but it doesn't seem to give you a graphical desktop by default; and without having used it or its package-management system before [& not knowing how well it works in VirtualBox], I'm not going to spend time trying to get an Arch environment set up right now. If anyone here happens to be able to test Arch Linux without too much trouble, it'd probably be worth doing, though.
(With OpenSUSE / Fedora / Ubuntu / Debian all tested & reported as-appropriate, I think we're at the point of diminishing returns for trying to test distros & report the vulnerability to them. Hopefully other distros are paying attention to their Xorg security updates and have already gotten this fix. And if they aren't, they're hopefully a small enough target to make them unattractive to attackers looking to exploit this.)
From my point-of-view it doesn't seem fair, from bounty hunting perspective, to handle this as a Duplicate of bug that was resolved 2012 and as per comment 20 on bug 803762 the test case from that bug do not even reproduce the crash anymore. I understand that the libXrender trunk has been fixed for this issue, and some distros have even shipped the fix, but since that fix you have been vulnerable to this issue for two years in major Linux distros, while thinking that the issue was fixed.
This is a duplicate because it's the exact same underlying issue as bug 803762, which we already reported upstream and even provided the fix for. Whether this bug is eligible for a bounty is a separate discussion, independent of the bug resolution. Note though that we didn't pay a bounty in bug 803762, presumably because the bug was in a system library that we used correctly. It might be eligible for a bounty from the affected Linux distros though, in case they have a similar program.
Flags: sec-bounty?
I got an email today from my Debian security contact, saying that wheezy (Debian stable, 7.8.0) has now shipped a fixed libxrender1 package. (And as noted in comment 41, Debian unstable is unaffected.) Their announcement: https://lists.debian.org/debian-security-announce/2015/msg00112.html I tested locally & verified that, after installing updates, I got no ASAN error output from my C++ testcase, nor from ASAN Firefox with the original SVG testcase here.
Ubuntu stable releases received updates this morning, as well. I've got the latest (non-beta) Ubuntu release "14.10 utopic" installed on my main development desktop. I installed the update there & re-tested my C++ testcase and ASAN Firefox w/ the SVG testcase here, and I got no ASAN error output.
So, summing up: * the latest stable versions of all vulnerable linux distros that I'm aware of (Ubuntu & Debian stable releases) have now received security updates to address this. * Ubuntu 15.04 beta also received an update, and Debian unstable was already unaffected. * Ubuntu LTS (14.04) received an update as well; I haven't tested it, but I'll trust Ubuntu QA on that. (we may want to have our QA sanity-check as well) * Latest Fedora & OpenSuse already had safe libxrender packages, based on my testing. (I wasn't able to reproduce any ASAN issues there.) * I haven't tested other distros beyond those 4. So, I think this is fixed everywhere -- or at least, I'm not aware of any linux distros that are still vulnerable to this.
I'm sorry we have to draw the line somewhere, but this is clearly an OS bug and not one in Firefox, and specifically in Ubuntu who didn't apply a patch we already supplied. Have to deny the bounty here.
Flags: sec-bounty? → sec-bounty-
Group: core-security → core-security-release
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: