
Analysis, POC, and arm64 exploit chain for a Linux cifs.ko DACL heap overflow (CVE-2026-97555), escalating to a uid-0 credential overwrite on the reference build.
English | 简体中文
SMB 客户端在重写 DACL 时发生的内核堆溢出。id_mode_to_cifs_acl() 按服务端
返回的 DACL 计算输出缓冲区大小,但 replace_sids_and_copy_aces() 会用新的
owner/group SID(最长 68 字节)重写每一条 ACE。当服务端返回短 SID 的 DACL
时,重写后的安全描述符超出分配大小,越过 kmalloc 对象写入。
本仓库包含分析、复现跨对象写的 POC,以及把溢出转成受控端到端链的 EXP (堆泄漏 → 页表页重占 → 任意 PTE 写 → 自身 cred 覆写为 uid 0),EXP 在 参考内核上验证。
| 项目 | 值 |
|---|---|
| CVE | CVE-2026-97555 |
| 类型 | 堆溢出(写,CWE-122),id_mode_to_cifs_acl() |
| 组件 | cifs.ko(SMB 客户端) |
| 影响 | 未包含上游修复的 Linux cifs.ko(验证目标为 6.12 GKI 系 Android 内核) |
| 修复 | 上游 0ee150794c75(stable fb736ab4fb8c) |
| 参考构建 | Android 16 GKI 系 6.12,arm64,4 KiB 页,64 字节 struct page |
| POC | 跨对象写已复现(SET_INFO 安全描述符 696 字节) |
| EXP | 参考构建上完整链到 uid-0 shell |
/proc/kpageflags 都需要 root。挂载能力属于测试夹具,不是漏洞本身,
不在本仓库范围内。uid/suid/euid/fsuid 四个字段提回 uid 0;不改
capability / securebits。清理方式是重启。src/exp.c 中的常量(符号地址、vmemmap 公式、BTF 偏移)属于参考构建,
换内核必须先重新推导,见 scripts/derive_offsets.sh。id_mode_to_cifs_acl() 用 dacl_ptr->size 或
num_aces * sizeof(struct smb_ace) 计算分配大小;
replace_sids_and_copy_aces() 随后用新的 owner/group SID 重建每条 ACE。
服务端 SID 很短(0 个子授权)而新 SID 为 68 字节时,重建后的 DACL 长于
分配,build_sec_desc() 越过 slab 对象写入。
内核的动态 FORTIFY 只检查内联的 ACE 头写入;SID 拷贝走独立的
cifs_copy_sid(),不受插桩。对齐布局使每条 ACE 头都落在
nsecdesclen - 28 之内即可到达漏洞拷贝。
服务端 cross7 布局(7 条 ACE,源长度 76/76/76/44/44/16/16)使分配恰好
512 字节;第 7 条 ACE 的 68 字节 SID 拷贝从偏移 492 开始、跨越对象边界;
重写后的描述符长度为 696 字节,即越过对象 184 字节。扩展后的安全描述符
仍会通过 SET_INFO 发出,因此写溢出可在服务端观察。
fb736ab4fb8c 的内核。kpageflags、挂载、chown),以及 cifs idmap
upcall 所需的 SELinux permissive 窗口(或等效策略放行)。src/poc_smb2_acl.py 提供的共享,用标准内核客户端以
cifsacl/modefromsid 挂载(scripts/mount_cifs.sh)。挂载是特权
夹具,测试者如何获得该权限不属于本仓库范围。cifs.idmap 键:参考环境没有 /sbin/cifs.idmap
upcall 助手(src/poc.c 与 src/exp.c 会自行预载,
src/acl_key_preload.c 是独立版本)。# 主机
python3 src/poc_smb2_acl.py # 溢出用 ACL_LAYOUT=cross7
adb reverse tcp:1468 tcp:1468
# 设备(root)
sh /data/local/tmp/e2e/mount_cifs.sh 127.0.0.1 share /mnt/cifs
make && make push
/data/local/tmp/poc /mnt/cifs
证据:服务端日志出现 SET_INFO security: len=696 ...(cross7),即安全
描述符长于 512 字节分配;scripts/trace_acl02.sh 可看到 chown 期间
id_mode_to_cifs_acl 的进入/返回。
POC 只触发漏洞路径,不做堆布局、泄漏或提权。触发会执行一次内核越界写: 在布局命中动态 FORTIFY 检查的构建上可能 panic,只应在可重启的测试设备上 执行。
EXP 是完整链(参考构建):
cross7 溢出改写相邻 key payload 的 datalen,keyctl_read
dump 64 KiB,其中包含活的 pipe_buffer 数组。泄漏的
anon_pipe_buf_ops 给出 KASLR slide,缓冲区页 P 给出真实
struct page 目标。+0x200 是活 hit 数组。释放的槽按
LIFO 被 chown 的安全描述符重占,某个 hit pipe 的 buffer[0] 被改写为
page=P、len=0x1234、ops=default_pipe_buf_ops。P;base 处 fault 触发
__pte_alloc 重占 P 为页表页,kretprobe 门禁确认
__alloc_pages_noprof 从 __pte_alloc 返回 P。P+16(PTE[2])开始;
前 8 字节是 P 自身的自映射描述符。用户态经 base+8 KiB 直接读写
页表页。KPF_SLAB 页分批经新鲜 PTE 映射,扫描本进程 comm;
用 pid/tgid、linear-map 窗口与 cred->uid/euid 交叉校验,并用从未
访问过的 VA 复核物理页。setresuid(2000)(内核重新分配 cred),经自映射
读 task->cred,只把 uid/suid/euid/fsuid 写 0,确认 getuid()==0
后清自映射并 execve("/system/bin/sh"),shell 以 uid 0 运行。make exp
make push
# 设备上以 root 运行:
sh /data/local/tmp/e2e/launch_exp.sh /mnt/cifs 10 1 r1 4000 400 2400 7 0 0 cred
# 结果在 /data/local/tmp/e2e/e2e_status.txt 与
# /data/local/tmp/e2e/root_shell.txt
cred 阶段由最后一个参数选择(cred);scout 只做只读验证后停住。
EXP 的 PTE 只存在于进程内,清理方式是重启。
依赖:Android NDK r29(可用 NDK= 覆盖)、GNU make、adb。
make # POC(arm64,API 24)
make exp # EXP
make build-all # 两者
make check # 推送并运行只读 pre-check(poc --check)
make push # 推送二进制与辅助脚本
make run # 推送并对 $(MNT)(默认 /mnt/cifs)运行 POC(destructive)
make host # POC 静态构建(qemu-aarch64)
make emu # host 构建并运行
make logs # logcat/dmesg 存入 logs/
make help
.
├── Makefile
├── README.md / README.zh-CN.md
├── LICENSE
├── src/
│ ├── poc.c # POC:idmap 预载 + chown 触发(不提权)
│ ├── exp.c # EXP:端到端链(含 cred 覆写)
│ ├── vuln_precheck.h # profile/环境门禁
│ ├── poc_smb2_acl.py # 恶意 SMB2/3 ACL 服务端(DACL 布局)
│ ├── acl_key_preload.c # 独立 cifs.idmap 键预载
│ └── cifs_keyring_dump.c # keyring 检查助手
├── scripts/
│ ├── mount_cifs.sh # 标准客户端挂载 POC 共享
│ ├── unmount_cifs.sh
│ ├── launch_exp.sh # 设备端 EXP 启动脚本
│ ├── trace_acl02.sh # id_mode_to_cifs_acl kprobe
│ └── derive_offsets.sh # 为 src/exp.c 推导 BTF 偏移
└── docs/analysis.md # 分析、原语与验证记录
vmlinux/BTF,并重新推导
偏移、符号地址与 vmemmap 公式。cifsacl 挂载、预载
idmap 键与 permissive 窗口。这是原语演示,不是从 untrusted_app 起步的
利用链。cifsacl/modefromsid。仅供授权安全研究与教学使用。作者不对滥用负责。仅在你拥有或获明确许可的 设备上测试。
MIT — 见 LICENSE。