Closed Bug 1900523 (CVE-2024-6613) Opened 11 months ago Closed 11 months ago

Assertion failure: framePtr->hasCachedSavedFrame() || hasGoodExcuse, at vm/SavedStacks.cpp:1483

Categories

(Core :: JavaScript Engine, defect, P3)

defect

Tracking

()

RESOLVED FIXED
128 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox127 --- wontfix
firefox128 --- fixed

People

(Reporter: sm-bugs, Assigned: jandem)

References

(Blocks 2 open bugs)

Details

(Keywords: csectype-dos, reporter-external, sec-low, Whiteboard: [adv-main128+])

Attachments

(4 files)

Steps to reproduce:

Checkout commit d9496bfef09039b2642da45585ca821c36917c6d and invoke the js shell as follows:

./js-spidermonkey-shell --fast-warmup --fuzzing-safe frameptr_has_cached_saved_frame.js

Actual results:

Assertion failure: framePtr->hasCachedSavedFrame() || hasGoodExcuse, at vm/SavedStacks.cpp:1483
Group: firefox-core-security → core-security
Component: Untriaged → JavaScript Engine
Product: Firefox → Core

More reduced test below. This has all the good stuff working together: Wasm <=> JS calls, promises, saved stacks, recover instruction throwing an exception during bailout. Still looking at it.

function f17(a18, a19) {
  const v20 = a18 >> a18;
  v20 <= v20 ? v20 : v20;
  a19 ^ a19;
}
function f4() {
  Promise.allSettled();
  do {
    f17(10n, -1n);
    try {
        f17(-2147483648n);
    } catch {
    }
  } while (!inIon());
}
const binary = wasmTextToBinary(`
  (module
    (import "m" "f" (func $f))
    (func (export "test")
      (call $f)
    )
  )`);
const mod = new WebAssembly.Module(binary);
const inst = new WebAssembly.Instance(mod, {"m": {"f": f4}});
for (let i = 0; i < 5; i++) {
  inst.exports.test();
}

Tthe JSJitFrameIter constructor is always using the bailout data here but it should only do this for Exit frames and not for JSJitToWasm transition frames. The iterator could actually iloop in this case because iteration would start over again at the bailout frame. Oops.

It's certainly sketchy but I have to see what opt builds are doing to determine if this is security sensitive.

Assignee: nobody → jdemooij
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Group: core-security → javascript-core-security
Keywords: sec-low
Blocks: sm-security
Severity: -- → S3
Priority: -- → P3
Pushed by jdemooij@mozilla.com: http://hg.mozilla.org/integration/autoland/rev/9fa4d3a5229b Don't use bailout data for JSJitToWasm frames. r=iain
Group: javascript-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 11 months ago
Resolution: --- → FIXED
Target Milestone: --- → 128 Branch
Flags: in-testsuite+
QA Whiteboard: [post-critsmash-triage]
Flags: qe-verify-
Flags: sec-bounty?

This can still be triggered (on 97eeb1c55a5c73bd3938d4899685321a7967333b) using the following flags and the attached test case. However, it only crashes about 1 of 50 executions on my machine.

js --fuzzing-safe  --fast-warmup --ion-check-range-analysis --ion-extra-checks  --disable-oom-functions --enable-new-set-methods --small-function-length=1024 --inlining-entry-threshold=8 --gc-zeal=21,210 --ion-scalar-replacement=on --ion-pruning=on --ion-range-analysis=on --ion-inlining=on --ion-gvn=on --ion-osr=on --ion-edgecase-analysis=on --spectre-mitigations=on --ion-limit-script-size=on --ion-offthread-compile=on --ion-optimize-gcbarriers=on --ion-iterator-indices=on --nursery-size=2 --nursery-strings=on --nursery-bigints=on --enable-ic-frame-pointers --disable-bailout-loop-check --ion-optimize-shapeguards=on --ion-licm=on --ion-instruction-reordering=on --cache-ir-stubs=on --no-sse42 --monomorphic-inlining=default --ion-load-keys=off --ion-sink=off <testcase>
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Attached file bug.js

(In reply to Nils Bars from comment #6)

This can still be triggered (on 97eeb1c55a5c73bd3938d4899685321a7967333b) using the following flags and the attached test case. However, it only crashes about 1 of 50 executions on my machine.

Please file a new bug :) It's likely a different issue. This is a pretty generic assertion that has caught multiple different bugs over the years.

Status: REOPENED → RESOLVED
Closed: 11 months ago11 months ago
Resolution: --- → FIXED

(In reply to Jan de Mooij [:jandem] from comment #2)

It's certainly sketchy but I have to see what opt builds are doing to determine if this is security sensitive.

You never fully replied what your assessment was. Can you add some extra details for the purpose of making a bug bounty decisions?
We did see you marked it as sec-low, but would like to hear a bit more if possible

Flags: needinfo?(jdemooij)

(In reply to Frederik Braun [:freddy] from comment #9)

You never fully replied what your assessment was. Can you add some extra details for the purpose of making a bug bounty decisions?
We did see you marked it as sec-low, but would like to hear a bit more if possible

The frame iterator could get stuck in an infinite loop because it would restart at the first frame after we saw Wasm frames, instead of moving on to the next JS frame. In this case we use the frame iterator because we're creating a stack trace for an exception, and for that we cap the number of frames we iterate to MAX_REPORTED_STACK_DEPTH (=128). I verified a non-debug build would just produce an incorrect stack trace (with about 128 frames).

Flags: needinfo?(jdemooij)

Thanks! Looks like this doesn't meet the bar for a bug bounty then.

Flags: sec-bounty? → sec-bounty-
Blocks: 1903968
Keywords: csectype-dos
See Also: → CVE-2024-6614
Whiteboard: [adv-main128-]
Whiteboard: [adv-main128-] → [adv-main128+]
Attached file advisory.txt
Alias: CVE-2024-6613
Flags: sec-bounty-hof+
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: