Closed Bug 2013586 Opened 9 months ago Closed 9 months ago

AddressSanitizer: heap-use-after-free [@ get] with READ of size 8 through [@ js::WasmModuleObject::customSections]

Categories

(Core :: JavaScript: WebAssembly, defect, P1)

x86_64
Linux
defect

Tracking

()

RESOLVED FIXED
149 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox-esr140 --- wontfix
firefox147 --- wontfix
firefox148 + fixed
firefox149 + fixed

People

(Reporter: decoder, Assigned: jpages)

References

Details

(7 keywords, Whiteboard: [fixed in 2013584][bugmon:update,bisected,confirmed][adv-main148-])

Attachments

(2 files, 1 obsolete file)

The following testcase crashes on mozilla-central revision 20260130-20b1a1e6c530 (fuzzing-asan-opt build, run with --fuzzing-safe --no-threads):

See attachment.

Backtrace:

=================================================================
==1738776==ERROR: AddressSanitizer: heap-use-after-free on address 0x777bd47ea410 at pc 0x63f7617cd6cb bp 0x7ffe875cd0d0 sp 0x7ffe875cd0c8
READ of size 8 at 0x777bd47ea410 thread T0
    #0 0x63f7617cd6ca in get /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:314:27
    #1 0x63f7617cd6ca in operator* /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:387:13
    #2 0x63f7617cd6ca in moduleMeta /js/src/wasm/WasmModule.h:157:53
    #3 0x63f7617cd6ca in js::WasmModuleObject::customSections(JSContext*, unsigned int, JS::Value*) /js/src/wasm/WasmJS.cpp:1499:42
    #4 0x63f760f31b6d in CallJSNative /js/src/vm/Interpreter.cpp:490:13
    #5 0x63f760f31b6d in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /js/src/vm/Interpreter.cpp:586:12
    #6 0x63f760f4fc7c in InternalCall /js/src/vm/Interpreter.cpp:653:10
    #7 0x63f760f4fc7c in CallFromStack /js/src/vm/Interpreter.cpp:658:10
    #8 0x63f760f4fc7c in js::Interpret(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:3272:16
    #9 0x63f760f30986 in MaybeEnterInterpreterTrampoline /js/src/vm/Interpreter.cpp:384:10
    #10 0x63f760f30986 in js::RunScript(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:460:13
    #11 0x63f760f35b4c in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, js::AbstractFramePtr, JS::MutableHandle<JS::Value>) /js/src/vm/Interpreter.cpp:850:10
    #12 0x63f7612e6ba1 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) /js/src/vm/CompilationAndEvaluation.cpp:572:10
    #13 0x63f75f2caa55 in RunFile(JSContext*, char const*, _IO_FILE*, CompileUtf8, bool, bool) /js/src/shell/js.cpp:1387:10
    #14 0x63f75f2c9e31 in Process(JSContext*, char const*, bool, FileKind) /js/src/shell/js.cpp
    #15 0x63f75f24434a in ProcessArgs /js/src/shell/js.cpp:12110:10
    #16 0x63f75f24434a in Shell(JSContext*, js::cli::OptionParser*) /js/src/shell/js.cpp:12363:12
    #17 0x63f75f22cee7 in main /js/src/shell/js.cpp:12769:12
    #18 0x7b1bd542a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #19 0x7b1bd542a28a in __libc_start_main csu/../csu/libc-start.c:360:3
    #20 0x63f75f1341f8 in _start (/home/decoder/Mozilla/Anthropic/.builds/asan/js/dist/bin/js+0x2d201f8) (BuildId: b9b60630d05b45547bce8211e76c23e091144ce3)

