ipc_kmsg_get_from_kernel, iOS 15.4 - root cause analysis

We discussed this vulnerability during Episode 152 on 20 September 2022

A fairly trivial OOB write in the XNU kernel that was introduced in an iOS 15.0 beta and patched in iOS 15.4. It seems ipc_kmsg_get_from_user() in conjunction with pre-allocated kmsgs (via mktimer) can receive sizes that are larger than the pre-allocated buffer. It’s possible to set the mktimer port as an exception port, and use something such as a breakpoint to get an exception message with controlled message contents (via the thread state) to overflow inside the ipc_kmsg structure. One primitive the writeup details is an arbitrary 4-byte write via the kmsg->ikm_header field, which is used as the destination in a memcpy in ipc_kmsg_get_from_kernel(). This blogpost mostly is just a root cause analysis and exploration of the arbitrary write primitive though, as Pointer Authentication (PAC) would get in the way of exploiting this. You’d also need some kind of read primitive to full chain this to know where to write to.