86 - Kernel UAFs and a Parallels VM Escape
A Use-After-Free in Android’s ION Allocator used by the kernel for DMA buffers that can be shared across user/kernel/device boundaries. The issue starts from the DMA_BUF_IOCTL_SYNC
that is exposed by the buffer’s file descriptor, this IOCTL can arbitrarily increment or decrement the reference counter for the shared buffer. Enabling a malicious user-space application to allocate a DMA buffer, pass it into another kernel function and then trigger the reference count to drop to zero resulting in it being freed while the other function is still using it.
An interesting primitive in io_uring
resulting in the ability to free adjacent kernel buffers.
For files that do not provide the read_iter
operation io_uring will fall back to use loop_rw_iter
to manually perform iterative read/writes. In doing so as it reads it will increment the requests addr
field by the size of the read. Normally, this will be a userland pointer however by calling IORING_OP_PROVIDE_BUFFERS
beforehand a kernel buffer can be used, which is later free’d once the operation completes. As the addr
field is no longer where it started it is possible to free adjacent kernel buffers.
Straight forward version is two Out-Of-Bounds accesses in reading and writing the Driver feature set
. A guest provided value is stored, and then used as an array index without any validation both in PciVirtIOWriteMM
and in PciVirtIOReadMM
giving relative read/write primitives.
This post also covers the exploitation (discovery and triaging at the start too!). First step was using the relative read to read out index 6
which contained a pointer nearby in memory, revealing the base address of the libMonitor.dyld
that that vulnerability was in.
Second step was turning the relative r/w into arbitrary r/w, this was done by targeting pointers in an io_port_handler
array that was in __bss
memory, which were used as parameters to the various handlers. Control of these pointers gave arbitrary read/write gadgets through AhciIdpIndexInPortFunc
and AhciIdpIndexOutPortFunc
Finally for arbitrary code execution on the host, the read was used to find the address of system
and the write was used to replace a function pointer used by smb_write
, and setup the command string for the variable used when smb_write
would call that function pointer.