0x777bd47ea410 is located 16 bytes inside of 56-byte region [0x777bd47ea400,0x777bd47ea438)
freed by thread T0 here:
    #0 0x63f75f1d52f6 in free /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:51:3
    #1 0x63f75fef3d51 in doFinalize /builds/worker/workspace/obj-build/dist/include/js/Class.h:663:5
    #2 0x63f75fef3d51 in finalize /js/src/vm/JSObject-inl.h:90:10
    #3 0x63f75fef3d51 in unsigned long js::gc::Arena::finalize<JSObject, (js::gc::FinalizeKind)2>(JS::GCContext*, js::gc::AllocKind, unsigned long) /js/src/gc/Sweeping.cpp:162:12
    #4 0x63f75fefca0a in bool FinalizeTypedArenas<JSObject, (js::gc::FinalizeKind)1, (js::gc::ReleaseEmpty)0>(JS::GCContext*, js::gc::ArenaList&, js::gc::SortedArenaList&, js::gc::AllocKind, JS::SliceBudget&) /js/src/gc/Sweeping.cpp:220:16
    #5 0x63f75feaf454 in js::gc::ArenaLists::foregroundFinalize(JS::GCContext*, js::gc::AllocKind, JS::SliceBudget&, js::gc::SortedArenaList&) /js/src/gc/Sweeping.cpp:1923:8
    #6 0x63f75feb5b78 in js::gc::GCRuntime::finalizeAllocKind(JS::GCContext*, JS::SliceBudget&) /js/src/gc/Sweeping.cpp:2138:19
    #7 0x63f75fee6c96 in sweepaction::SweepActionForEach<ContainerIter<mozilla::EnumSet<js::gc::AllocKind, unsigned long>>, mozilla::EnumSet<js::gc::AllocKind, unsigned long>>::run(js::gc::SweepAction::Args&) /js/src/gc/Sweeping.cpp:2383:19
    #8 0x63f75fefde37 in sweepaction::SweepActionSequence::run(js::gc::SweepAction::Args&) /js/src/gc/Sweeping.cpp:2348:23
    #9 0x63f75fee66e7 in sweepaction::SweepActionForEach<js::gc::SweepGroupZonesIter, JSRuntime*>::run(js::gc::SweepAction::Args&) /js/src/gc/Sweeping.cpp:2383:19
    #10 0x63f75fefde37 in sweepaction::SweepActionSequence::run(js::gc::SweepAction::Args&) /js/src/gc/Sweeping.cpp:2348:23
    #11 0x63f75fee5f97 in sweepaction::SweepActionForEach<js::gc::SweepGroupsIter, JSRuntime*>::run(js::gc::SweepAction::Args&) /js/src/gc/Sweeping.cpp:2383:19
    #12 0x63f75feb9d6e in js::gc::GCRuntime::performSweepActions(JS::SliceBudget&) /js/src/gc/Sweeping.cpp:2567:53
    #13 0x63f75fdf6f93 in js::gc::GCRuntime::incrementalSlice(JS::SliceBudget&, JS::GCReason, bool) /js/src/gc/GC.cpp:4081:11
    #14 0x63f75fdfc0a5 in js::gc::GCRuntime::gcCycle(bool, JS::SliceBudget const&, JS::GCReason) /js/src/gc/GC.cpp:4634:3
    #15 0x63f75fdfdb3d in js::gc::GCRuntime::collect(bool, JS::SliceBudget const&, JS::GCReason) /js/src/gc/GC.cpp:4823:9
    #16 0x63f75fe0651e in gc /js/src/gc/GC.cpp:4903:3
    #17 0x63f75fe0651e in JS::NonIncrementalGC(JSContext*, JS::GCOptions, JS::GCReason) /js/src/gc/GCAPI.cpp:300:21
    #18 0x63f75f6c4a50 in GC(JSContext*, unsigned int, JS::Value*) /js/src/builtin/TestingFunctions.cpp:789:3
    #19 0x63f760f31b6d in CallJSNative /js/src/vm/Interpreter.cpp:490:13
    #20 0x63f760f31b6d in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /js/src/vm/Interpreter.cpp:586:12
    #21 0x63f760f4fc7c in InternalCall /js/src/vm/Interpreter.cpp:653:10
    #22 0x63f760f4fc7c in CallFromStack /js/src/vm/Interpreter.cpp:658:10
    #23 0x63f760f4fc7c in js::Interpret(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:3272:16
    #24 0x63f760f30986 in MaybeEnterInterpreterTrampoline /js/src/vm/Interpreter.cpp:384:10
    #25 0x63f760f30986 in js::RunScript(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:460:13
    #26 0x63f760f31ce7 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /js/src/vm/Interpreter.cpp:618:13
    #27 0x63f760f337f4 in InternalCall /js/src/vm/Interpreter.cpp:653:10
    #28 0x63f760f337f4 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /js/src/vm/Interpreter.cpp:685:8
    #29 0x63f75f53140b in js::Call(JSContext*, JS::Handle<JS::Value>, JSObject*, JS::MutableHandle<JS::Value>) /js/src/vm/Interpreter.h:113:10
    #30 0x63f76142c1ec in JS::OrdinaryToPrimitive(JSContext*, JS::Handle<JSObject*>, JSType, JS::MutableHandle<JS::Value>) /js/src/vm/JSObject.cpp:2383:14
    #31 0x63f76142dba0 in js::ToPrimitiveSlow(JSContext*, JSType, JS::MutableHandle<JS::Value>) /js/src/vm/JSObject.cpp:2494:10
    #32 0x63f76116d97f in ToPrimitive /js/src/vm/JSObject.h:802:10
    #33 0x63f76116d97f in JSString* js::ToStringSlow<(js::AllowGC)1>(JSContext*, js::MaybeRooted<JS::Value, (js::AllowGC)1>::HandleType) /js/src/vm/StringType.cpp:3230:10
    #34 0x63f7617ccab4 in ToString /builds/worker/workspace/obj-build/dist/include/js/Conversions.h:260:10
    #35 0x63f7617ccab4 in js::WasmModuleObject::customSections(JSContext*, unsigned int, JS::Value*) /js/src/wasm/WasmJS.cpp:1478:26
    #36 0x63f760f31b6d in CallJSNative /js/src/vm/Interpreter.cpp:490:13
    #37 0x63f760f31b6d in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /js/src/vm/Interpreter.cpp:586:12
    #38 0x63f760f4fc7c in InternalCall /js/src/vm/Interpreter.cpp:653:10
    #39 0x63f760f4fc7c in CallFromStack /js/src/vm/Interpreter.cpp:658:10
    #40 0x63f760f4fc7c in js::Interpret(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:3272:16
    #41 0x63f760f30986 in MaybeEnterInterpreterTrampoline /js/src/vm/Interpreter.cpp:384:10
    #42 0x63f760f30986 in js::RunScript(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:460:13
    #43 0x63f760f35b4c in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, js::AbstractFramePtr, JS::MutableHandle<JS::Value>) /js/src/vm/Interpreter.cpp:850:10

