OP-TEE OS cleanup_shm_refs() 越界读取漏洞复现环境
参考文档:https://optee.readthedocs.io/en/latest/building/devices/qemu.html#qemu-v8
安全公告:https://github.com/OP-TEE/optee_os/security/advisories/GHSA-65w8-6mrg-52g7
| 字段 | 内容 |
|---|---|
| 漏洞 | cleanup_shm_refs() 未验证 num_params(理论可达 127,实际受 Linux TEE ioctl TEE_MAX_ARG_SIZE=1024 限制为 31),但 saved_attr[] 仅 4 个元素 |
| 影响版本 | OP-TEE OS < 3.19.0 |
| 触发条件 | Normal World 通过直接 ioctl 发送 num_params=31 的 INVOKE 请求(绕过 libteec 的 4-参数限制) |
| 后果 | 越界读取安全世界栈数据;若栈残留值匹配 TMEM 类型则触发 Use-After-Free |
| 修复 | cleanup_shm_refs(MIN(TEE_NUM_PARAMS, num_params), ...)(commit 728616b) |
CVE-2022-46152/
├── README.md # 本文件
├── setup.sh # 一键搭建环境
├── run_qemu.sh # 启动 QEMU
├── exploit.sh # 自动/手动复现脚本
├── cve-2022-46152-oob-emsg.patch # OP-TEE OS 调试补丁(entry_std.c OOB EMSG)
├── qemu-pflash-suppress-unimp-log.patch # QEMU 补丁(抑制 pflash_write 噪音日志)
├── poc/
│ ├── cve_2022_46152.c # PoC exploit 源码(直接 ioctl 绕过 libteec)
│ └── Makefile # 交叉编译 Makefile
├── docs/
│ └── vulnerability_analysis.md # 详细漏洞技术分析
└── optee/ # OP-TEE 环境(由 setup.sh 创建)
├── optee_os/ # OP-TEE OS 3.18.0(漏洞版本)
├── build/ # 构建系统(qemu_v8.mk)
├── linux/ # Linux 内核
├── buildroot/ # Buildroot rootfs
├── trusted-firmware-a/ # TF-A v2.6
├── qemu/ # QEMU v7.0.0(源码)
└── out/bin/ # 编译产物
├── bl1.bin # TF-A BL1
├── Image # Linux 内核镜像
└── rootfs.cpio.gz # 包含 PoC 的 rootfs
# Ubuntu/Debian
sudo apt-get install -y \
repo git make python3 \
aarch64-linux-gnu-gcc \
device-tree-compiler \
libglib2.0-dev libpixman-1-dev \
netcat-openbsd expect
# 验证
aarch64-linux-gnu-gcc --version
repo --version
cd CVE-2022-46152
mkdir -p optee
cd optee
repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml -b 3.18.0
cd ..
注意:使用
3.18.0标签,此版本包含 CVE-2022-46152 漏洞,尚未应用修复。
./setup.sh
该脚本会:
repo sync 拉取全部源码optee/toolchains/ 已存在则跳过,否则自动下载)make all 构建 TF-A、OP-TEE OS 3.18.0、Linux、Buildroot# 打开三个终端:
# 终端1 — 启动 QEMU:
./run_qemu.sh --no-gdb
# 终端2 — Normal World 控制台(等待 run_qemu.sh 启动后再运行):
python3 optee/build/soc_term.py 54320
# 终端3 — Secure World(OP-TEE 日志,等待 run_qemu.sh 启动后再运行):
python3 optee/build/soc_term.py 54321
说明:
run_qemu.sh会在内部以服务端模式启动soc_term.py监听 54320/54321,
QEMU 作为客户端连接。上述命令是连接到已运行实例的示例,一般无需手动执行。
# 在 Normal World 终端(54320)等待登录提示后:
(none) login: root
# 执行 PoC
/root/cve_2022_46152
=== CVE-2022-46152 PoC Exploit ===
OP-TEE cleanup_shm_refs() Out-of-Bounds Read
Affected: OP-TEE OS < 3.19.0
[+] Opened /dev/tee0
[*] Opening session to Hello World TA...
[+] Session opened: id=2
[*] Triggering vulnerability: invoking with num_params=31
[*] saved_attr[] has only 4 slots -> reading 27 extra stack words OOB
[*] Buffer size: 1016 bytes (TEE_MAX_ARG_SIZE limit: 1024)
[+] ioctl returned: ret=0xffff0006 origin=0x3
[+] VULNERABILITY TRIGGERED!
[+] TEE returned TEE_ERROR_BAD_PARAMETERS (0xFFFF0006)
[+] entry_invoke_command() rejected num_params=31,
[+] but cleanup_shm_refs(31, saved_attr[4], ...) ran OOB!
[*] Check the Secure World UART (port 54321) for crash details.
[*] Done. Check secure world UART output for OOB/abort evidence.
注意:
TEE_MAX_ARG_SIZE=1024限制了单次 ioctl 传入最多 31 个参数(libteec 限制为 4)。 即便如此,num_params=31 仍足以触发 OOB(读取 saved_attr[4..30],超出边界 27 个元素)。
I/TC: OP-TEE version: 3.18.0 (...)
...
I/TA: Hello World!
E/TC:? 0 entry_invoke_command:452 CVE-2022-46152: OOB! cleanup_shm_refs num_params=31 > TEE_NUM_PARAMS=4
D/TC:? 0 tee_ta_close_session:511 csess ... id 2
I/TA: Goodbye!
加粗警告行
E/TC:? 0 entry_invoke_command:452 CVE-2022-46152: OOB!是通过
cve-2022-46152-oob-emsg.patch补丁在entry_std.c中添加的显式日志,
用于确认漏洞触发路径。cleanup_shm_refs越界读取栈上 27 个额外元素;
若栈残留值匹配 TMEM 类型,可触发mobj_put()Use-After-Free。
/* core/tee/entry_std.c */
static TEE_Result entry_invoke_command(struct optee_msg_arg *arg)
{
uint32_t saved_attr[TEE_NUM_PARAMS]; /* 仅 4 个槽! */
...
res = copy_in_params(arg->params, arg->num_params, params, saved_attr);
if (res != TEE_SUCCESS) {
/* ❌ BUG: num_params 可为 127,越界读 saved_attr[4..126] */
cleanup_shm_refs(arg->num_params, saved_attr, arg->params);
goto out;
}
...
}
if (res != TEE_SUCCESS) {
/* ✅ FIX: MIN(4, 127) = 4,不再越界 */
cleanup_shm_refs(MIN(TEE_NUM_PARAMS, num_params), saved_attr, arg->params);
goto out;
}
# 搭建环境
./setup.sh
# 启动 QEMU(带 GDB 调试端口)
./run_qemu.sh
# 启动 QEMU(不等待 GDB)
./run_qemu.sh --no-gdb
# 查看手动复现步骤
./exploit.sh --manual
# 自动化复现(无需额外终端,结果输出到当前 shell)
./exploit.sh
# 连接到 Normal World 控制台(run_qemu.sh 启动后)
python3 optee/build/soc_term.py 54320
# 连接到 Secure World 日志(run_qemu.sh 启动后)
python3 optee/build/soc_term.py 54321
# GDB 调试 OP-TEE OS
aarch64-linux-gnu-gdb optee/optee_os/out/arm/core/tee.elf
(gdb) target remote localhost:1234
(gdb) c
本仓库在 QEMU v7.0.0 基础上应用了补丁 qemu-pflash-suppress-unimp-log.patch,
消除运行 VM 时在终端产生的噪音输出:
pflash_write: Write to buffer emulation is flawed
hw/block/pflash_cfi01.c 的 pflash_write() 在处理 CFI pflash 0xe8(Write to buffer)命令时,
调用 qemu_log_mask(LOG_UNIMP, ...) 记录一条"实现不完整"告警。TF-A 固件在启动过程中会写入
pflash,触发此路径,导致每次启动都打印该信息。
hw/block/pflash_cfi01.c)删除 case 0xe8 分支内的 qemu_log_mask(LOG_UNIMP, ...) 调用,保留功能逻辑不变。
optee/qemu/)cd optee/qemu
git apply ../../qemu-pflash-suppress-unimp-log.patch
cd build
make -j$(nproc) qemu-system-aarch64
本仓库在 OP-TEE OS 3.18.0 基础上应用了一个调试补丁 cve-2022-46152-oob-emsg.patch,
使漏洞触发时能在 Secure World UART 输出显式告警,便于复现验证。
core/tee/entry_std.c)#include <trace.h>entry_invoke_command() 中,cleanup_shm_refs() 调用前检测 num_params > TEE_NUM_PARAMS,EMSG() 打印 CVE-2022-46152: OOB! cleanup_shm_refs num_params=N > TEE_NUM_PARAMS=4⚠️ 此补丁仅用于调试/演示,不是安全修复。真正的修复见 commit 728616b。
optee/optee_os/)cd optee/optee_os
git apply ../../cve-2022-46152-oob-emsg.patch
cd ../../
make -C optee/build optee-os