Closed
Bug 628228
Opened 13 years ago
Closed 3 years ago
TextRun integer overflow
Categories
(Core :: Layout: Text and Fonts, defect)
Tracking
()
RESOLVED
INCOMPLETE
People
(Reporter: info, Assigned: jfkthame)
Details
(Keywords: crash, testcase, Whiteboard: [sg:dos?][null-pointer access or oom])
Attachments
(2 files, 1 obsolete file)
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:2.0b10pre) Gecko/20110123 Firefox/4.0b10pre Build Identifier: TextRun integer overflow. ------------------------ Integer overflow on a TextRun, which is likely to be exploitable. Affected: --------- Mozilla Firefox 3.6.13 Minefield 4.0b10pre (2011-01-23) (nightly) Image ----- memory\jemalloc\crtsrc\new.cpp @ 61 Procedure: ----------- 0012a5a8 100c0ad4 MOZCRT19!operator new(unsigned int size = 0x41414141)+0x73 0012a668 101106fd xul!gfxWindowsFontGroup::MakeTextRun(unsigned char * aString = 0x41414141 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX... Stack trace ----------- CPU - main thread, module kernel32 EAX 0012A890 ECX 00000000 EDX 781D7BA8 MOZCRT19.781D7BA8 EBX 01100121 ESP 0012A88C EBP 0012A8E0 ESI 0012A918 EDI 00000164 EIP 7C812AFB kernel32.7C812AFB C 0 ES 0023 32bit 0(FFFFFFFF) P 1 CS 001B 32bit 0(FFFFFFFF) A 0 SS 0023 32bit 0(FFFFFFFF) Z 0 DS 0023 32bit 0(FFFFFFFF) S 0 FS 003B 32bit 7FFDE000(FFF) T 0 GS 0000 NULL D 0 O 0 LastErr 00000000 ERROR_SUCCESS EFL 00200206 (NO,NB,NE,A,NS,PE,GE,G) ST0 empty 61.000000000000000000 ST1 empty 0.0 ST2 empty 1.0000000000000000000 ST3 empty 0.0 ST4 empty 0.0 ST5 empty 0.0 ST6 empty 0.0 ST7 empty 0.0 3 2 1 0 E S P U O Z D I FST 0120 Cond 0 0 0 1 Err 0 0 1 0 0 0 0 0 (LT) FCW 027F Prec NEAR,53 Mask 1 1 1 1 1 1 Last cmnd 001B:10110277 xul.10110277 XMM0 00000000 00000000 00000000 00000000 XMM1 00000000 00000000 00000000 00000000 XMM2 00000000 00000433 00000000 00000433 XMM3 00000000 00000000 00000000 00000000 XMM4 01D8B000 7FDE7800 7FDE7400 7B3A4C00 XMM5 7FDDE800 7FDDE000 7FDDD800 7FDDD000 XMM6 7FDE0800 7FDE0000 7FDDF800 7FDDF000 XMM7 00000000 00000000 00000000 00000000 P U O Z D I MXCSR 00001FA1 FZ 0 DZ 0 Err 1 0 0 0 0 1 Rnd NEAR Mask 1 1 1 1 1 1 CPU Stack Address Value ASCII Comments 0012A88C /04C19320 ?Á 0012A890 |E06D7363 csmà 0012A894 |00000001 ... 0012A898 |00000000 .... 0012A89C |7C812AFB û*| ; RETURN from ntdll.RtlRaiseException to kernel32.7C812AFB 0012A8A0 |00000003 ... 0012A8A4 |19930520 ? 0012A8A8 |0012A928 (©. 0012A8AC |781CAA34 4ªx 0012A8B0 |0000000C .... 0012A8B4 |78132E76 v.x ; RETURN to MOZCRT19.78132E76 0012A8B8 |0081110C .. 0012A8BC |781A8A50 P?x 0012A8C0 |7813D051 QÐx ; RETURN from MOZCRT19._encode_pointer to MOZCRT19.7813D051 0012A8C4 |0081110C .. 0012A8C8 |781A8A50 P?x 0012A8CC |781324C4 Ä$x ; RETURN from ntdll.RtlLeaveCriticalSection to MOZCRT19.781324C4 0012A8D0 |781D7BA8 ¨{x 0012A8D4 |0012A914 ©. 0012A8D8 |781317B7 ·x ; RETURN from MOZCRT19._unlock to MOZCRT19.781317B7 0012A8DC |00000008 ... 0012A8E0 |0012A918 ©. 0012A8E4 \7815C52B +Åx ; RETURN from kernel32.RaiseException to MOZCRT19.7815C52B 0012A8E8 E06D7363 csmà ; Code = E06D7363 0012A8EC 00000001 ... ; Flags = EXCEPTION_NONCONTINUABLE 0012A8F0 00000003 ... ; ArgCount = 3 0012A8F4 0012A90C .©. ; Arguments = 0012A90C -> 19930520 / snip 0012AA7C 8000000A ...? 0012AA80 0012C54C LÅ. ; ASCII 41,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 0012AA84 0012B0D0 а. 0012AA88 10110816 ; RETURN from xul.102EF6E0 to xul.10110816 0012AA8C 00000011 ... 0012AA90 04C331A0 1à 0012AA94 00000000 .... 0012AA98 00000000 .... 0012AA9C 33730F50 Ps3 0012AAA0 0012ACE8 è¬. 0012AAA4 01D98300 .?Ù 0012AAA8 38764940 @Iv8 0012AAAC 00000000 .... 0012AAB0 800000C8 È..? 0012AAB4 41414141 AAAA 0012AAB8 41414141 AAAA 0012AABC 41414141 AAAA 0012AAC0 41414141 AAAA 0012AAC4 41414141 AAAA 0012AAC8 41414141 AAAA 0012AACC 41414141 AAAA 0012AAD0 41414141 AAAA 0012AAD4 41414141 AAAA 0012AAD8 41414141 AAAA 0012AADC 41414141 AAAA 0012AAE0 41414141 AAAA 0012AAE4 41414141 AAAA 0012AAE8 41414141 AAAA 0012AAEC 41414141 AAAA 0012AAF0 41414141 AAAA 0012AAF4 41414141 AAAA 0012AAF8 41414141 AAAA 0012AAFC 41414141 AAAA 0012AB00 41414141 AAAA 0012AB04 41414141 AAAA 0012AB08 41414141 AAAA 0012AB0C 41414141 AAAA 0012AB10 41414141 AAAA 0012AB14 41414141 AAAA 0012AB18 41414141 AAAA 0012AB1C 41414141 AAAA 0012AB20 41414141 AAAA 0012AB24 41414141 AAAA 0012AB28 41414141 AAAA 0012AB2C 41414141 AAAA 0012AB30 41414141 AAAA 0012AB34 41414141 AAAA 0012AB38 41414141 AAAA 0012AB3C 41414141 AAAA 0012AB40 41414141 AAAA 0012AB44 41414141 AAAA 0012AB48 41414141 AAAA 0012AB4C 41414141 AAAA 0012AB50 41414141 AAAA 0012AB54 41414141 AAAA 0012AB58 41414141 AAAA 0012AB5C 41414141 AAAA 0012AB60 41414141 AAAA 0012AB64 41414141 AAAA 0012AB68 41414141 AAAA 0012AB6C 41414141 AAAA 0012AB70 41414141 AAAA 0012AB74 41414141 AAAA 0012AB78 41414141 AAAA Example. -------- <script> var el = document.createElement('div'); el = document.body.appendChild(el); var stack = "AAAAAAAAAAAAAAAA"; // 16 function bar() { for(i=0;i<1000000;i++){ it =document.createElement('option'); it.innerHTML = stack; it=el.appendChild(it); stack += 'XXXX'; // +4 } for(k=0;k<1000000;k++) { it.innerHTML= stack; } } setInterval("bar()",1); </script> Reproducible: Always Steps to Reproduce: 1. run test case (will launch automatically) 2. wait. If it doesn't crash, increment the loop 3. should crash. Actual Results: Buffer overflow we could control. Expected Results: Don't overflow.
Reporter | ||
Comment 1•13 years ago
|
||
Reporter | ||
Comment 2•13 years ago
|
||
Reporter | ||
Updated•13 years ago
|
Component: General → Security
Reporter | ||
Comment 3•13 years ago
|
||
The 1st test case didn't have BODY tag, and thus will not work. My apologies. The first test case can be removed.
Reporter | ||
Comment 4•13 years ago
|
||
I'm rushing it ;-) The first test case didn't have a BODY element, my apologies. Please run the 2nd test case. The 1st one can be deleted since it will not work.
Reporter | ||
Updated•13 years ago
|
Attachment #506336 -
Attachment is obsolete: true
Updated•13 years ago
|
Component: Security → Layout: Text
QA Contact: general → layout.fonts-and-text
Assignee: nobody → jfkthame
Comment 5•13 years ago
|
||
> TextRun integer overflow
Where do you see an integer overflow?
Comment 6•13 years ago
|
||
I have tested this on XP, Win7, Linux and OSX. Both trunk and branch builds. I didn't see any evidence of integer overflow anywhere. The vast majority of crashes are deliberate process termination on out-of-memory. I got a few null-pointer crashes due to malloc returning NULL in non-jemalloc builds (1.9.2 on OSX). No scary crashes AFAICT.
Reporter | ||
Comment 7•13 years ago
|
||
Hi Mats, It's there, but probably not very obvious. Let's say we use a 32-bit unsigned integer constant 0xffffffff: var stack = unescape("\xff\xff\xff\xff\xff\xff\xff\xff"); Then this is what happens: -------------------------------------------------------- 0012a5a8 100c0ad4 MOZCRT19!operator new(unsigned int size = 0xffffffff)+0x73 0012a668 101106fd xul!gfxWindowsFontGroup::MakeTextRun(unsigned char * aString = 0xffffffff "--- memory read error at address 0xffffffff ---" -------------------------------------------------------- We obviously get a memory read error. If we add 0x1 we should be able to overflow it. (0xffffffff + 1 = 0x0) In my case it did, because our application did not crash anymore with the addition. Since I have to trigger an exception to see what is going on, I can not use it in a bug report since one will be under the impression that nothing has happened. Even if it didn't overflow, it's unwise to let me control a pointer at will. At a minimum it could be a NULL, but that is bad enough. I could be completely wrong though, but this what I noticed so far.
Comment 8•13 years ago
|
||
> We obviously get a memory read error.
WinDbg got a memory read error when it tried to read that address
to display the string value, but that's an entirely different matter.
You can't trust what WinDbg says about the values on the stack in an
optimized build. I'm pretty sure neither gfxWindowsFontGroup::MakeTextRun
nor 'operator new' was called with the values that WinDbg shows.
GDB on Linux/OSX gets this wrong too when used on release builds.
As far as I know, the only way to see the correct values is to use
a debug build (and even that fails sometimes).
Reporter | ||
Comment 9•13 years ago
|
||
I use three debuggers: Ollydbg, Immunity and Windbg. Trace is done in Olly. I only got the symbols for Windbg. Btw, if I run a nightly it loads faulty symbols. Any idea why this happens?
Reporter | ||
Comment 10•13 years ago
|
||
The operator_new accounts for it. -> obj-firefox/memory/jemalloc/src/new.cpp Should be a failed malloc, possibly followed by a dereferenced NULL pointer Looks pretty consistent to me so far. I know OOM's get called out quickly, but remember that we don't always have to crash towards an exception. There are quite a couple of bugs listed on Bugzilla that _are_ exploitable and were called out for an OOM, then supposedly we're fixed while returning a couple months later with a full-blown exploit. Also, I did not get an OOM on Minefield 4.0b10pre 2011-01-23 nightly. It simply crashed.
Comment 11•13 years ago
|
||
> Also, I did not get an OOM on Minefield 4.0b10pre 2011-01-23 nightly.
> It simply crashed.
In VS Express 2008 I get this stack for a 4.0b10pre 2011-01-25 nightly:
mozalloc.dll!mozalloc_abort(const char * const msg=0x003e20fc) Line 77 C++
mozalloc.dll!mozalloc_handle_oom() Line 54 + 0xa bytes C++
xul.dll!nsTArray_base<nsTArrayDefaultAllocator>::EnsureCapacity(unsigned int capacity=0x00003fe1, unsigned int elemSize=0x00000004) Line 98 + 0x11 bytes C++
xul.dll!gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext * aContext=0x03f99a90, gfxTextRun * aTextRun=0x5c0ffe20, _hb_buffer_t * aBuffer=0x3a4fd400, unsigned int aTextRunOffset=0x00000000, unsigned int aRunLength=0x00003fe1) Line 980 + 0x2a bytes C++
xul.dll!gfxHarfBuzzShaper::InitTextRun(gfxContext * aContext=, gfxTextRun * aTextRun=, const wchar_t * aString=, unsigned int aRunStart=, unsigned int aRunLength=, int aRunScript=) Line 884 C++
...
It looks like a safe OOM abort to me.
Reporter | ||
Comment 12•13 years ago
|
||
There is indeed a difference in the stack from Mozilla Firefox 3.6.13 and Minefield 4.0b10pre 2011-01-23. The above traces were only done on 3.6.13. Here is a trace I just did with Minefield 4.0b10pre 2011-01-23 nightly, and is consistent with your comment. However, it does crash my copy. Also, I noticed yesterday that we don't need huge loops. A mere 27000 rounds (of added elements) will suffice, and that number might be even lower yet. CPU - main thread, module mozalloc EAX 00000000 ECX 362C0BF9 EDX 781D6C50 MOZCRT19.781D6C50 EBX 00000000 ESP 0012D54C EBP 0012D57C ESI 78143280 MOZCRT19.__iob_func EDI 78187640 MOZCRT19.fputs EIP 003E1A3A mozalloc.003E1A3A XMM0 00580058 00580058 00580058 00580058 XMM1 00580058 00580058 00580058 00580058 XMM2 00580058 00580058 00580058 00580058 XMM3 00580058 00580058 00580058 00580058 XMM4 00580058 00580058 00580058 00580058 XMM5 00580058 00580058 00580058 00580058 XMM6 00580058 00580058 00580058 00580058 CPU Disasm Address Hex dump Command Comments 003E1A3A 8B0D 00000000 MOV ECX,DWORD PTR DS:[0] 003E1A40 010D 48333E00 ADD DWORD PTR DS:[3E3348],ECX 003E1A46 6A 7F PUSH 7F 003E1A48 FF15 78203E00 CALL DWORD PTR DS:[<&MOZCRT19._exit>] 003E1A4E 5F POP EDI 003E1A4F 5E POP ESI 003E1A50 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] 003E1A54 8B01 MOV EAX,DWORD PTR DS:[ECX] 003E1A56 8B50 04 MOV EDX,DWORD PTR DS:[EAX+4] 003E1A59 FFD2 CALL EDX 003E1A5B 50 PUSH EAX 003E1A5C E8 ADFFFFFF CALL ?mozalloc_abort@@YAXQBD@Z 003E1A61 CC INT3 003E1A62 68 FC203E00 PUSH OFFSET 003E20FC ; ASCII "out of memory" 003E1A67 E8 A2FFFFFF CALL ?mozalloc_abort@@YAXQBD@Z 003E1A6C CC INT3 003E1A6D 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8] 003E1A71 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] 003E1A75 56 PUSH ESI 003E1A76 50 PUSH EAX 003E1A77 51 PUSH ECX 003E1A78 E8 25F6FFFF CALL <JMP.&MOZCRT19.memalign> ; Jump to MOZCRT19.memalign 003E1A7D 8BF0 MOV ESI,EAX 003E1A7F 83C4 08 ADD ESP,8 003E1A82 85F6 TEST ESI,ESI 003E1A84 75 10 JNE SHORT 003E1A96 003E1A86 FF15 A4203E00 CALL DWORD PTR DS:[<&MOZCRT19._errno>] 003E1A8C 8338 16 CMP DWORD PTR DS:[EAX],16 003E1A8F 74 05 JE SHORT 003E1A96 003E1A91 ^ E9 CCFFFFFF JMP ?mozalloc_handle_oom@@YAXXZ 003E1A96 8BC6 MOV EAX,ESI 003E1A98 5E POP ESI 003E1A99 C3 RETN 003E1A9A 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+0C] 003E1A9E 8B4C24 08 MOV ECX,DWORD PTR SS:[ESP+8] 003E1AA2 8B5424 04 MOV EDX,DWORD PTR SS:[ESP+4] 003E1AA6 50 PUSH EAX 003E1AA7 51 PUSH ECX 003E1AA8 52 PUSH EDX 003E1AA9 E8 12F6FFFF CALL <JMP.&MOZCRT19.posix_memalign> ; Jump to MOZCRT19.posix_memalign 003E1AAE 83C4 0C ADD ESP,0C 003E1AB1 85C0 TEST EAX,EAX 003E1AB3 74 0A JE SHORT 003E1ABF 003E1AB5 83F8 0C CMP EAX,0C 003E1AB8 75 05 JNE SHORT 003E1ABF 003E1ABA ^ E9 A3FFFFFF JMP ?mozalloc_handle_oom@@YAXXZ 003E1ABF C3 RETN 003E1AC0 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] 003E1AC4 50 PUSH EAX 003E1AC5 FF15 A8203E00 CALL DWORD PTR DS:[<&MOZCRT19._strdup>] 003E1ACB 83C4 04 ADD ESP,4 003E1ACE 85C0 TEST EAX,EAX 003E1AD0 75 05 JNE SHORT 003E1AD7 003E1AD2 ^ E9 8BFFFFFF JMP ?mozalloc_handle_oom@@YAXXZ 003E1AD7 C3 RETN 003E1AD8 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8] 003E1ADC 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] 003E1AE0 50 PUSH EAX 003E1AE1 51 PUSH ECX 003E1AE2 E8 E5F5FFFF CALL <JMP.&MOZCRT19.calloc> ; Jump to MOZCRT19.calloc 003E1AE7 83C4 08 ADD ESP,8 003E1AEA 85C0 TEST EAX,EAX 003E1AEC 75 05 JNE SHORT 003E1AF3 003E1AEE ^ E9 6FFFFFFF JMP ?mozalloc_handle_oom@@YAXXZ 003E1AF3 C3 RETN
Comment 13•12 years ago
|
||
I don't see evidence that this bug needs to remain private. Seems like Mats doesn't either. Opening it up. Marking confirmed since Mats was able to reproduce.
Group: core-security
Status: UNCONFIRMED → NEW
Ever confirmed: true
Comment 14•3 years ago
|
||
Marking this as Resolved > Incomplete since the attached test case isn't working anymore and the reporter cannot be contacted to provide a result of the issue.
Status: NEW → RESOLVED
Closed: 3 years ago
Resolution: --- → INCOMPLETE
You need to log in
before you can comment on or make changes to this bug.
Description
•