180 - An iPod Nano Bug, XNU Vuln, and a WebKit UAF
A trivial out of bounds access in the iPod nano 3rd-5th generation’s USB stack in the bootROM. The USB::HandlePendingSetup()
handler for SETUP packets would accept a request and dispatch it to different sub-handlers based on the bmRequestType
. In the case of bmRequestType == 3
, it would take an attacker controlled wIndex
value to index into an array of handlers then execute it. This index was unchecked and could access out of bounds of the array. This gave an attacker code execution immediately, and these devices don’t have no-execute (NX). By utilizing a bx r0
ARM gadget (r0
was set to point to the attacker’s request buffer which they control the contents of), they could execute their own shellcode and get stable code exec.
Kinda of a cool race condition and sort of differential attack deep inside XNU’s virtual memory system that allows for bypassing “copy on write” and writing to the underlying page without making a copy.
This starts off with the vm_map_copy_overwrite
function, when handling large copies it will take one of two routes, an aligned or unaligned route, aligned if the copy neatly lands on a page boundary, unaligned if it doesn’t. While these two should semantically do the same thing, the code for an unaligned copy has one extra condition. The aligned copy, if its a copy on write page, always makes a shadow copy of the memory that’ll be used. The unaligned copy how performs the same check for copy on write protected pages, but also checks the page’s flags for the VM_PROT_WRITE
flag, only making a shadow copy if the page is also writable.
This condition is enforced earlier in the chain, before the call to perform the copy vm_map_copy_overwrite_nested
will iterate over the entire destination address range and ensure they all have the write flag, so this exploitable condition should be possible. However all this isn’t atomic, and there is a race condition. During the copying process the mapping is unlocked and relocked between calls to vm_fault_copy
creating an opportunity for the flag to be flipped.
The end result of this is a write to a CoW page that will be reflected in all other users of that same page.