previously allocated by thread T0 here:
    #0 0x63f75f1d5594 in malloc /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:67:3
    #1 0x63f76176ff87 in js_new<js::wasm::Module, js::wasm::ModuleMetadata &, js::wasm::Code &> /builds/worker/workspace/obj-build/dist/include/js/Utility.h:546:1
    #2 0x63f76176ff87 in js::wasm::ModuleGenerator::finishModule(js::wasm::BytecodeBufferOrSource const&, js::wasm::ModuleMetadata&, JS::OptimizedEncodingListener*) /js/src/wasm/WasmGenerator.cpp:1406:26
    #3 0x63f76170113f in js::wasm::CompileBuffer(js::wasm::CompileArgs const&, js::wasm::BytecodeBufferOrSource const&, std::unique_ptr<char [], JS::FreePolicy>*, mozilla::Vector<std::unique_ptr<char [], JS::FreePolicy>, 0ul, js::SystemAllocPolicy>*, JS::OptimizedEncodingListener*) /js/src/wasm/WasmCompile.cpp:1029:13
    #4 0x63f7617d3525 in js::WasmModuleObject::construct(JSContext*, unsigned int, JS::Value*) /js/src/wasm/WasmJS.cpp:1687:14
    #5 0x63f760f34368 in CallJSNative /js/src/vm/Interpreter.cpp:490:13
    #6 0x63f760f34368 in CallJSNativeConstructor /js/src/vm/Interpreter.cpp:508:8
    #7 0x63f760f34368 in InternalConstruct(JSContext*, js::AnyConstructArgs const&, js::CallReason) /js/src/vm/Interpreter.cpp:714:14
    #8 0x63f760129f04 in js::jit::DoCallFallback(JSContext*, js::jit::BaselineFrame*, js::jit::ICFallbackStub*, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) /js/src/jit/BaselineIC.cpp:1677:10
    #9 0x771b520118d3  ([anon:js-executable-memory]+0x28d3)
    #10 0x771b52017658  ([anon:js-executable-memory]+0x8658)
    #11 0x771b5203043a  ([anon:js-executable-memory]+0x143a)
    #12 0x771b5200f3dc  ([anon:js-executable-memory]+0x3dc)
    #13 0x63f760751fd3 in EnterBaseline /js/src/jit/BaselineJIT.cpp:147:5
    #14 0x63f760751fd3 in js::jit::EnterBaselineInterpreterAtBranch(JSContext*, js::InterpreterFrame*, unsigned char*) /js/src/jit/BaselineJIT.cpp:202:26
    #15 0x63f760f56ba9 in js::Interpret(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:2032:17
    #16 0x63f760f30986 in MaybeEnterInterpreterTrampoline /js/src/vm/Interpreter.cpp:384:10
    #17 0x63f760f30986 in js::RunScript(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:460:13
    #18 0x63f760f35b4c in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, js::AbstractFramePtr, JS::MutableHandle<JS::Value>) /js/src/vm/Interpreter.cpp:850:10
    #19 0x63f7612e6397 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) /js/src/vm/CompilationAndEvaluation.cpp:565:10
    #20 0x63f75f26ff70 in EvaluateInner(JSContext*, JS::Handle<JSString*>, JS::MutableHandle<JSObject*>, JS::Handle<JSObject*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) /js/src/shell/js.cpp:3170:32
    #21 0x63f75f271f89 in Evaluate(JSContext*, unsigned int, JS::Value*) /js/src/shell/js.cpp:2907:10
    #22 0x63f760f31b6d in CallJSNative /js/src/vm/Interpreter.cpp:490:13
    #23 0x63f760f31b6d in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /js/src/vm/Interpreter.cpp:586:12
    #24 0x63f760f337f4 in InternalCall /js/src/vm/Interpreter.cpp:653:10
    #25 0x63f760f337f4 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /js/src/vm/Interpreter.cpp:685:8
    #26 0x63f760f0844f in js::ForwardingProxyHandler::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /js/src/proxy/Wrapper.cpp:166:10
    #27 0x63f760ee247b in js::CrossCompartmentWrapper::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /js/src/proxy/CrossCompartmentWrapper.cpp:230:19
    #28 0x63f760ef13c1 in js::Proxy::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) /js/src/proxy/Proxy.cpp:703:19
    #29 0x63f760f321b5 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /js/src/vm/Interpreter.cpp:566:14
    #30 0x63f760f4fc7c in InternalCall /js/src/vm/Interpreter.cpp:653:10
    #31 0x63f760f4fc7c in CallFromStack /js/src/vm/Interpreter.cpp:658:10
    #32 0x63f760f4fc7c in js::Interpret(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:3272:16
    #33 0x63f760f30986 in MaybeEnterInterpreterTrampoline /js/src/vm/Interpreter.cpp:384:10
    #34 0x63f760f30986 in js::RunScript(JSContext*, js::RunState&) /js/src/vm/Interpreter.cpp:460:13
    #35 0x63f760f35b4c in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, js::AbstractFramePtr, JS::MutableHandle<JS::Value>) /js/src/vm/Interpreter.cpp:850:10
    #36 0x63f7612e6ba1 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) /js/src/vm/CompilationAndEvaluation.cpp:572:10
    #37 0x63f75f2caa55 in RunFile(JSContext*, char const*, _IO_FILE*, CompileUtf8, bool, bool) /js/src/shell/js.cpp:1387:10
    #38 0x63f75f2c9e31 in Process(JSContext*, char const*, bool, FileKind) /js/src/shell/js.cpp
    #39 0x63f75f24434a in ProcessArgs /js/src/shell/js.cpp:12110:10
    #40 0x63f75f24434a in Shell(JSContext*, js::cli::OptionParser*) /js/src/shell/js.cpp:12363:12

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:314:27 in get
Shadow bytes around the buggy address:
  0x777bd47ea180: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x777bd47ea200: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x777bd47ea280: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
  0x777bd47ea300: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x777bd47ea380: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
