When sending ool memory via |mach_msg| with |deallocate| flag or |MACH_MSG_VIRTUAL_COPY| flag, |mach_msg| performs moving the memory to the destination process instead of copying it. But it doesn’t consider the memory entry object that could resurrect the moved memory. As a result, it could lead to a shared memory race condition.
Exploitation: We need specific code that references the memory twice from |mach_msg|. Here’s a snippet of such a function |xpc_dictionary_insert|. v14 = strlen(shared_memory); <<-- 1st v15 = _xpc_malloc(v14 + 41); ... strcpy((char *)(v15 + 32), shared_memory); <<-- 2nd
If we change the string’s length bigger before |strcpy| is called, it will result in a heap overflow.
This bug is triggerable from a sandboxed process.
The attached PoC will crash diagnosticd(running as root). It requires more than 512MB of memory to run.
Tested on macOS Sierra 10.12.2(16C67).
clang++ -o poc poc.cc -std=c++11
Attachment: poc.cc