Invia #798504: ggml-org llama.cpp (confirmed on commit e15efe0 / tag b8635+1) Uncontrolled Recursioninformazioni

Titologgml-org llama.cpp (confirmed on commit e15efe0 / tag b8635+1) Uncontrolled Recursion
Descrizione## CVSS **CVSS 3.1 Vector:** AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H **CVSS 3.1 Score:** 7.5 High --- ## Summary The GBNF grammar parser in llama.cpp contains unbounded mutual recursion between `parse_sequence()` (line 592) and `parse_alternates()` (line 440) in `src/llama-grammar.cpp`. A crafted grammar string with deeply nested grouping parentheses (e.g., `root ::=(((...` with 2,000 levels) exhausts the call stack and crashes the process with SIGSEGV or SIGABRT. This is remotely exploitable via the HTTP API: the `grammar` parameter in `POST /v1/chat/completions` and `POST /completion` accepts untrusted GBNF strings that are parsed before generation begins. No authentication is required by default. A single 4 KB malicious API request crashes the entire llama-server process, denying service to all concurrent users. **Distinction from CVE-2026-2069:** CVE-2026-2069 (GHSA-f8m3-93xm-637c) affects `llama_grammar_advance_stack` the grammar **evaluation** phase. This vulnerability is in `parse_sequence`/`parse_alternates` the grammar **parsing** phase. Different functions, different phases, different triggers. The CVE-2026-2069 fix (PR #18993, currently unmerged) does NOT touch the parsing functions and would not patch this bug. --- ## Technical Details ### Mutual Recursion 1. `parse_sequence()` at line 592 encounters `'('` and calls `parse_alternates()` at line 597 2. `parse_alternates()` at line 440 immediately calls back to `parse_sequence()` 3. Each `(` adds ~2-4 KB of stack frames (std::string, std::vector, function params) With 8 MB default Linux stack: - ASan builds: ~2,000 nesting levels exhausts the stack - Release builds: ~5,000-10,000 nesting levels ### Attack Surfaces | Entry Point | Access | |---|---| | `POST /v1/chat/completions` (`grammar` param) | HTTP API, no auth | | `POST /completion` (`grammar` param) | HTTP API, no auth | | `llama-cli --grammar` / `--grammar-file` | CLI | | `llama_grammar_init()` | Library API | --- ## Exploit / PoC **File:** `poc-017-gbnf-recursion.txt` (4,010 bytes — 2,000 nested parentheses) **Generate:** ```bash python3 -c "print('root ::=' + '(' * 2000)" > poc-017.txt ``` **Reproduce via CLI:** ```bash llama-cli --grammar-file poc-017.txt -m model.gguf -p test # => SIGSEGV (stack overflow) or ASan: stack-overflow ``` **Reproduce via HTTP API:** ```bash curl -s http://localhost:8080/v1/chat/completions \ -H 'Content-Type: application/json' \ -d "{\"model\":\"any\",\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}], \"grammar\":\"root ::=$(python3 -c "print('(' * 2000)")\"}" # => Server crashes ``` --- ## Suggested Fix Add recursion depth counter with limit of 1024: ```cpp static constexpr int LLAMA_GRAMMAR_MAX_NESTING = 1024; // In parse_sequence(), before recursive call: if (depth >= LLAMA_GRAMMAR_MAX_NESTING) { throw std::runtime_error("grammar nesting depth exceeded"); } pos = parse_alternates(pos, rule_name, sub_rule_id, true, depth + 1); ``` --- ## Deconfliction Note | Published CVE | Root Cause | This Bug | |---|---|---| | CVE-2026-2069 (PR #18993) | Stack overflow in `llama_grammar_advance_stack` (evaluation phase, line 858) | Stack overflow in `parse_sequence`/`parse_alternates` (parsing phase, lines 440/597) | PR #18993 is currently UNMERGED and only modifies evaluation-phase functions. Even if merged, it would NOT fix this parsing-phase vulnerability. --- ## Discovery - **Tool:** Crucible structure-aware fuzzer (grammar campaign) - **Date:** 2026-04-04 - **Confirmed on:** llama.cpp commit e15efe0 (tag b8635+1), Fedora 43 x86_64
Utente
 m00dy (UID 97162)
Sottomissione07/04/2026 03:39 (4 mesi fa)
Moderazione26/07/2026 19:34 (4 months later)
StatoAccettato
Voce VulDB383354 [ggml-org llama.cpp e15efe0 JSON-Schema-to-GBNF Conversion json-schema-to-grammar.cpp transform negazione del servizio]
Punti17

Do you know our Splunk app?

Download it now for free!