=>0x777bd47ea400: fd fd[fd]fd fd fd fd fa fa fa fa fa fd fd fd fd
  0x777bd47ea480: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x777bd47ea500: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x777bd47ea580: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
  0x777bd47ea600: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
  0x777bd47ea680: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==1738776==ABORTING

This bug is part of a series of bugs reported by Anthropic, thank you for your contributions to Firefox!

Attached file Testcase —
Assignee: nobody → jpages

This one seems to be related to 2013584, similar use-after-free of ModuleMetadata.

Verified bug as reproducible on mozilla-central 20260130211306-fda5656fd125.
Unable to bisect testcase (Testcase reproduces on start build!):

Start: d87cd04072b041911d218cec1baf59de7f2a5ede (20251103213617)
End: 20b1a1e6c530f3506d5378bf5f4da504b6f03661 (20260130092147)
BuildFlags: BuildFlags(asan=True, tsan=False, debug=False, fuzzing=True, coverage=False, valgrind=False, no_opt=False, fuzzilli=False, nyx=False, searchfox=False, afl=False)

Whiteboard: [bugmon:update,bisect] → [bugmon:update,bisected,confirmed]
See Also: → CVE-2026-2804

As with bug 2013584, while it is true that content can trigger CCW nuking via navigation, this is only for chrome-content references, not content-content references (which we can't nuke because it would be web-visible). So, in this case again it would only come up if chrome JS is running a WebAssembly module from content which is probably bad news anyways. This seems sec-moderate at worst.

Similar to Bug 2013584, this seems to be a missing GC root around the creation of a WasmModuleObject in WasmJS.cpp.

In this testcase, the first module will get collected and we end up with some use-after-free in the second one.

Attached file (secure) (obsolete) —
Severity: -- → S3
Priority: -- → P1

Is ESR115 also affected?

Flags: needinfo?(jpages)
Flags: needinfo?(jpages)

This bug is very similar to Bug 2013584.

It is actually the same issue which is duplicated at 3/4 points in the same file. I will close this one and merge the two patches.

Status: NEW → RESOLVED
Closed: 9 months ago
Duplicate of bug: CVE-2026-2804
Resolution: --- → DUPLICATE
Attachment #9541963 - Attachment is obsolete: true

No valid actions for resolution (DUPLICATE).
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.

Keywords: bugmon
Whiteboard: [bugmon:update,bisected,confirmed] → [bugmon:update,bisected,confirmed][adv-main148-]

(In reply to Julien Pages [:jpages] from comment #9)

This bug is very similar to Bug 2013584

It is actually the same issue which is duplicated at 3/4 points in the same file. I will close this one and merge the two patches.

Merging the patches is fine, but for security bug statistics purposes we should make this "depend on" the other bug rather than be a duplicate. There's a reasonable chance you would have missed the other occurrences without this bug pointing another one out.

Depends on: CVE-2026-2804
No longer duplicate of bug: CVE-2026-2804
Resolution: DUPLICATE → FIXED
Whiteboard: [bugmon:update,bisected,confirmed][adv-main148-] → [fixed in 2013584][bugmon:update,bisected,confirmed][adv-main148-]
QA Whiteboard: [sec] [qa-triage-done-c150/b149]
Target Milestone: --- → 149 Branch
Group: core-security-release
Keywords: keep-hidden
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: