New issue
Advanced search Search tips
Starred by 4 users

Issue metadata

Status: Fixed
Owner:
Closed: Dec 2016
Cc:



Sign in to add a comment

double vm_deallocate in userspace MIG code can lead to UaF in mach services

Project Member Reported by ianbeer@google.com, Sep 26 2016 Back to list

Issue description

Userspace MIG services often use mach_msg_server or mach_msg_server_once to implent an RPC server.

These two functions are also responsible for managing the resources associated with each message
similar to the ipc_kobject_server routine in the kernel.

If a MIG handler method returns an error code then it is assumed to not have take ownership of any
of the resources in the message and both mach_msg_server and mach_msg_server_once will pass the message
to mach_msg_destroy:

If the message had and OOL memory descriptor it reaches this code:


  case MACH_MSG_OOL_DESCRIPTOR : {
    mach_msg_ool_descriptor_t *dsc;

    dsc = &saddr->out_of_line;
    if (dsc->deallocate) {
        mach_msg_destroy_memory((vm_offset_t)dsc->address,
        dsc->size);
    }
    break;
  }

...

  static void
  mach_msg_destroy_memory(vm_offset_t addr, vm_size_t size)
  {
      if (size != 0)
    (void) vm_deallocate(mach_task_self(), addr, size);
  }

If the deallocate flag is set in the ool descriptor then this will pass the address contained in the descriptor
to vm_deallocate.

By default MIG client code passes OOL memory with the copy type set to MACH_MSG_PHYSICAL_COPY which ends up with the
receiver getting a 0 value for deallocate (meaning that you *do* need vm_deallocate it in the handler even if you return
and error) but by setting the copy type to MACH_MSG_VIRTUAL_COPY in the sender deallocate will be 1 in the receiver meaning
that in cases where the MIG handler vm_deallocate's the ool memory and returns an error code the mach_msg_* code will
deallocate it again.

Exploitability hinges on being able to get the memory reallocated inbetween the two vm_deallocate calls, probably in another thread.

This PoC only demonstrates that an instance of the bug does exist in the first service I looked at,
com.apple.system.DirectoryService.legacy hosted by /usr/libexec/dspluginhelperd. Trace through in a debugger and you'll see the
two calls to vm_deallocate, first in _receive_session_create which returns an error code via the MIG reply message then in
mach_msg_destroy.

Note that this service has multiple threads interacting with mach messages in parallel.

I will have a play with some other services and try to exploit an instance of this bug class but the severity should
be clear from this PoC alone.

Tested on MacOS Sierra 10.12 16A323
 
dsplug.c
4.4 KB View Download
Project Member

Comment 1 by ianbeer@google.com, Sep 26 2016

Labels: Id-648842132 Reported-2016-Sep-26
Project Member

Comment 2 by ianbeer@google.com, Sep 26 2016

crash PoC

dspluginhelperd actually uses a global dispatch queue to receive and process mach messages,
these are by default parallel which makes triggering this bug to demonstrate memory corruption
quite easy, just talk to the service on two threads in parallel.

Note again that this isn't a report about this particular bug in this service but about the
MIG ecosystem - the various hand-written equivilents of mach_msg_server* / dispatch_mig_server
eg in notifyd and lots of other services all have the same issue.
dsplug_parallel.c
3.0 KB View Download
Project Member

Comment 3 by ianbeer@google.com, Dec 22 2016

Labels: -Restrict-View-Commit Fixed-2016-Dec-13 CVE-2016-7633
Status: Fixed
Fixed in MacOS 10.12.2: https://support.apple.com/en-us/HT207423

Sign in to add a comment