Closed Bug 2029070 (CVE-2026-8946) Opened 6 months ago Closed 4 months ago

Unbounded attacker-controlled alloca (stack-clash) in [@ vorbis_book_init_decode]

Categories

(Core :: Audio/Video: Web Codecs, defect)

defect

Tracking

()

RESOLVED FIXED
152 Branch
Tracking Status
firefox-esr115 151+ fixed
firefox-esr140 151+ fixed
firefox150 --- wontfix
firefox151 + fixed
firefox152 + fixed

People

(Reporter: bugmon, Assigned: chunmin)

References

Details

(5 keywords, Whiteboard: [prefs-checked][pp3][adv-main151+][adv-esr140.11+][adv-esr115.36+])

Crash Data

Attachments

(12 files, 4 obsolete files)

1.94 KB, text/html
Details
1.80 KB, patch
Details | Diff | Splinter Review
13.17 KB, text/plain
Details
878 bytes, patch
Details | Diff | Splinter Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
28.62 KB, text/plain
Details
22.13 KB, application/zip
Details
9 bytes, text/plain
Details
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review

Unbounded attacker-controlled alloca (stack-clash) in [@ vorbis_book_init_decode]

libvorbis's vorbis_book_init_decode() calls alloca(sizeof(*codep)*n) and alloca(n*sizeof(*sortindex)) where n is the number of used codebook entries. The Vorbis setup header encodes the entry count as a raw 24-bit field (vorbis_codebook.c:158), and the spec's "ordered" length encoding lets a ~10-byte bitstream declare millions of used entries. With n = 2^23, the first alloca requests 64 MiB, moving %rsp far past the thread's guard page in a single step; the subsequent loop codep[i] = codes+i then writes 8 M heap-pointer values starting 64 MiB below the legitimate stack and walking upward.

This is a classic stack-clash (CWE-789) primitive: the attacker chooses n (and hence the displacement, any multiple of 8 up to ~128 MiB) precisely, so the write window can be aimed at adjacent thread stacks or heap arenas that lie below the decoder thread's stack. In the provided ASAN run the target region happened to be unmapped, but in a groomed address space (or non-ASAN release builds without -fstack-clash-protection on this TU) the writes land in live memory.

The path is reachable directly from web content with no user interaction: new AudioDecoder().configure({codec:"vorbis", description:<~126 bytes>}) ships the malicious headers over PRemoteDecoder to the Utility audio-decoding process, where FFmpeg's oggvorbis_decode_init calls vorbis_synthesis_init → _vds_shared_init → vorbis_book_init_decode. The same code is also reached in the content process via OggDemuxer/VorbisState::Init() when playing an .ogg file in <audio>.

Build Info

Affected Code

