Closed Bug 1977130 (CVE-2025-9181) Opened 1 year ago Closed 1 year ago

Free on address which was not realloc()-ed in js::GetNativeStackBaseImpl after realloc failure at pthread_getattr_np

Categories

(Core :: JavaScript Engine, defect, P3)

defect

Tracking

()

RESOLVED FIXED
143 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox-esr128 142+ fixed
firefox-esr140 142+ fixed
firefox141 --- wontfix
firefox142 + fixed
firefox143 + fixed

People

(Reporter: sourc7, Assigned: sfink)

References

(Blocks 1 open bug)

Details

(Keywords: csectype-uninitialized, reporter-external, sec-moderate, Whiteboard: [client-bounty-form][adv-main142+][adv-esr140.2+][adv-esr128.14+])

Attachments

(4 files)

Attached file log_minidump_00.txt

While fuzzing on Firefox Nightly 32-bit (Official Build) (BuildID=20250707093546) on Arch Linux (with original glibc), I found from minidump.txt it crash at SIGSEGV / SEGV_ACCERR during execution of js::newContext to free.

However, it still hard to reproduce the same, even after multiple tries.

After looking the code, the crash occurs at NativeStack.cpp in the function js::GetNativeStackBaseImpl:

void* js::GetNativeStackBaseImpl() {
 pthread_getattr_np(thread, &sattr);  // 1. realloc failure for &sattr inside pthread_getattr_np
...
...
 pthread_attr_destroy(&sattr); // 2. free on address which was not realloc()-ed on &sattr

To reliably reproduce this bug, we can use patched glibc to simulate the realloc failure inside pthread_getattr_np(thread, &sattr) to return ENOMEM, leaving the &sattr address not realloc()-ed, then on pthread_attr_destroy it free on &sattr address (which not realloc()-ed) which cause the crash.

Flags: sec-bounty?
Group: firefox-core-security → javascript-core-security
Component: Security → JavaScript Engine
Product: Firefox → Core

Steve, could this be from your stack-mmap change?

Flags: needinfo?(sphink)
Blocks: sm-security
Severity: -- → S3
Priority: -- → P3

Here are the steps for patching glibc to simulate pthread_attr_set_affinity to return ENOMEM, to apply the pthread_attr_setaffinity_simulate_enomem.patch and compile glibc 2.4.1, I'm following the Arch Linux PKGBUILD process.

Steps to reproduce

  1. wget https://ftp.gnu.org/gnu/glibc/glibc-2.41.tar.xz
  2. tar -xvf glibc-2.41.tar.xz -C /tmp
  3. cd /tmp/glibc-2.41
  4. (Download pthread_attr_setaffinity_simulate_enomem.patch to /tmp/glibc-2.41)
  5. patch nptl/pthread_attr_setaffinity.c < pthread_attr_setaffinity_simulate_enomem.patch
  6. mkdir build32
  7. cd build32
  8. export CC="gcc -m32 -mstackrealign" && export CXX="g++ -m32 -mstackrealign"
  9. cat <<EOF > configparms
    slibdir=/usr/lib32
    rtlddir=/usr/lib32
    sbindir=/usr/bin
    rootsbindir=/usr/bin
    EOF
  10. ../configure --prefix=/usr --enable-bind-now --with-headers=/usr/include --enable-kernel=4.4 --enable-multi-arch --enable-systemtap --disable-werror --disable-profile --disable-nscd --host=i686-pc-linux-gnu --libdir=/usr/lib32 --libexecdir=/usr/lib32
  11. sudo make -j32 DESTDIR=/var/target-chroot install

(Change /var/target-chroot/ directory to Arch Linux root installation e.g. Virtual Machine .qcow2/.img disk root or Arch Linux pacstrap chroot installation folder)

I recommend to running this directly on Arch Linux virtual machine (e.g. QEMU for simplicity and avoid host OS breakages), so we can install it directly, by changing the DESTDIR=/var/target-chroot to DESTDIR=/

After patched glibc was installed on the system, then visit set-interval-new-worker.forpatch.html on Firefox 32-bit, it will crash at js::NewContext to free

This similar to my bug 1895081, which realloc failure inside pthread_getattr_np, that cause free on address (which not realloc()-ed) by pthread_attr_destroy

The fix would be add MOZ_RELEASE_ASSERT to check the return value of pthread_getattr_np. If the function fails (e.g., returns ENOMEM due to a memory allocation failure), then it will trigger the MOZ_RELEASE_ASSERT assertion.

See Also: → CVE-2024-6603

Notes to self: pthread_getattr_np calls __pthread_attr_copy calls __pthread_attr_setaffinity_np which does the realloc. But only if the extension field is set and has affinity mask info in extension->cpusetsize.

...but wait, what is setting affinity? I see some pthread_setaffinity_np calls, but they're in dav1d and glsl, neither of which is on a JS-running thread. Perhaps it's different in glibc 2.41? I have glibc 2.35.

Oh... yes, 2.41 is wildly different. It calls __pthread_attr_setaffnity_np unconditionally.

But you're right, given your diagnosis it seems like the fix is pretty straightforward. Now to see who's ok with forced crashes in their code...

Flags: needinfo?(sphink)
Attached file (secure)
Assignee: nobody → sphink
Status: NEW → ASSIGNED
Group: javascript-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 143 Branch
Flags: sec-bounty? → sec-bounty+

Please nominate this for Beta/ESR140/ESR128 approval when you get a chance.

As a reminder we are in the last week of beta for uplifts!

Comment on attachment 9502818 [details]
(secure)

Beta/Release Uplift Approval Request

  • User impact if declined/Reason for urgency: Honestly, it's hard for me to see a path to user impact. It seems very hard to trigger and about as hard to exploit. It's probably more useful as bulletproofing to aid fuzzers. That said, if I were to try to make use of this, I'd play around with Web Workers since they do the relevant actions while the main thread is sitting around and potentially making use of them.
  • Is this code covered by automated tests?: No
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): The change itself is very safe. It forces a crash when the problematic operation fails, and in normal practice, it should never fail (unless your system is severely messed up already).
  • String changes made/needed: none
  • Is Android affected?: Yes
Flags: needinfo?(sphink)
Attachment #9502818 - Flags: approval-mozilla-beta?

Comment on attachment 9502818 [details]
(secure)

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration: Mainly to reduce fuzzing noise (the type of fuzzing that caught this -- fault injection -- is generally useful). It is also just barely possible that this might be exploitable via Web Workers (or some other worker type).
  • User impact if declined: see above
  • Fix Landed on Version: 143
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): It forces a safe crash in the very unlikely event that this fails during regular usage.
Attachment #9502818 - Flags: approval-mozilla-esr140?
Attachment #9502818 - Flags: approval-mozilla-esr128?

Comment on attachment 9502818 [details]
(secure)

Approved for 142.0b8

Attachment #9502818 - Flags: approval-mozilla-beta? → approval-mozilla-beta+

Comment on attachment 9502818 [details]
(secure)

Approved for 140.2esr and 128.14esr.

Attachment #9502818 - Flags: approval-mozilla-esr140?
Attachment #9502818 - Flags: approval-mozilla-esr140+
Attachment #9502818 - Flags: approval-mozilla-esr128?
Attachment #9502818 - Flags: approval-mozilla-esr128+
Whiteboard: [client-bounty-form] → [client-bounty-form][adv-main142+][adv-esr140.2+][adv-esr128.14+]
QA Whiteboard: [sec] [uplift] [qa-triage-done-c143/b142]
Flags: qe-verify-
Alias: CVE-2025-9181
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: