Closed Bug 319872 Opened 19 years ago Closed 19 years ago

CVE-2006-0297 probably an integer overflow in jsxml.c

Categories

(Core :: JavaScript Engine, defect, P2)

1.8 Branch
x86
Linux
defect

Tracking

()

VERIFIED FIXED
mozilla1.9alpha1

People

(Reporter: guninski, Assigned: mrbkap)

Details

(Keywords: verified1.8.0.1, verified1.8.0.2, verified1.8.1, Whiteboard: [sg:investigate] critical? [rft-dl])

Attachments

(4 files, 1 obsolete file)

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8) Gecko/20051111 Firefox/1.5
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8) Gecko/20051111 Firefox/1.5

in jsxml.c:2351 EscapeAttributeValue
    if (c == '"')
            newlength += 5;
        else if (c == '<')
            newlength += 3;
        else if (c == '&' || c == '\n' || c == '\r' || c == '\t')
            newlength += 4;

this seems somewhat suspicous, because of "int too big" problem (probably
after multiplication with sizeof(jschar) ).

some empirical evidence suggests SEGV in free() after hitting this code,
though the exact codepath is not determined yet.

exploitability will be determined later.

debug builds die from abort(), but 1.5 release crashes in free.

testcase to follow.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1220606272 (LWP 16742)]
0xb753e339 in free () from /lib/tls/libc.so.6

#0  0xb753e339 in free () from /lib/tls/libc.so.6
#1  0xb7fc2ea9 in js_ReportCompileErrorNumberUC ()
   from /opt/firefox15/libmozjs.so
#2  0xb7fc2ef7 in js_FinishStringBuffer () from /opt/firefox15/libmozjs.so
#3  0xb7fd342d in js_IsXMLName () from /opt/firefox15/libmozjs.so
#4  0xb7fd3954 in js_IsXMLName () from /opt/firefox15/libmozjs.so
#5  0xb7fd9b62 in js_IsXMLName () from /opt/firefox15/libmozjs.so
#6  0xb7f989b9 in js_Invoke () from /opt/firefox15/libmozjs.so
#7  0xb7fa1717 in js_Interpret () from /opt/firefox15/libmozjs.so
#8  0xb7f99011 in js_Execute () from /opt/firefox15/libmozjs.so
#9  0xb7f78a28 in JS_EvaluateUCScriptForPrincipals ()
   from /opt/firefox15/libmozjs.so

(gdb) x/i $eip
0xb753e339 <free+73>:   mov    0x4(%ecx),%eax
(gdb) p/x $eax
$1 = 0xb76037e4
(gdb) p/x $ecx
$2 = 0xfffffff9



Reproducible: Always

Steps to Reproduce:
testcase
Actual Results:  
crash in free()