File: media/libvorbis/lib/vorbis_sharedbook.c, line 334-371

  for(i=0;i<s->entries;i++)
    if(s->lengthlist[i]>0)
      n++;
  ...
  if(n>0){
    ...
    ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
    ogg_uint32_t **codep=alloca(sizeof(*codep)*n);   // n up to ~2^24, no bound check

    if(codes==NULL)goto err_out;

    for(i=0;i<n;i++){
      codes[i]=bitreverse(codes[i]);
      codep[i]=codes+i;                              // writes n pointers below guard page
    }

    qsort(codep,n,sizeof(*codep),sort32a);

    sortindex=alloca(n*sizeof(*sortindex));          // second unbounded alloca
    ...
    for(i=0;i<n;i++){
      int position=codep[i]-codes;
      sortindex[position]=i;
    }

File: media/libvorbis/lib/vorbis_codebook.c, line 157-216

  s->dim=oggpack_read(opb,16);
  s->entries=oggpack_read(opb,24);          // attacker-controlled, up to 16,777,215
  if(s->entries==-1)goto _eofout;

  if(ov_ilog(s->dim)+ov_ilog(s->entries)>24)goto _eofout;  // dim=0 ⇒ no limit on entries
  ...
  case 1:
    /* ordered */
    {
      long length=oggpack_read(opb,5)+1;
      ...
      for(i=0;i<s->entries;){
        long num=oggpack_read(opb,ov_ilog(s->entries-i));  // single read fills all entries
        ...
        for(j=0;j<num;j++,i++)
          s->lengthlist[i]=length;          // every entry marked used ⇒ n == s->entries
        length++;
      }
    }

s->entries is a raw 24-bit field from the setup header. The ordered-length branch lets one num value mark all entries as used in ~10 bytes of bitstream. vorbis_book_init_decode then performs two alloca() calls sized n*8 and n*4 with no upper bound, followed by linear writes across the entire allocated span.

Exploit Chain

  1. Attacker page constructs a Vorbis codec description (id + comment + setup headers, ~126 bytes) whose second codebook uses ordered encoding with dim=0 and entries=2^23 (or any chosen n ≤ ~2^24).
  2. Page calls AudioDecoder.configure({codec:'vorbis', description}); the config is sent over PRemoteDecoder::Init to the Utility audio-decoding process.
  3. Utility process: FFmpegAudioDecoder::Init → avcodec_open2 → oggvorbis_decode_init parses the headers (vorbis_synthesis_headerin) and calls vorbis_synthesis_init.
  4. _vds_shared_init → vorbis_book_init_decode executes alloca(8*n); %rsp jumps 8*n bytes (e.g. 64 MiB) past the guard page.
  5. The loop for(i=0;i<n;i++) codep[i]=codes+i; writes 8·n bytes of heap-pointer values starting at the displaced %rsp and walking upward, overwriting whatever mapping (adjacent thread stack, heap arena) the attacker has groomed into that range.
  6. Corrupted memory in the victim region is later used, yielding control-flow hijack or further memory corruption in the Utility (or content, via the <audio>/OggDemuxer path) process.

IPC Path

  • PRemoteDecoder Init
    • Protocol: PRemoteDecoder
    • Parent process: Utility (Generic audio)
    • Child process: Content
    • Message flow: Content -> Utility: Construct(RemoteDecoderInfoIPDL{AudioInfo.mCodecSpecificConfig=<malicious vorbis headers>}) then Init()

Steps to Reproduce

  1. Build Firefox with AddressSanitizer (no extra prefs or patches required).
  2. Serve and load the attached test.html in the ASAN build.
  3. Observe the Utility audio-decoding process crash with ASAN stack-overflow in vorbis_book_init_decode (media/libvorbis/lib/vorbis_sharedbook.c:355), with the faulting address ~64 MiB below the frame pointer.

Security Impact

  • Severity: High
  • Attacker capability: Web content can move the decoder thread's stack pointer by an attacker-chosen multiple of 8 bytes (up to ~128 MiB) past the guard page and then perform a contiguous 8·n-byte write of predictable heap-pointer values into that region. With address-space grooming this yields out-of-stack memory corruption (stack-clash) in the Utility audio-decoding process; the same primitive is also reachable in the content process via OggDemuxer when playing a crafted .ogg file.
  • Preconditions: None beyond visiting a malicious page (WebCodecs AudioDecoder is enabled by default). No user interaction, prefs, or compromised renderer required.

ASAN Report

==313952==ERROR: AddressSanitizer: stack-overflow on address 0x79f9c9aae858 (pc 0x79fa0f71c17d bp 0x79f9cdaae990 sp 0x79f9c9aae860 T6)
    #0 0x79fa0f71c17d in vorbis_book_init_decode /firefox/media/libvorbis/lib/vorbis_sharedbook.c:355:26
    #1 0x79fa0f6eced9 in _vds_shared_init /firefox/media/libvorbis/lib/vorbis_block.c:240:12
    #2 0x79fa0f6f5ccf in vorbis_synthesis_init /firefox/media/libvorbis/lib/vorbis_block.c:709:6
    #3 0x79f9cf38c4ed in oggvorbis_decode_init /firefox/media/ffvpx/libavcodec/libvorbisdec.c:123:5
    #4 0x79f9cf1d815d in avcodec_open2 /firefox/media/ffvpx/libavcodec/avcodec.c:336:19
    #5 0x79f9f157e46c in mozilla::FFmpegDataDecoder<46465650>::InitDecoder(AVCodec*, AVDictionary**) /firefox/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp:238:7
    #6 0x79f9f1567be3 in mozilla::FFmpegDataDecoder<46465650>::InitSWDecoder(AVDictionary**) /firefox/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp:107:10
    #7 0x79f9f1567420 in mozilla::FFmpegAudioDecoder<46465650>::Init() /firefox/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp:141:10
    #8 0x79f9f1487560 in mozilla::MediaDataDecoderProxy::Init()::$_0::operator()() const /firefox/dom/media/platforms/wrappers/MediaDataDecoderProxy.cpp:16:33
    #9 0x79f9f1487560 in mozilla::detail::ProxyFunctionRunnable<mozilla::MediaDataDecoderProxy::Init()::$_0, mozilla::MozPromise<mozilla::TrackInfo::TrackType, mozilla::MediaResult, true>>::Run() /firefox/obj-firefox-asan/dist/include/mozilla/MozPromise.h:1836:29
    #10 0x79f9e7df82b7 in mozilla::TaskQueue::Runner::Run() /firefox/xpcom/threads/TaskQueue.cpp:309:20
    #11 0x79f9e7e1fa37 in nsThreadPool::Run() /firefox/xpcom/threads/nsThreadPool.cpp:444:14
    #12 0x79f9e7e12c2a in nsThread::ProcessNextEvent(bool, bool*) /firefox/xpcom/threads/nsThread.cpp:1173:16
    #13 0x79f9e7e1b5f9 in NS_ProcessNextEvent(nsIThread*, bool) /firefox/xpcom/threads/nsThreadUtils.cpp:465:10
    #14 0x79f9e9873671 in mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) /firefox/ipc/glue/MessagePump.cpp:297:20
    #15 0x79f9e96b57a4 in MessageLoop::RunInternal() /firefox/ipc/chromium/src/base/message_loop.cc:371:10
    #16 0x79f9e96b57a4 in MessageLoop::RunHandler() /firefox/ipc/chromium/src/base/message_loop.cc:364:3
    #17 0x79f9e96b57a4 in MessageLoop::Run() /firefox/ipc/chromium/src/base/message_loop.cc:346:3
    #18 0x79f9e7e0b0f0 in nsThread::ThreadFunc(void*) /firefox/xpcom/threads/nsThread.cpp:374:10
    #19 0x7dfa13dbd88f in _pt_root /firefox/nsprpub/pr/src/pthreads/ptthread.c:191:3
    #20 0x5c4b2228fbf6 in asan_thread_start(void*) _asan_rtl_:28
    #21 0x7dfa14355aa3 in pthread_condattr_setpshared ??:?
    #22 0x7dfa143e2a63 in clone ??:0:0

SUMMARY: AddressSanitizer: stack-overflow (/firefox/obj-firefox-asan/dist/bin/libgkcodecs.so+0x6a017d) (BuildId: 823f1fcf5fd5e15a99b69a1de4edb232)
Thread T6 created by T5 here:
    ...
    #14 0x79f9f0f1fb73 in mozilla::RemoteDecoderParent::RecvInit(std::function<void (mozilla::InitResultIPDL const&)>&&) /firefox/dom/media/ipc/RemoteDecoderParent.cpp:52:13
    #15 0x79f9f103810a in mozilla::PRemoteDecoderParent::OnMessageReceived(IPC::Message const&) /firefox/obj-firefox-asan/ipc/ipdl/PRemoteDecoderParent.cpp:216:87
    ...
Thread T5 created by T0 (Utility Process) here:
    ...
    #13 0x79f9e98c5599 in mozilla::ipc::UtilityMediaServiceParent::RecvNewContentRemoteMediaManager(mozilla::ipc::Endpoint<mozilla::PRemoteMediaManagerParent>&&, mozilla::dom::IdType<mozilla::dom::ContentParent> const&) /firefox/ipc/glue/UtilityMediaServiceParent.cpp:142:8
    ...
==313952==ABORTING
Attached file test.html —
Attached patch fix.patch — — Splinter Review
Attached file crash_stack.txt —
Group: core-security → media-core-security
Crash Signature: [@ vorbis_book_init_decode ]

The bug has a crash signature, thus the bug will be considered confirmed.

Status: UNCONFIRMED → NEW
Ever confirmed: true
Whiteboard: [prefs-checked]

Pref check: no prefs required (AudioDecoder is on by default) → supported config. sec-high is correct: attacker-chosen stack displacement up to ~128 MiB, web-reachable, no interaction.

Crash reproduced on origin/main, fix applied, verified no crash with the attached testcase (k=23 → 8M entries) and a k=16 variant (64K entries).

This patch bounds n (used entries) to 32768 before the two alloca() calls. The limit is taken from the dec_firsttable hint packing later in the same function — loval/hival are clamped to 15 bits each, so the decode hints already saturate past 32768 entries. Real Vorbis codebooks top out in the low thousands.

Compared to attachment 9564019 [details] [diff] [review] (alloca→malloc): that fixes the stack-clash but still permits ~200 MiB of heap per codebook (_make_words, codep, sortindex, plus the persistent c->codelist/dec_index/dec_codelengths) and an 8M-element qsort, all from ~126 bytes of input. Bounding n closes both the memory-corruption and the resource-exhaustion variants.

The err_out path calls vorbis_book_clear(c); at the point of the new check only scalar fields are set (pointer members are still NULL from the memset), so cleanup is safe.

Note: vendored code — should also go upstream to xiph.org/vorbis.

This is the analysis tool's suggested fix. Feel welcome to adopt it as a starting point and evolve it as needed to meet our coding standards.

audio decoding in vorbis related. Karl, mind taking a look?

Flags: needinfo?(karlt)
Severity: -- → S2
Component: Audio/Video → Audio/Video: Web Codecs
Whiteboard: [prefs-checked] → [prefs-checked][pp3]
Assignee: nobody → cchang
Attached file (secure) (obsolete) —

Add TestVorbisCodebookInit that constructs Vorbis headers with a codebook
using dim=0 and entries=2^23 to verify the decoder rejects it without
crashing.

Attached file (secure) —

Add a crafted .ogg file with a codebook that has dim=0 and entries=2^23,
and a crashtest HTML that loads it via <audio> to verify no crash via
the OggDemuxer path.

Attached file (secure) —

Reject codebooks with more than 32768 used entries before the alloca()
calls in vorbis_book_init_decode(). The dec_firsttable hint packing uses
15 bits per value and saturates past 32768, and real codebooks top out
in the low thousands. This prevents stack overflow from a crafted setup
header with dim=0 and a large entry count.

This is a sec bug in libvorbis library. I'll upload a standalone test and fix shortly, and report to upstream developer repo

Attached file bug-2029070-analysis.md (obsolete) —

I'm concerned that bounding n to 32768 isn't sufficient as long as vorbis_book_init_decode() continues to use alloca(). With this limit in place, an attacker can still trigger 384kB of stack allocation - the PLATFORM_DECODER pool uses 512kB stacks but at least one of the threads the Vorbis decoder may run on uses a 256kB stack (Web Audio decodeAudioData() path via MediaSupervisor), so this still leaves a realistic crash/DoS on that path. More importantly, per bug 2027386, Firefox macOS builds don't have compiler-emitted stack probing for these alloca() calls, so bounding n shrinks but does not remove stack-clash window on that platform.

Also, bug 2026182 seems to be a duplicate of this one.

Attachment #9570063 - Attachment is obsolete: true
Duplicate of this bug: 2026182

updated version of the analysis

Attachment #9570066 - Attachment is obsolete: true
Attached file libvorbis-report.zip —

issue analysis that will be reported to upstream vorbis community, including the standalone tests (w/ debugging logs) and suggested fix. I've requested an account from https://gitlab.xiph.org/xiph/vorbis. Now I am waiting for account approval.

(In reply to Matthew Gregan [:kinetik] from comment #15)

I'm concerned that bounding n to 32768 isn't sufficient as long as vorbis_book_init_decode() continues to use alloca(). With this limit in place, an attacker can still trigger 384kB of stack allocation - the PLATFORM_DECODER pool uses 512kB stacks but at least one of the threads the Vorbis decoder may run on uses a 256kB stack (Web Audio decodeAudioData() path via MediaSupervisor), so this still leaves a realistic crash/DoS on that path. More importantly, per bug 2027386, Firefox macOS builds don't have compiler-emitted stack probing for these alloca() calls, so bounding n shrinks but does not remove stack-clash window on that platform.

Also, bug 2026182 seems to be a duplicate of this one.

For anyone concern, the solution in https://phabricator.services.mozilla.com/D294331 has been updated.

Flags: needinfo?(karlt)
Attached file oldadv.txt (obsolete) —

Updated advisory.txt

(In reply to Simon Friedberger [:simonf] from comment #21)

Created attachment 9572593 [details]

Hi Simon, the file uploaded looks incomplete?

Flags: needinfo?(sfriedberger)

That's intentional, the parts which are not filled-in are auto-generated (usually everything is) I needed to override the reporter field because we unfortunately fixed the duplicate instead of the original report.

Flags: needinfo?(sfriedberger)

Comment on attachment 9570065 [details]
(secure)

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Moderate. The patch reveals that alloca() calls sized by used_entries in vorbis_book_init_decode were replaced with heap allocations, pointing to this function as the location of the issue. However, constructing the triggering Vorbis setup header — including bypassing the ov_ilog(dim)+ov_ilog(entries)>24 guard with dim=0 and using ordered-length encoding to fill all entries — requires independent knowledge of the Vorbis bitstream specification not disclosed by the patch.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No. Commit messages are generic, no inline comments reveal the vulnerability class, and the crashtest will not land with the fix.
  • Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: The vulnerable alloca calls in libvorbis's vorbis_book_init_decode have been present since libvorbis was first vendored into Firefox, with no pref gate on desktop. All currently supported desktop branches are affected: Nightly (152), Beta (151), Release (150), ESR 140, ESR 128, and ESR 115. The status-firefox* flags should be updated to reflect affected for all active versions.
  • If not all supported branches, which bug introduced the flaw?: N/A — the vulnerable code predates the Firefox regression range; it was present when libvorbis was first vendored.
  • Do you have backports for the affected branches?: Not yet prepared.
  • If not, how different, hard to create, and risky will they be?: Low risk. The fix is small and self-contained (two alloca→malloc replacements plus null checks in a single function). The libvorbis code has not diverged across branches. Backports to Beta, Release, ESR 140, ESR 128, and ESR 115 should apply cleanly. Note: ESR backports require separate uplift approval.
  • How likely is this patch to cause regressions; how much testing does it need?: Low. The change is limited to vorbis_book_init_decode during codec initialization, replaces stack allocation with heap allocation without altering the algorithm, and introduces no API changes. The existing err_out cleanup path was already exercised by prior tests.
  • Is the patch ready to land after security approval is given?: Yes.
  • Is Android affected?: No for Release, Beta, and ESR on Android. WebCodecs AudioDecoder is gated behind @IS_NIGHTLY_BUILD@ on Android, and Ogg/Vorbis playback via <audio> uses the Android platform decoder, bypassing libvorbis. Android Nightly is potentially affected via WebCodecs, as the Android native codec module is not enabled in the Utility process.

Drafted with the assistance of Claude Code — reviewed and approved by the patch author.

Attachment #9570065 - Flags: sec-approval?
Attachment #9570065 - Flags: sec-approval? → sec-approval+
Group: media-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → 152 Branch

The patch landed in nightly and beta is affected.
:chunmin, is this bug important enough to require an uplift?

For more information, please visit BugBot documentation.

Flags: needinfo?(cchang)

To add to comment 28, please also add uplift requests for ESR140 and ESR115.

firefox-beta Uplift Approval Request

  • User impact if declined/Reason for urgency: sec-high stack-clash / out-of-stack memory corruption in the Utility audio-decoding process (and the content process via OggDemuxer) reachable from a malicious page with no user interaction via WebCodecs AudioDecoder or <audio> Ogg playback. On Linux/macOS the attacker can move the decoder thread's stack pointer past the guard page by an attacker-chosen displacement (up to ~128 MiB) and write predictable pointer values into adjacent mappings, yielding memory corruption. On Windows the same bitstream is DoS (auto-restarted). Without the fix the same code is also a resource-exhaustion vector (~200 MiB heap and an 8M-element qsort from ~126 bytes of input).
  • Code covered by automated testing?: no
  • Fix verified in Nightly?: yes
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing: N/A
  • Risk associated with taking this patch: low
  • Explanation of risk level: Self-contained change to one vendored libvorbis function — replaces two alloca() calls with _ogg_malloc/_ogg_free of the same data, and adds NULL checks on the surrounding existing heap allocations. No API/ABI change and no behavioural change on the success path. The Ogg/Vorbis decode path is exercised by all Ogg/Vorbis media playback, so any regression would be immediately visible. Diff is ~30 lines in a single .c file plus a moz.yaml patches: entry registering the upstream-style backport patches.
  • String changes made/needed?: None
  • Is Android affected?: yes
Attachment #9584660 - Flags: approval-mozilla-beta?
Attached file (secure) —

firefox-esr140 Uplift Approval Request

  • User impact if declined/Reason for urgency: sec-high stack-clash / out-of-stack memory corruption in the Utility audio-decoding process (and the content process via OggDemuxer) reachable from a malicious page with no user interaction via WebCodecs AudioDecoder or <audio> Ogg playback. On Linux/macOS the attacker can move the decoder thread's stack pointer past the guard page by an attacker-chosen displacement (up to ~128 MiB) and write predictable pointer values into adjacent mappings, yielding memory corruption. On Windows the same bitstream is DoS (auto-restarted). Without the fix the same code is also a resource-exhaustion vector (~200 MiB heap and an 8M-element qsort from ~126 bytes of input).
  • Code covered by automated testing?: no
  • Fix verified in Nightly?: yes
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing: N/A
  • Risk associated with taking this patch: low
  • Explanation of risk level: Self-contained change to one vendored libvorbis function — replaces two alloca() calls with _ogg_malloc/_ogg_free of the same data, and adds NULL checks on the surrounding existing heap allocations. No API/ABI change and no behavioural change on the success path. The Ogg/Vorbis decode path is exercised by all Ogg/Vorbis media playback, so any regression would be immediately visible. Diff is ~30 lines in a single .c file plus a moz.yaml patches: entry registering the upstream-style backport patches.
  • String changes made/needed?: None
  • Is Android affected?: yes
Attachment #9584661 - Flags: approval-mozilla-esr140?
Attached file (secure) —

firefox-release Uplift Approval Request

  • User impact if declined/Reason for urgency: sec-high stack-clash / out-of-stack memory corruption in the Utility audio-decoding process (and the content process via OggDemuxer) reachable from a malicious page with no user interaction via WebCodecs AudioDecoder or <audio> Ogg playback. On Linux/macOS the attacker can move the decoder thread's stack pointer past the guard page by an attacker-chosen displacement (up to ~128 MiB) and write predictable pointer values into adjacent mappings, yielding memory corruption. On Windows the same bitstream is DoS (auto-restarted). Without the fix the same code is also a resource-exhaustion vector (~200 MiB heap and an 8M-element qsort from ~126 bytes of input).
  • Code covered by automated testing?: no
  • Fix verified in Nightly?: yes
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing: N/A
  • Risk associated with taking this patch: low
  • Explanation of risk level: Self-contained change to one vendored libvorbis function — replaces two alloca() calls with _ogg_malloc/_ogg_free of the same data, and adds NULL checks on the surrounding existing heap allocations. No API/ABI change and no behavioural change on the success path. The Ogg/Vorbis decode path is exercised by all Ogg/Vorbis media playback, so any regression would be immediately visible. Diff is ~30 lines in a single .c file plus a moz.yaml patches: entry registering the upstream-style backport patches.
  • String changes made/needed?: None
  • Is Android affected?: yes
Attachment #9584662 - Flags: approval-mozilla-release?
Attached file (secure) (obsolete) —
Attached file (secure) —
Attachment #9584670 - Flags: approval-mozilla-esr115?

firefox-esr115 Uplift Approval Request

  • User impact if declined/Reason for urgency: sec-high stack-clash / out-of-stack memory corruption in the Utility audio-decoding process (and the content process via OggDemuxer) reachable from a malicious page with no user interaction via WebCodecs AudioDecoder or <audio> Ogg playback. On Linux/macOS the attacker can move the decoder thread's stack pointer past the guard page by an attacker-chosen displacement (up to ~128 MiB) and write predictable pointer values into adjacent mappings, yielding memory corruption. On Windows the same bitstream is DoS (auto-restarted). Without the fix the same code is also a resource-exhaustion vector (~200 MiB heap and an 8M-element qsort from ~126 bytes of input).
  • Code covered by automated testing?: no
  • Fix verified in Nightly?: yes
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing: N/A
  • Risk associated with taking this patch: low
  • Explanation of risk level: This patch only replaces two alloca() calls with _ogg_malloc/_ogg_free of the same data, and adds NULL checks on the surrounding existing heap allocations.
  • String changes made/needed?: None
  • Is Android affected?: yes
Attachment #9584660 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9584661 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
Flags: needinfo?(cchang)
Attachment #9584662 - Attachment is obsolete: true
Attachment #9584662 - Flags: approval-mozilla-release?
Attachment #9584670 - Flags: approval-mozilla-esr115? → approval-mozilla-esr115+
QA Whiteboard: [sec] [uplift] [qa-triage-done-c152/b151]
Whiteboard: [prefs-checked][pp3] → [prefs-checked][pp3][adv-main151+][adv-esr140.11+][adv-esr115.36+]
Attachment #9572593 - Attachment description: advisory.txt → oldadv.txt
Attachment #9572593 - Attachment filename: advisory.txt → oldadv.txt
Attachment #9572593 - Attachment is obsolete: true

revised local patches are going to be imported via bug 2039973

Blocks: 2039973
See Also: → 2039973
Alias: CVE-2026-8946
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: