Deallocator mismatch in SECITEM_ArenaDupItem()
Categories
(NSS :: Libraries, defect, P1)
Tracking
(firefox-esr115128+ fixed, firefox126 wontfix, firefox127 wontfix, firefox128+ fixed)
People
(Reporter: mozillabugs, Assigned: jschanck)
References
Details
(Keywords: reporter-external, sec-moderate, Whiteboard: [post-critsmash-triage][adv-main128+][adv-esr115.13+])
Attachments
(2 files)
SECITEM_ArenaDupItem() (security/nss/lib/util/secitem.c) calls the incorrect deallocator on lines 258-61 (below) if lines 253-55 fail to allocate to->data. Lines 258-61 unconditionally call PORT_Free(to), which is incorrect if to was allocated from an arena, as by lines 244-46.
Code from FIREFOX_124_0_2_RELEASE:
235: SECItem *
236: SECITEM_ArenaDupItem(PLArenaPool *arena, const SECItem *from)
237: {
238: SECItem *to;
239:
240: if (from == NULL) {
241: return (NULL);
242: }
243:
244: if (arena != NULL) {
245: to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
246: } else {
247: to = (SECItem *)PORT_Alloc(sizeof(SECItem));
248: }
249: if (to == NULL) {
250: return (NULL);
251: }
252:
253: if (arena != NULL) {
254: to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len);
255: } else {
256: to->data = (unsigned char *)PORT_Alloc(from->len);
257: }
258: if (to->data == NULL) {
259: PORT_Free(to);
260: return (NULL);
261: }
262:
263: to->len = from->len;
264: to->type = from->type;
265: if (to->len) {
266: PORT_Memcpy(to->data, from->data, to->len);
267: }
268:
269: return (to);
270: }
Here is a debugger-based POC:
- Start FF with
-profilemanagerand attach a debugger to it. - Set a BP on line 254, but disable it.
- Click "start".
- Load, e.g., https://www.nytimes.com
- While it's loading, enable the BP.
- When the BP fires, record the value in
from->len. - Now replace
from->lenwith0x80000000, which guarantees thatPORT_ArenaAlloc()will fail. - Step line 254.
- Replace
from->lenwith the original value you recorded in step 6. - Step through line 259.
- Proceed and watch FF crash, possibly in
arena_run_reg_dalloc()with a "double free?"RELEASE_ASSERT, and possibly elsewhere with an access violation.
This bug has existed at least since the earliest version of NSS (3.10) on https://ftp.mozilla.org/pub/security/nss/releases/ . Presumably it's an inheritance from Netscape.
| Assignee | ||
Comment 1•1 year ago
|
||
SECItem_ArenaDupItem is not used very often (searchfox). But it is used in CERT_DecodeGeneralName which is called from cert_GetCertificateEmailAddresses by way of CERT_DecodeAltNameExtension. So maybe this is the cause of Bug 1748105? I'm surprised that PORT_ArenaAlloc would fail (other than with a safe OOM crash) in Firefox though.
| Assignee | ||
Comment 2•1 year ago
|
||
| Reporter | ||
Comment 3•1 year ago
|
||
(In reply to John Schanck [:jschanck] from comment #1)
...So maybe this is the cause of Bug 1748105?
Please CC me on that bug if you can.
Updated•1 year ago
|
| Assignee | ||
Comment 4•1 year ago
|
||
It is possible to trigger this without causing an OOM crash because of this condition in PORT_ArenaAlloc.
That said, I spent some time constructing malformed certificates / certificates with very large directoryName SANs / etc, and I was not able to reproduce Bug 1748105 along this path. So I'm leaning towards this double-free being unrelated to Bug 1748105. I've CC'd you anyway.
| Reporter | ||
Comment 5•1 year ago
•
|
||
(In reply to John Schanck [:jschanck] from comment #4)
It is possible to trigger this without causing an OOM crash because of this condition in
PORT_ArenaAlloc.That said, I spent some time constructing malformed certificates / certificates with very large directoryName SANs / etc, and I was not able to reproduce Bug 1748105 along this path. So I'm leaning towards this double-free being unrelated to Bug 1748105. I've CC'd you anyway.
Thanks for the followup. I looked at https://bugzilla.mozilla.org/show_bug.cgi?id=1748105 and have an idea, expanding on your intuition, that might explain it. See that bug for details.
Updated•1 year ago
|
| Assignee | ||
Comment 6•1 year ago
|
||
:glandium, do you know whether Firefox will use an infallible allocator here? We're trying to decide how severe this really is.
| Assignee | ||
Updated•1 year ago
|
Comment 7•1 year ago
|
||
Firefox only uses infallible allocations for operator new and moz_xmalloc/moz_xcalloc/etc..
| Reporter | ||
Comment 8•1 year ago
•
|
||
But PORT_ArenaAlloc() is fallible, at least for large allocations and apparently for all allocations.
PORT_ArenaAlloc() uses PL_ARENA_ALLOCATE(), which uses PR_MALLOC() if it can't just allocate from an arena. PR_MALLOC() uses malloc(), which calls PageMalloc(), which calls MozJemalloc::malloc(), which calls BaseAllocator::malloc(), which calls arena_t::Malloc(), which calls one of arena_t::MallocSmall(), arena_t::MallocLarge(), or arena_t::MallocHuge(), depending on the requested size. These all look fallible. Tracing arena_t::MallocHuge() eventually results in a call to the Windows API VirtualAlloc(). Faking its return value as NULL eventually causes PORT_ArenaAlloc() to return NULL. You can also emulate this by using the debugger to doctor from->len to some large value on line 254, then iterating that line. Eventually it returns NULL, rather than crashing with an OOM like moz_xmalloc().
This path is similar to the one taken by fallible nsTArray, which uses MozJemallocPHC::realloc(), which calls PageRealloc(), which calls BaseAllocator::realloc(), which calls arena_t::Ralloc() or arena_t::Malloc(), the latter of which joins the flow above.
Updated•1 year ago
|
| Assignee | ||
Comment 9•1 year ago
•
|
||
Updated•1 year ago
|
Updated•1 year ago
|
Comment 10•1 year ago
|
||
Good find. We're awarding a bounty for this as a sec-moderate. We're happy to revisit that decision if you can come up with a test case that allows to trigger this more reliably.
Comment 11•1 year ago
|
||
(In reply to John Schanck [:jschanck] from comment #9)
https://hg.mozilla.org/projects/nss/rev/dbd189b826b80eb0ff99d7769e16482624434682
This doesn't seem to be a fix for this issue.
| Assignee | ||
Comment 12•1 year ago
|
||
Thanks, updated my earlier comment. The correct patch is
https://hg.mozilla.org/projects/nss/rev/f9b22115dc97be76e388dc9d0dca946dde955e64
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Comment 13•1 year ago
|
||
Setting esr115 to Fixed for 115.13esr.
Bug 1905160 was uplifted to esr115
Updated•1 year ago
|
Updated•1 year ago
|
Comment 14•1 year ago
|
||
Updated•8 months ago
|
Description
•