Show Notes

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.