# CVE-2020-27932: iOS Kernel privesc with turnstiles
*Ian Beer, Project Zero (Originally posted on [Project Zero blog](https://googleprojectzero.blogspot.com/p/rca.html) 2021-02-04)*

## The Basics

**Disclosure or Patch Date:** 5 November 2020

**Product:** Apple iOS

**Advisory:** https://support.apple.com/en-us/HT211929 

**Affected Versions:** iOS 14.1 and previous

**First Patched Version:** iOS 14.2

**Issue/Bug Report:** https://bugs.chromium.org/p/project-zero/issues/detail?id=2107 

**Patch CL:** N/A

**Bug-Introducing CL:** N/A

**Reporter(s):** Ian Beer of Google Project Zero


## The Code

**Proof-of-concept:** https://bugs.chromium.org/p/project-zero/issues/detail?id=2107

**Exploit sample:** N/A

**Did you have access to the exploit sample when doing the analysis?** Yes

## The Vulnerability

**Bug class:** Type confusion

**Vulnerability details:**

A kernel type confusion between an `ipc_port` pointer and a `host_notify_entry` pointer due to failure to account for the semantics of `IKOT_HOST_NOTIFY` ports in turnstile code.


`IKOT_HOST_NOTIFY` ports have slightly unusual semantics: the `host_request_notification` method allows userspace to take a regular, userspace-owned mach port and set the `kobject` field to point to a `host_notify_entry` object. The `kobject` field is actually a member of a fairly large union (`kdata`) leading to plenty of opportunities for type confusions if kernel code doesn't account for the semantics of `IKOT_HOST_NOTIFY` ports (i.e., if the kernel code doesn't know that userspace-owned ports can suddenly become `IKOT_HOST_NOTIFY` ports.)

```
union {
  ipc_kobject_t kobject;
  ipc_kobject_label_t kolabel;
  ipc_importance_task_t imp_task;
  ipc_port_t sync_inheritor_port;
  struct knote *sync_inheritor_knote;
  struct turnstile *sync_inheritor_ts;
} kdata;
```

There have been type confusions here before; for example a type confusion between `imp_task` and `kobject` (via the `IKOT_HOST_NOTIFY` trick) was fixed in MacOS 10.10.

In this case the turnstiles code added around iOS 12 added the `sync_inheritor_port` field to the `kdata` union to indicate the destination port to which a new type of port called a special reply port had been sent. Through some mach port gymnastics it was possible to get the kernel to read a pointer to a `host_notify_entry` as a `ipc_port` pointer (via `sync_inheritor_port`) and then cause an out of bounds write.

Specifically: send a mach message to a destination port and attach the `thread_special_reply_port` as the `msgh_local_port` with a `SEND_ONCE` disposition.

The trick to make something bad happen is to set the `MACH_SEND_SYNC_OVERRIDE` flag when sending that message. This allows you to change the `ip_sync_link_state` value away from `PORT_SYNC_LINK_ANY`.

After sending that message, convert the thread's `special_reply_port` to a `IKOT_HOST_NOTIFY` via `host_request_notification`.

Then attempt to receive a message on that `special_reply_port` and you'll hit the type-confusion when `ipc_port_adjust_special_reply_port_locked` reads `special_reply_port->ip_sync_inheritor_port` expecting a valid port pointer, but actually finds a `host_notify_entry` pointer because the `special_reply_port` was converted to a `host_notify` port.

**Patch analysis:** N/A

**Thoughts on how this vuln might have been found _(fuzzing, code auditing, variant analysis, etc.)_:**

This bug could be seen as a variant of earlier issues involving this union; it could have been found via manual review if you were familiar with those earlier issues. Actually figuring out the conditions required to cause an exploitable type confusion are non-trivial, and I wouldn't expect a fuzzer to find them.

**(Historical/present/future) context of bug:** 

## The Exploit

(The terms *exploit primitive*, *exploit strategy*, *exploit technique*, and *exploit flow* are [defined here](https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html).)

**Exploit strategy (or strategies):** *Still under analysis.*

**Exploit flow:** *Still under analysis.*

**Known cases of the same exploit flow:** *Still under analysis.*

**Part of an exploit chain?** This vulnerability was used as a part of an iOS exploit chain. It was used after the Safari RCE ([CVE-2020-27930](CVE-2020-27930.md)) and the kernel memory disclosure ([CVE-2020-27950](CVE-2020-27950.md)).

## The Next Steps

### Variant analysis

**Areas/approach for variant analysis (and why):** I would suggest auditing similar uses of complex unions.

**Found variants:** N/A

### Structural improvements

The use of a union here seems unnecessary; the memory saving is negligible on modern systems. My suggestion would be to either add another memory to `ipc_port` which stores the current valid field of the `kdata` union, or break the union fields out into separate members.

### 0-day detection methods


## Other References 
