Submit #1000891: ggml-org xxxxxxxxxx llama.cpp up to main commit 8212c7802455255460ab8e18fc34754560031b34 (latest release b11160, 2026-09-24) Out-of-Bounds Write (CWE-787)info

Titleggml-org xxxxxxxxxx llama.cpp up to main commit 8212c7802455255460ab8e18fc34754560031b34 (latest release b11160, 2026-09-24) Out-of-Bounds Write (CWE-787)
DescriptionA vulnerability was found in ggml-org/llama.cpp up to main commit 8212c7802455255460ab8e18fc34754560031b34 (latest release b11160, 2026-09-24) and classified as high 7.8. Affected is the gen-audio streaming-state export of the multimodal projector runtime (tools/mtmd), reachable through the pocket-tts text-to-speech path of llama-tts. The manipulation of the mmproj tensor a.gen.wav.upsample.weight (with a.gen.wav.quant_out.weight, a.gen.emb_mean, a.gen.emb_std) leads to a heap out-of-bounds write whose length and contents are chosen by the projector file, repeated on every streaming flush of the audio generator, and the defect escalates to arbitrary command execution: a weaponized projector artifact was demonstrated executing an attacker-chosen command inside the victim process from the official command line alone, with no debugger and no memory patching. The attack is launched locally: the victim has to run the documented llama-tts command line with an attacker-supplied mmproj file passed to --mmproj alongside the victim's own pocket-tts backbone model. Technical Details - Affected file/function (measured at tested commit 3d82ef62d47fd74e18f36c5eccbdcf965b617b17 and re-measured at current main 8212c7802455255460ab8e18fc34754560031b34 on 2026-09-25; the construct is unchanged and no release contains a fix): list_pockettts_state_slots() sizes the streaming-state slot "up" from the declared weight shape as [gen_upsample_w->ne[0] - mimi_downsample, gen_upsample_w->ne[2]] (tools/mtmd/models/pockettts-gen.cpp:125). The graph builder's conv_transpose1d() instead treats the weight as non-depthwise whenever ne[1] != 1 and takes the output-channel count from ne[1] (tools/mtmd/models/pockettts-seanet.cpp:53-57), so the graph's state_out_up tensor shape follows ne[1]. The host-side export in clip_encode() sizes the state_out vector from the declared slot shapes (state_out.resize(total), tools/mtmd/clip.cpp:5835-5841 at the tested commit; :5865-5872 at current main) and then copies ggml_nbytes(t) bytes of the actual graph tensors sequentially into it (ggml_backend_tensor_get at clip.cpp:5849 / :5880) with no check that offset + nb stays within state_out, so nothing makes the allocation and the copies agree. A projector whose upsample weight is declared F32 [K, 512, 2] instead of the genuine depthwise [32, 1, 512] makes the host reserve a [K-16, 2] slot (192 bytes) while the graph produces a [K-16, 512] state tensor (49,152 bytes for K = 40): each export writes roughly 49 KB past a 192-byte reservation, once per GEN_WAV streaming flush. Three further tensors (a.gen.wav.quant_out.weight as an identity ne=[32,1], a.gen.emb_mean = [1,0,...], a.gen.emb_std = zeros) pin the transposed-convolution input to a known value, which makes every written 32-bit word exactly attacker-chosen, with a different payload per flush. The same export serves the qwen3-tts gen path (list_gen_state_slots, tools/mtmd/clip.cpp:4408-4413 at the tested commit). - Vulnerable parameter: mmproj GGUF tensors a.gen.wav.upsample.weight (with a.gen.wav.quant_out.weight, a.gen.emb_mean, a.gen.emb_std) - Attack vector: Local - Privileges required: None - Trigger condition: default configuration (--no-mmproj-offload was used in the lab for determinism only); one normal user interaction (generating speech from an attacker-supplied projector). The victim's own backbone must be a gen-audio (pocket-tts) model - the genuine kyutai/pocket-tts conversion was the victim; the attacker's file is only the mmproj, built by rewriting four tensors of an otherwise genuine projector file. - Escalation (achieved in the laboratory, fixed environment): the controlled, repeating, per-flush-programmable heap overwrite was escalated end-to-end to arbitrary command execution on a pinned environment (llama.cpp 3d82ef62d47fd74e18f36c5eccbdcf965b617b17, Ubuntu 20.04, glibc 2.31, clang 16 RelWithDebInfo, ASLR disabled in the container). The chain: the overwrite corrupts allocator metadata and poisons tcache; a freed ggml backend object is reclaimed with a forged structure; a forged std::set red-black-tree node makes the tree rebalancing write an attacker-chosen pointer into the backend's registry; a fake function-pointer entry redirects a call through glibc's setcontext to regain RIP/RSP/RDI; the payload then calls system() with an attacker-chosen command. The weaponized run used no debugger and no memory patching, and the proof command's output (uid=0 in the container) was written to a file. The exploit is deterministic for the pinned build and environment only (hardcoded addresses; other builds require recalibration) - the vulnerability itself is not environment-specific, only this weaponization is. - Origin of the weakness: original code of the project (pocket-tts support arrived in commit stream #26871, 2026-08; qwen3-tts in #26254). No prior advisory or public report of this exact issue exists (the repository's 13 published GitHub security advisories cover none of tools/mtmd; issue-tracker and global searches on 2026-09-24/25 returned zero hits). Reported to the vendor on 2026-09-24 through public PR #29360 - the repository's security policy states the private vulnerability reporting program is disabled and directs fixes to public PRs; the PR describes the memory-safety mechanism but no exploitation technique. The escalation summarized above has not been disclosed anywhere prior to this submission. - Validation: three levels, all in isolated container laboratories. (1) AddressSanitizer at the pinned commit: heap-buffer-overflow in the state_out copy path with the crafted projector; well-formed projectors unaffected. (2) Release build under gdb: the overwrite is byte-deterministic across runs, and a crafted implant kept the corrupted heap self-consistent through an entire generation (8 flushes x 64 rounds). (3) Native end-to-end (no debugger, no patching): the weaponized artifact executed an attacker-chosen command in the victim process from the official command line alone; the process exits 139 afterwards, expected from the forged context returning to a null address. The fix proposed in PR #29360 sizes state_out from the graph tensors, closing the write at its source. Impact - Confidentiality: High (arbitrary command execution demonstrated in the laboratory: full access to the victim process's memory and privileges) - Integrity: High (attacker-chosen 32-bit words over live heap objects and allocator state, escalating to arbitrary command execution) - Availability: High (reliable process abort/crash at or after generation; exploitation itself redirects the process) CVSS v3.1 Score: 7.8 (High) Vector: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H Timeline - Discovered: 2026-09-23 (memory-safety defect); escalation to code execution completed 2026-09-24 - Vendor notified: 2026-09-24 (public PR #29360, opened 2026-09-24T08:16Z - the only channel: the repository's security policy disables private vulnerability reporting and directs fixes to public PRs) - Patch released: [pending - PR #29360 open as of 2026-09-25; no release contains a fix] - Public disclosure: [pending - this VulDB submission; the memory-safety mechanism is public since PR #29360 (2026-09-24), the escalation is first disclosed here] Countermeasure Merge PR #29360: resolve the graph tensors first and size state_out from ggml_nbytes() of exactly those tensors, so the allocation and the copies cannot disagree by construction (the PR additionally rejects negative feature_layer values). Additionally validate depthwise shape and channel relations when loading pocket-tts weights, and bounds-check each state-tensor copy against the destination buffer. Until a fix ships, do not run the llama-tts / gen-audio paths with mmproj files from untrusted sources, or run them only in an isolated environment.
Source⚠️ https://github.com/3em0/cve_repo/tree/main/2026/llama.cpp.pockettts_state_heap_oob_rce
User
 Dem00000 (UID 98563)
Submission09/25/2026 18:56 (1 month ago)
Moderation10/25/2026 07:55 (30 days later)
StatusAccepted
VulDB entry426164 [ggml-org llama.cpp up to b9060 Pocket-TTS pockettts-gen.cpp list_pockettts_state_slots mmproj out-of-bounds write]
Points20

Interested in the pricing of exploits?

See the underground prices here!