Open Bug 615465 Opened 14 years ago Updated 2 years ago

future-proof allocations in txNodeSet::ensureGrowSize

Categories

(Core :: XSLT, defect)

x86
Linux
defect

Tracking

()

Tracking Status
blocking2.0 --- -

People

(Reporter: alexander.miller, Unassigned)

References

()

Details

(Keywords: sec-other, Whiteboard: [sg:nse])

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.10 (maverick) Firefox/3.6.12
Build Identifier: 

Provided the target's system has enough memory, two possible integer overflows resulting in incorrect allocation are possible at:

http://mxr.mozilla.org/mozilla-central/source/content/xslt/src/xpath/txNodeSet.cpp#553

(The developer even acknowledged memory safety hazards there)

http://mxr.mozilla.org/mozilla-central/source/content/xslt/src/xpath/txNodeSet.cpp#527

When overflown there, it is possible to trick the program in to thinking it has space to put the node, and if it doesn't node data overwrites adjacent memory.

Reproducible: Didn't try




In the IRC I was discussing this with bz, and because of the way operator new[] is compiled, this should only be exploitable on builds that were built with gcc, so at least for now, I'm marking this as Linux only.
Depends on: 466445
We're doing the multiplication-by-sizeof outselves here, so this isn't the gcc bug.
No longer depends on: 466445
Jonas, can you have a look here?
Assignee: nobody → jonas
Whiteboard: [sg:critical]
Whiteboard: [sg:critical]
This doesn't look exploitable to me.

(Math below for 32bit)

In order for this allocation to overflow |newLength * sizeof(txXPathNode)| needs to be bigger than 2^32. In order for that to be the case we need newLength to be
greater than 2^32/8 = 2^29. Since we use a growing factor of 2, this means that we have to be growing a nodeset which is 2^28 in size.

Since nodesets always contain unique nodes, this means that we have to have 2^28 nodes. However the smallest node that I see is an empty textnode which in 1.9.2 is 6 words = 24 bytes large. These nodes also need to live in a child-list, meaning an extra 4 bytes per node is needed there.

This means that we'll need to have 28*2^28 = 1.75 * 2^32 bytes of node data. This is more than what fits in a 32bit process.

The math works out the same way on 64bit, just with bigger numbers.


You could try to create 2^27 nodes, and create two nodesets which contain them all and then merge those two nodesets. In that case we pessimistically allocate for 2^28 node slots and we would overflow.

Howevever even 2^27 nodes plus the two nodesets is enough that we'd run out of memory first.
Should this just be marked INVALID?
I wouldn't mind making this code more resilient against future changes.
Not blocking.
blocking2.0: beta9+ → -
Status: UNCONFIRMED → NEW
Ever confirmed: true
Summary: Two possible buffer overflows in txNodeSet::ensureGrowSize → future-proof allocations in txNodeSet::ensureGrowSize
Whiteboard: [sg:nse]
Group: core-security
Severity: normal → S3

The bug assignee is inactive on Bugzilla, so the assignee is being reset.

Assignee: jonas → nobody
You need to log in before you can comment on or make changes to this bug.