macOS Kernel - Use-After-Free Due to Lack of Locking in 'AppleEmbeddedOSSupportHostClient::registerNotificationPort'

EDB-ID: 44007
Author: Google Security Research
Published: 2018-02-09
CVE: CVE-2018-4083
Type: Dos
Platform: macOS
Aliases: N/A
Advisory/Source: Link
Tags: N/A
Vulnerable App: N/A

 AppleEmbeddedOSSupportHost.kext is presumably involved in the communication with the OS running on the touch bar on new MBP models. 

Here's the userclient's registerNotificationPort method:

__text:0000000000002DE4 ; AppleEmbeddedOSSupportHostClient::registerNotificationPort(ipc_port *, unsigned int, unsigned int)
__text:0000000000002DE4 push rbp
__text:0000000000002DE5 mov rbp, rsp
__text:0000000000002DE8 push r14
__text:0000000000002DEA push rbx
__text:0000000000002DEB mov r14, rsi
__text:0000000000002DEE mov rbx, rdi
__text:0000000000002DF1 mov rdi, [rbx+0E8h]
__text:0000000000002DF8 test rdi, rdi
__text:0000000000002DFB jz short loc_2E0D
__text:0000000000002DFD call __ZN12IOUserClient23releaseNotificationPortEP8ipc_port ; IOUserClient::releaseNotificationPort(ipc_port *)
__text:0000000000002E02 mov qword ptr [rbx+0E8h], 0
__text:0000000000002E0D
__text:0000000000002E0D loc_2E0D: ; CODE XREF: AppleEmbeddedOSSupportHostClient::registerNotificationPort(ipc_port *,uint,uint)+17j
__text:0000000000002E0D mov [rbx+0E8h], r14
__text:0000000000002E14 xor eax, eax
__text:0000000000002E16 pop rbx
__text:0000000000002E17 pop r14
__text:0000000000002E19 pop rbp
__text:0000000000002E1A retn

The IOUserClient superclass doesn't implement any locking for this method; it's up to the user client itself to correctly prevent
dangerous concurrent accesses.

By calling registerNotificationPort in two threads in parallel we can cause a AppleEmbeddedOSSupportHostClient to drop two references on a port when
it only holds one.

Note that AppleEmbeddedOSSupportHostClient is only reachable by root so this is a root -> kernel priv esc.

Repro like this: while true; do ./embedded_host; done

Please test on a machine which has a touchbar!
> kextstat | grep AppleEmbeddedOSSupport
should display something if it does.
*/

// ianbeer
#if 0
MacOS kernel uaf due to lack of locking in AppleEmbeddedOSSupportHostClient::registerNotificationPort

AppleEmbeddedOSSupportHost.kext is presumably involved in the communication with the OS running on the touch bar on new MBP models.

Here's the userclient's registerNotificationPort method:

__text:0000000000002DE4 ; AppleEmbeddedOSSupportHostClient::registerNotificationPort(ipc_port *, unsigned int, unsigned int)
__text:0000000000002DE4 push rbp
__text:0000000000002DE5 mov rbp, rsp
__text:0000000000002DE8 push r14
__text:0000000000002DEA push rbx
__text:0000000000002DEB mov r14, rsi
__text:0000000000002DEE mov rbx, rdi
__text:0000000000002DF1 mov rdi, [rbx+0E8h]
__text:0000000000002DF8 test rdi, rdi
__text:0000000000002DFB jz short loc_2E0D
__text:0000000000002DFD call __ZN12IOUserClient23releaseNotificationPortEP8ipc_port ; IOUserClient::releaseNotificationPort(ipc_port *)
__text:0000000000002E02 mov qword ptr [rbx+0E8h], 0
__text:0000000000002E0D
__text:0000000000002E0D loc_2E0D: ; CODE XREF: AppleEmbeddedOSSupportHostClient::registerNotificationPort(ipc_port *,uint,uint)+17j
__text:0000000000002E0D mov [rbx+0E8h], r14
__text:0000000000002E14 xor eax, eax
__text:0000000000002E16 pop rbx
__text:0000000000002E17 pop r14
__text:0000000000002E19 pop rbp
__text:0000000000002E1A retn

The IOUserClient superclass doesn't implement any locking for this method; it's up to the user client itself to correctly prevent
dangerous concurrent accesses.

By calling registerNotificationPort in two threads in parallel we can cause a AppleEmbeddedOSSupportHostClient to drop two references on a port when
it only holds one.

Note that AppleEmbeddedOSSupportHostClient is only reachable by root so this is a root -> kernel priv esc.

Repro like this: while true; do ./embedded_host; done

Please test on a machine which has a touchbar!
> kextstat | grep AppleEmbeddedOSSupport
should display something if it does.
Related Posts