Expected Results:  
crash free
Version: unspecified → 1.5 Branch
Attached file crash in free()
crash in free()
Assignee: nobody → mrbkap
Component: Security → JavaScript Engine
Flags: blocking1.9a1+
Flags: blocking1.8.0.1+
Product: Firefox → Core
Whiteboard: [sg:investigate] critical?
Version: 1.5 Branch → 1.8 Branch
Status: UNCONFIRMED → NEW
Ever confirmed: true
QA Contact: firefox → general
Status: NEW → ASSIGNED
Priority: -- → P2
Target Milestone: --- → mozilla1.9alpha
no action, so adding management without offensing words.
management knows better.
good management.
I'm sorry for not commenting earlier. I have a patch in hand and am currently running it through tests to ensure that it does not introduce any regressions. I didn't bother commenting because I feel that, in general, the "Status" of a bug is sufficient to indicate that I am working on a fix. So there has certainly been action on this bug.
Attached patch patch v1 (obsolete) — Splinter Review
I cannot reproduce the crash on my machine (though it's brought almost to its knees), but this should fix the overflow.

I also found a bug in the use of StringBuffer::grow (please excuse my dirty C++ syntax here!) where we were too agressively growing the string.
Attachment #205755 - Flags: review?(brendan)
Comment on attachment 205755 [details] [diff] [review]
patch v1

> static JSBool
> GrowStringBuffer(JSStringBuffer *sb, size_t newlength)
> {
>     ptrdiff_t offset;
>     jschar *bp;
> 
>     offset = PTRDIFF(sb->ptr, sb->base, jschar);
>-    newlength += offset;
>-    bp = (jschar *) realloc(sb->base, (newlength + 1) * sizeof(jschar));
>+    newlength += offset + 1;
>+    if (newlength > offset && newlength < ~(size_t)0 / sizeof(jschar))

Put this in number-line order:

>+    if (offset < newlength && newlength < ~(size_t)0 / sizeof(jschar))

Also, you'll need to cast offset to (size_t) to shut up an MSVC warning.

Pick these nits and r=me (new patch in bug only for branch landing and verification).

Thanks for fixing these(! what was I thinking adding the offset in the callers?) bugs,

/be
Attachment #205755 - Flags: review?(brendan) → review+
I added the cast and an assertion to make sure that casting |offset| wasn't going to do the wrong thing.
Attachment #205755 - Attachment is obsolete: true
Attachment #205762 - Flags: review?(brendan)
Comment on attachment 205762 [details] [diff] [review]
Patch for checkin

r=me, nominate for branches once this bakes a bit on the trunk.

/be
Attachment #205762 - Flags: review?(brendan) → review+
Fix checked into trunk.
Status: ASSIGNED → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
Although there is a testcase outlined in this bug, it is one that doesn't complete in a time short enough to allow it to be placed in the normal JavaScript Test Library so I am marking this testcase-.
Flags: testcase-
Comment on attachment 205762 [details] [diff] [review]
Patch for checkin

Another security fix that has been thoroughly baked on the trunk.

/be
Attachment #205762 - Flags: approval1.8.1?
Attachment #205762 - Flags: approval1.8.0.1?
Comment on attachment 205762 [details] [diff] [review]
Patch for checkin

a=dveditz for drivers
Attachment #205762 - Flags: approval1.8.1?
Attachment #205762 - Flags: approval1.8.1+
Attachment #205762 - Flags: approval1.8.0.1?
Attachment #205762 - Flags: approval1.8.0.1+
Fix checked into the branches.
I've rethought the time limit and think we can put this in the automated tests after all.

no crash in 1.8.0.1, 1.8.1, 1.9a1 on winxp 20060112

no crash in 1.8.0.1 linux 20060112

crash in 1.8.1 linux 20060112 TB13900472

libc.so.6 + 0x61e79 (0x00c3de79)
FreeStringBuffer()  [/builds/tinderbox/Fx-Mozilla1.8/Linux_2.4.21-27.0.4.ELsmp_Depend/mozilla/js/src/jsscan.c, line 823]

crash in 1.9a1 linux 20060112 TB13900588

libc.so.6 + 0x61e79 (0x00e29e79)
FreeStringBuffer()  [/builds/tinderbox/Fx-Trunk/Linux_2.4.21-27.0.4.ELsmp_Depend/mozilla/js/src/jsscan.c, line 823]
Status: RESOLVED → REOPENED
Flags: testcase- → testcase?
Resolution: FIXED → ---
Flags: testcase? → testcase+
Attached patch Fix the bad callSplinter Review
In a debug build, you would have noticed an assertion in jsscan.c. The problem is fairly obvious: in the case that !STRING_BUFFER_OK(&sb), we were reporting oom and jumping to out:, where we would only test for str != null (with no assignments to str outside of null) and try to free the sentinal value. Rearranging the label won't work, so here's the patch to not free when we don't want to.
Attachment #208787 - Flags: review?(brendan)
Comment on attachment 208787 [details] [diff] [review]
Fix the bad call

r=me, thanks for fixing this.

/be
Attachment #208787 - Flags: review?(brendan)
Attachment #208787 - Flags: review+
Attachment #208787 - Flags: approval1.8.1?
Attachment #208787 - Flags: approval1.8.0.2?
Flags: blocking1.8.0.2?
Fixed on trunk, again.
Status: REOPENED → RESOLVED
Closed: 19 years ago19 years ago
Resolution: --- → FIXED
Flags: blocking1.7.13-
Flags: blocking-aviary1.0.8-
Keywords: fixed1.8.1
sorry for the bugspam, saw the checkin and thought the missing fixed1.8.1 was as oversight, but it was removed with comment 13
Keywords: fixed1.8.1
There are other issues with this that I need to sort out. I verified based on the results of the browser based tests which don't necessarily run long enough to show  crashes. I am rebuilding with the patch in attachment 208787 [details] [diff] [review] to get a better idea of what is happening.
(In reply to comment #19)
with  attachment 208787 [details] [diff] [review] I crash in windows firefox 1.5 (1.8)

JSHashNumber
js_HashString(JSString *str)
{
    JSHashNumber h;
    const jschar *s;
    size_t n;

    h = 0;
    for (s = JSSTRING_CHARS(str), n = JSSTRING_LENGTH(str); n; s++, n--)
->        h = (h >> (JS_HASH_BITS - 4)) ^ (h << 4) ^ *s;
    return h;
}


	h	0x00000000
	n	0x2fa6001a
+	s	0x00000001 ""
-	str	0x0013dc48
	length	0x2fa6001a
+	chars	0x00000001 ""


js_HashString(JSString * 0x0013dc48) line 2811 + 19 bytes
js_AtomizeString(JSContext * 0x00032dd8, JSString * 0x0013dc48, unsigned int 0x00000080) line 650 + 9 bytes
js_AtomizeChars(JSContext * 0x00032dd8, const unsigned short * 0x00000001, unsigned int 0x2fa6001a, unsigned int 0x00000000) line 752 + 19 bytes
js_GetToken(JSContext * 0x00032dd8, JSTokenStream * 0x004a9af8) line 1271 + 42 bytes
js_MatchToken(JSContext * 0x00032dd8, JSTokenStream * 0x004a9af8, int 0x00000043) line 2130 + 13 bytes
XMLTagContent(JSContext * 0x00032dd8, JSTokenStream * 0x004a9af8, JSTreeContext * 0x0013e308, int 0x0000003d, JSAtom * * 0x0013e244) line 3407 + 15 bytes
XMLElementOrList(JSContext * 0x00032dd8, JSTokenStream * 0x004a9af8, JSTreeContext * 0x0013e308, int 0x00000000) line 3534 + 23 bytes
XMLElementContent(JSContext * 0x00032dd8, JSTokenStream * 0x004a9af8, JSParseNode * 0x004a9dd0, JSTreeContext * 0x0013e308) line 3486 + 19 bytes
XMLElementOrList(JSContext * 0x00032dd8, JSTokenStream * 0x004a9af8, JSTreeContext * 0x0013e308, int 0x00000000) line 3584 + 21 bytes
XMLElementOrListRoot(JSContext * 0x00032dd8, JSTokenStream * 0x004a9af8, JSTreeContext * 0x0013e308, int 0x00000000) line 3671 + 21 bytes
js_ParseXMLTokenStream(JSContext * 0x00032dd8, JSObject * 0x000387c8, JSTokenStream * 0x004a9af8, int 0x00000000) line 3717 + 24 bytes
ParseXMLSource(JSContext * 0x00032dd8, JSString * 0x008d7ff8) line 1943 + 25 bytes
ToXML(JSContext * 0x00032dd8, long 0x008d7ffc) line 2042 + 13 bytes
XML(JSContext * 0x00032dd8, JSObject * 0x008d86a8, unsigned int 0x00000001, long * 0x0041db8c, long * 0x0013e524) line 7051 + 13 bytes
js_Invoke(JSContext * 0x00032dd8, unsigned int 0x00000001, unsigned int 0x00000001) line 1177 + 23 bytes
js_Interpret(JSContext * 0x00032dd8, unsigned char * 0x00420771, long * 0x0013ee20) line 3095 + 15 bytes
js_Execute(JSContext * 0x00032dd8, JSObject * 0x000387c8, JSScript * 0x00420670, JSStackFrame * 0x00000000, unsigned int 0x00000000, long * 0x0013fecc) line 1423 + 19 bytes
JS_ExecuteScript(JSContext * 0x00032dd8, JSObject * 0x000387c8, JSScript * 0x00420670, long * 0x0013fecc) line 3999 + 25 bytes
Process(JSContext * 0x00032dd8, JSObject * 0x000387c8, char * 0x00032d2a) line 223 + 22 bytes
ProcessArgs(JSContext * 0x00032dd8, JSObject * 0x000387c8, char * * 0x00032cc4, int 0x00000003) line 470 + 17 bytes
main(int 0x00000003, char * * 0x00032cc4, char * * 0x00033268) line 2565 + 21 bytes
JS! mainCRTStartup + 227 bytes
KERNEL32! 7c816d4f()

I am ASSuming this is related to the overlong string crash in bug 342422 and the int overflow is indeed resolved with this patch. I'll try the patch in bug 324422 combined with this.
Bob, would you file a new bug on that crash? If it turns out to be a dupe, we'll mark it then.
(In reply to comment #21)
Filed Bug 324533 
Summary: probably an integer overflow in jsxml.c → CVE-2006-0297 probably an integer overflow in jsxml.c
regarding CVE in the summary:

i consider mitre/CVE corporate/government's puppies and have low opinion of
them.

mitre's  "Steven M. Christey" <coley@linus.mitre.org>
co-authored the "responsible disclosure draft rfc" which was
obviously a corporate plot and was ditched by even the IETF - check the
ietf archives for this corporate fiasco.
Attachment #208787 - Flags: approval1.8.1? → branch-1.8.1?(brendan)
Comment on attachment 208787 [details] [diff] [review]
Fix the bad call

approving for 1.8 and 1.8.0 branch checkin.

/be
Attachment #208787 - Flags: branch-1.8.1?(brendan)
Attachment #208787 - Flags: branch-1.8.1+
Attachment #208787 - Flags: approval1.8.0.2?
Attachment #208787 - Flags: approval1.8.0.2+
Group: security
Flags: blocking1.8.0.2? → blocking1.8.0.2+
I don't have a stack for this, but this now crashes in 1.8/1.8.0.1 linux only in browser tests on e4x/Regress/regress-319872.js

linux-1.8_2006020704
linux-1.8.0.1_2006020704
Keywords: verified1.8.0.1
Isn't that just bug 324533?
(In reply to comment #26)
> Isn't that just bug 324533?
> 

yeah.
Status: RESOLVED → VERIFIED
Second fix checked into the 1.8.0.2 branch.
Keywords: fixed1.8.0.2
Marking [rft-dl] (ready for testing in Firefox 1.5.0.2 release candidates) since in-testsuite+ indicates a test case exists in the js test library.
Whiteboard: [sg:investigate] critical? → [sg:investigate] critical? [rft-dl]
(In reply to comment #29)
> Marking [rft-dl] (ready for testing in Firefox 1.5.0.2 release candidates)
> since in-testsuite+ indicates a test case exists in the js test library.

Are these status whiteboard marks documented somewhere?  Thanks,

/be
v ff 1.8.0.1/1.8/1.9 20060302 win/linux/mac
Although I wasn't able to reproduce it with my local builds, I saw a crash in the trunk shell on windows from 20060328. No crashes in the browser versions of the tests or on mac or linux.
(In reply to comment #32)
> No crashes in the browser versions of
> the tests or on mac or linux.
> 

for me linux trunk also seems safe.
Checking in regress-319872.js;
/cvsroot/mozilla/js/tests/e4x/Regress/regress-319872.js,v  <--  regress-319872.js
initial revision: 1.1
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: