Full Report
Arm TrustZone is a Trusted Execution Environment (TEE) which runs two operating systems: a secure world and a non-secure world. For instance, a cryptographic service could be on the secure world. Then, a user could make a request to sign the data, without directly having access to the key. The Qualcomm secure world is called Qualcomm Secure Execution Environment (QSEE) but has not seen much use. Android runs the non-secure code and the QSEE contains user mode programs called trustlets. An Android user program sends a special ioctl that the kernel will handle and send to the secure world. This process is performed using shared memory. Write to some place, send the ioctl and then the secure world will do the processing and write back to the specified location. The simple protocol is not always enough. In these cases, some truslets need read/write access to memory, requiring the use of pointers. There's potential for abuse though: writing of arbitrary addresses to physical memory is bad and giving the trustlet access to the buffers directly is scary. To prevent these attacks, Qualcomm adds ION file descriptors, each represents an offset into the input buffer. Upon receiving the write request, the ION buffer is translated back to its original form. There is an allowlist for what descriptor can access what memory with a given offset. This offset causes major problems. By using the offset into the middle of these tables, we can get it to pull addresses part way in between. Although we can't write to arbitrary addresses, we can write to these corrupted addresses. The images in the article explain this super well. The difference between physical and virtual memory is important here. The virtual memory may be contiguous but not the physical. As a result, the buffer must contain information about both the address and the size of it. So, this allows us to control both the address and the size of the data being copied in. By using the primitive, the author was able to corrupt the allowlist table itself. Now, the buffers physical memory is mapped to the entire Android kernel. The author needed a primitive where they could write to arbitrary locations using the allowlist bypass they found. The widevine DRM has a bunch of complicated pointer functionality that was perfect for this. Using the encrypt/decrypt functionality made this easy to get a R/W primitive. Overall, an interesting post on using TrustZone to attack the Android kernel. The fundamental design flaw of the system was surprising. I didn't fully understand the entire exploit mechanism but enjoyed it regardless.
Analysis Summary
# Research: Attacking the Android kernel using the Qualcomm TrustZone
## Metadata
- **Author:** Tamir Zahavi-Brunner
- **Institution:** Independent Research (documented via personal technical blog)
- **Publication:** Tamir Zahavi-Brunner’s Blog
- **Date:** September 14, 2022
## Abstract
This research details the discovery and exploitation of **CVE-2021-1961**, a critical vulnerability in the communication protocol between the Android OS (Normal World) and Qualcomm Secure Execution Environment (QSEE/TrustZone). The author demonstrates how a logic flaw in the handling of ION memory buffers allows an attacker to bypass memory isolation, granting a trustlet unauthorized access to the entire Android kernel memory. The research culminates in a reliable, version-agnostic exploit achieving arbitrary physical memory read/write primitives.
## Research Objective
The study aims to investigate the security boundaries of the Qualcomm TrustZone (QSEE) communication protocol. Specifically, it seeks to determine if flaws in the shared memory management system (ION buffers and whitelisting) can be leveraged to compromise the Android kernel from a user-mode process with access to the QSEE interface.
## Methodology
### Approach
1. **Reverse Engineering:** Systematic analysis of the closed-source QSEE trustlets and the `qseecom` kernel module to understand the undocumented communication protocol.
2. **Vulnerability Research:** Identifying logic errors in how the Trusted Execution Environment (TEE) validates memory pointers and offsets provided by the Normal World.
3. **Exploit Development:** Proof-of-concept creation to transform a memory corruption bug into a stable read/write primitive.
### Dataset/Environment
- Qualcomm-based Android devices using QSEE.
- The `Widevine` DRM trustlet (used as an exploitation vector).
- Software interface: `/dev/qseecom`.
### Tools & Technologies
- Interactive Disassemblers (e.g., IDA Pro/Ghidra) for binary analysis.
- Android Kernel sources (for `qseecom` driver analysis).
- Custom C/C++ exploitation code.
## Key Findings
### Primary Results
1. **Protocol Design Flaw:** The QSEE protocol allows input data and memory pointers to be interleaved using offsets. The system failed to validate if these offsets caused memory addresses to overlap.
2. **Whitelist Bypass:** By overlapping ION buffer descriptors, an attacker can corrupt the "whitelist" entries that define which memory regions a trustlet can access.
3. **Kernel Compromise:** This corruption allows a trustlet to be "fooled" into treating the entire Android kernel physical memory as a legitimate shared buffer.
### Novel Contributions
- **Hardware-Backed Primitive:** Unlike software-only kernel exploits, this uses the TEE as a "confused deputy" to modify kernel memory, bypassing many standard OS-level mitigations.
- **Version Agnostic Technique:** The researcher developed a method to scan physical memory for `kallsyms` (kernel symbols), making the exploit work across different devices and kernel versions without hardcoded offsets.
## Technical Details
The vulnerability lies in the translation of ION file descriptors. When a user sends a command, they provide an input buffer and a table of offsets. The kernel replaces the data at those offsets with the physical addresses of ION buffers.
- **The Bug:** If two offsets are provided such that the second address partially overwrites the first, the "size" field of the first ION buffer entry can be controlled by the attacker.
- **The Primitive:** By carefully aligning buffers from different ION heaps, the author created a whitelist entry with a massive "size" spanning the kernel's memory space.
- **The Vector:** The Widevine trustlet’s encryption/decryption functions were repurposed. By asking Widevine to "decrypt" data from a kernel address into another kernel address, the author achieved arbitrary R/W.
## Practical Implications
### For Security Practitioners
- TEE boundaries are not impenetrable; the "glue" code (drivers and protocols) between worlds is a high-value target.
- Hardware-based isolation is only as strong as the validation logic in the Secure World.
### For Defenders
- **Input Validation:** Ensure all offsets and lengths in shared memory protocols are strictly validated for overlaps (sanity checks).
- **Least Privilege:** Restrict access to `/dev/qseecom`. While not accessible to untrusted apps by default, any bridged service (like media servers) becomes a critical pivot point.
### For Researchers
- Demonstrates that reversing TEE components (despite being closed-source) is essential for full-stack mobile security audits.
## Limitations
- **Access Requirements:** The exploit requires access to `/dev/qseecom`, which is typically restricted by SELinux. It is not a "one-click" remote exploit but requires a prior chain (e.g., a vulnerability in a privileged service) to reach this interface.
## Comparison to Prior Work
This research updates the community's understanding of QSEE, which had largely remained stagnant since Gal Beniamini's 2016 publications. It moves beyond simple buffer overflows into complex logic flaws in TEE memory management.
## Future Work
- Investigation into other TEE implementations (e.g., Trustonic, OP-TEE) for similar protocol-level overlaps.
- Analysis of newer Qualcomm mitigations that may have been introduced in response to this CVE.
## References
- CVE-2021-1961
- [Tamir Zahavi-Brunner's Blog - Original Post](https://tamirzb.com/attacking-android-kernel-using-qualcomm-trustzone)
- Qualcomm Security Advisories (2021)