Skip to content

Commit e102f96

Browse files
committed
address backwards compatibility
1 parent cf32187 commit e102f96

File tree

3 files changed

+101
-46
lines changed

3 files changed

+101
-46
lines changed

Crashlytics/Crashlytics/Components/FIRCLSContext.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@
185185
_firclsContext.readonly->machException.path =
186186
FIRCLSContextAppendToRoot(rootPath, FIRCLSReportMachExceptionFile);
187187

188+
// MacOS12 below does not support identity protected behavior
189+
// check releases here: https://opensource.apple.com/releases/
190+
// TODO: remove EXCEPTION_DEFAULT support when we bump min MacOS support to 12+
191+
_firclsContext.readonly->machException.behavior = EXCEPTION_DEFAULT;
192+
if (@available(macOS 12, *)) {
193+
_firclsContext.readonly->machException.behavior = EXCEPTION_IDENTITY_PROTECTED;
194+
}
188195
FIRCLSMachExceptionInit(&_firclsContext.readonly->machException);
189196
});
190197
#endif

Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c

Lines changed: 74 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,19 @@
3333
static void* FIRCLSMachExceptionServer(void* argument);
3434
static bool FIRCLSMachExceptionThreadStart(FIRCLSMachExceptionReadContext* context);
3535
static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context,
36-
MachExceptionProtectedMessage* message);
36+
union MachExceptionMessage* message);
3737
static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context,
38-
MachExceptionProtectedMessage* message);
38+
union MachExceptionMessage* message);
3939
static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context,
40-
MachExceptionProtectedMessage* message,
40+
union MachExceptionMessage* message,
4141
kern_return_t result);
4242
static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context);
4343
static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts,
44-
exception_mask_t mask);
44+
exception_mask_t mask,
45+
exception_behavior_t behavior);
4546
static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
46-
MachExceptionProtectedMessage* message);
47-
static void FIRCLSCrashedThreadLookup(MachExceptionProtectedMessage* message, thread_t* crashedThread);
47+
union MachExceptionMessage* message);
48+
static void FIRCLSCrashedThreadLookup(union MachExceptionMessage* message, thread_t* crashedThread);
4849
#pragma mark - Initialization
4950
void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context) {
5051
if (!FIRCLSUnlinkIfExists(context->path)) {
@@ -58,7 +59,7 @@ void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context) {
5859

5960
if (!FIRCLSMachExceptionThreadStart(context)) {
6061
FIRCLSSDKLog("Unable to start thread\n");
61-
FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask);
62+
FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask, context->behavior);
6263
}
6364
}
6465

@@ -166,7 +167,7 @@ static void* FIRCLSMachExceptionServer(void* argument) {
166167
pthread_setname_np("com.google.firebase.crashlytics.MachExceptionServer");
167168

168169
while (1) {
169-
MachExceptionProtectedMessage message;
170+
union MachExceptionMessage message;
170171

171172
// read the exception message
172173
if (!FIRCLSMachExceptionReadMessage(context, &message)) {
@@ -187,14 +188,17 @@ static void* FIRCLSMachExceptionServer(void* argument) {
187188
return NULL;
188189
}
189190

191+
// need to chaneg here
190192
static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context,
191-
MachExceptionProtectedMessage* message) {
193+
union MachExceptionMessage* message) {
192194
mach_msg_return_t r;
193195

194-
memset(message, 0, sizeof(MachExceptionProtectedMessage));
196+
memset(message, 0, sizeof(union MachExceptionMessage));
195197

196-
r = mach_msg(&message->head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(MachExceptionProtectedMessage),
198+
// no need if condition here since head structure for union MachExceptionMessage is the same.
199+
r = mach_msg(&message->default_message.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(union MachExceptionMessage),
197200
context->port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
201+
198202
if (r != MACH_MSG_SUCCESS) {
199203
FIRCLSSDKLog("Error receiving mach_msg (%d)\n", r);
200204
return false;
@@ -205,34 +209,42 @@ static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* conte
205209
return true;
206210
}
207211

212+
// need to change here
208213
static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context,
209-
MachExceptionProtectedMessage* message) {
210-
FIRCLSSDKLog("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n", message->exception,
211-
message->codeCnt, message->codeCnt > 0 ? message->code[0] : -1,
212-
message->codeCnt > 1 ? message->code[1] : -1);
213-
214-
// This will happen if a child process raises an exception, as the exception ports are
215-
// inherited.
216-
mach_port_t actual_port;
214+
union MachExceptionMessage* message) {
217215
kern_return_t kr;
218-
task_id_token_t token = message->task_id_token_t.name;
219-
kr = task_identity_token_get_task_port(token, TASK_FLAVOR_CONTROL, &actual_port);
216+
217+
if (context->behavior == EXCEPTION_DEFAULT) {
218+
if(message->default_message.task.name != mach_task_self()) {
219+
FIRCLSSDKLog("Mach exception task mis-match, returning failure\n");
220+
return KERN_FAILURE;
221+
}
222+
} else {
223+
FIRCLSSDKLog("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n", message->protected_message.exception,
224+
message->protected_message.codeCnt, message->protected_message.codeCnt > 0 ? message->protected_message.code[0] : -1,
225+
message->protected_message.codeCnt > 1 ? message->protected_message.code[1] : -1);
220226

221-
if (kr != KERN_SUCCESS) {
222-
FIRCLSSDKLog("Could not find task from task id token. returning failure\n");
223-
return KERN_FAILURE;
224-
}
227+
// This will happen if a child process raises an exception, as the exception ports are
228+
// inherited.
229+
mach_port_t actual_port;
230+
task_id_token_t token = message->protected_message.task_id_token_t.name;
231+
kr = task_identity_token_get_task_port(token, TASK_FLAVOR_CONTROL, &actual_port);
225232

226-
const bool is_mismatch = (actual_port != mach_task_self());
227-
mach_port_deallocate(mach_task_self(), actual_port);
233+
if (kr != KERN_SUCCESS) {
234+
FIRCLSSDKLog("Could not find task from task id token. returning failure\n");
235+
return KERN_FAILURE;
236+
}
237+
const bool is_mismatch = (actual_port != mach_task_self());
238+
mach_port_deallocate(mach_task_self(), actual_port);
228239

229-
if (is_mismatch) {
230-
FIRCLSSDKLog("Mach exception task mis-match, returning failure\n");
231-
return KERN_FAILURE;
240+
if (is_mismatch) {
241+
FIRCLSSDKLog("Mach exception task mis-match, returning failure\n");
242+
return KERN_FAILURE;
243+
}
232244
}
233245

234246
FIRCLSSDKLog("Unregistering handler\n");
235-
if (!FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask)) {
247+
if (!FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask, context->behavior)) {
236248
FIRCLSSDKLog("Failed to unregister\n");
237249
return KERN_FAILURE;
238250
}
@@ -253,17 +265,17 @@ static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadC
253265
}
254266

255267
static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context,
256-
MachExceptionProtectedMessage* message,
268+
union MachExceptionMessage* message,
257269
kern_return_t result) {
258270
MachExceptionReply reply;
259271
mach_msg_return_t r;
260272

261273
// prepare the reply
262-
reply.head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(message->head.msgh_bits), 0);
263-
reply.head.msgh_remote_port = message->head.msgh_remote_port;
274+
reply.head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(message->default_message.head.msgh_bits), 0);
275+
reply.head.msgh_remote_port = message->default_message.head.msgh_remote_port;
264276
reply.head.msgh_size = (mach_msg_size_t)sizeof(MachExceptionReply);
265277
reply.head.msgh_local_port = MACH_PORT_NULL;
266-
reply.head.msgh_id = message->head.msgh_id + 100;
278+
reply.head.msgh_id = message->default_message.head.msgh_id + 100;
267279

268280
reply.NDR = NDR_record;
269281

@@ -309,7 +321,7 @@ static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context)
309321

310322
// ORing with MACH_EXCEPTION_CODES will produce 64-bit exception data
311323
kr = task_swap_exception_ports(task, context->mask, context->port,
312-
EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES, THREAD_STATE_NONE,
324+
context->behavior | MACH_EXCEPTION_CODES, THREAD_STATE_NONE,
313325
context->originalPorts.masks, &context->originalPorts.count,
314326
context->originalPorts.ports, context->originalPorts.behaviors,
315327
context->originalPorts.flavors);
@@ -328,7 +340,8 @@ static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context)
328340
}
329341

330342
static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts,
331-
exception_mask_t mask) {
343+
exception_mask_t mask,
344+
exception_behavior_t behavior) {
332345
kern_return_t kr;
333346

334347
// Re-register all the old ports.
@@ -346,7 +359,7 @@ static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* orig
346359

347360
// Finally, mark any masks we registered for that do not have an original port as unused.
348361
kr = task_set_exception_ports(mach_task_self(), mask, MACH_PORT_NULL,
349-
EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
362+
behavior | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
350363
if (kr != KERN_SUCCESS) {
351364
FIRCLSSDKLog("unable to unset unregistered mask: 0x%x", mask);
352365
return false;
@@ -485,7 +498,7 @@ void FIRCLSMachExceptionNameLookup(exception_type_t number,
485498
}
486499

487500
static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
488-
MachExceptionProtectedMessage* message) {
501+
union MachExceptionMessage* message) {
489502
if (!context || !message) {
490503
return false;
491504
}
@@ -507,21 +520,36 @@ static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
507520

508521
FIRCLSFileWriteHashStart(&file);
509522

510-
FIRCLSFileWriteHashEntryUint64(&file, "exception", message->exception);
523+
if (context->behavior == EXCEPTION_DEFAULT) {
524+
FIRCLSFileWriteHashEntryUint64(&file, "exception", message->default_message.exception);
525+
} else {
526+
FIRCLSFileWriteHashEntryUint64(&file, "exception", message->protected_message.exception);
527+
}
511528

512529
// record the codes
513530
FIRCLSFileWriteHashKey(&file, "codes");
514531
FIRCLSFileWriteArrayStart(&file);
515-
for (mach_msg_type_number_t i = 0; i < message->codeCnt; ++i) {
516-
FIRCLSFileWriteArrayEntryUint64(&file, message->code[i]);
532+
if (context->behavior == EXCEPTION_DEFAULT) {
533+
for (mach_msg_type_number_t i = 0; i < message->default_message.codeCnt; ++i) {
534+
FIRCLSFileWriteArrayEntryUint64(&file, message->default_message.code[i]);
535+
}
536+
} else {
537+
for (mach_msg_type_number_t i = 0; i < message->protected_message.codeCnt; ++i) {
538+
FIRCLSFileWriteArrayEntryUint64(&file, message->protected_message.code[i]);
539+
}
517540
}
518541
FIRCLSFileWriteArrayEnd(&file);
519542

520543
const char* name = NULL;
521544
const char* codeName = NULL;
522545

523-
FIRCLSMachExceptionNameLookup(message->exception, message->codeCnt > 0 ? message->code[0] : 0,
524-
&name, &codeName);
546+
if (context->behavior == EXCEPTION_DEFAULT) {
547+
FIRCLSMachExceptionNameLookup(message->default_message.exception, message->default_message.codeCnt > 0 ? message->default_message.code[0] : 0,
548+
&name, &codeName);
549+
} else {
550+
FIRCLSMachExceptionNameLookup(message->protected_message.exception, message->protected_message.codeCnt > 0 ? message->protected_message.code[0] : 0,
551+
&name, &codeName);
552+
}
525553

526554
FIRCLSFileWriteHashEntryString(&file, "name", name);
527555
FIRCLSFileWriteHashEntryString(&file, "code_name", codeName);
@@ -545,7 +573,7 @@ static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
545573
return true;
546574
}
547575

548-
static void FIRCLSCrashedThreadLookup(MachExceptionProtectedMessage* message, thread_t* crashedThread) {
576+
static void FIRCLSCrashedThreadLookup(union MachExceptionMessage* message, thread_t* crashedThread) {
549577
thread_act_array_t threadList;
550578
mach_msg_type_number_t threadCount;
551579

@@ -564,7 +592,7 @@ static void FIRCLSCrashedThreadLookup(MachExceptionProtectedMessage* message, th
564592

565593
if (kr == KERN_SUCCESS) {
566594
FIRCLSSDKLog("Thread %d: Thread port: %d, thread id: %llx\n", i, threadList[i], identifierInfo.thread_id);
567-
if (message->thread_id == identifierInfo.thread_id) {
595+
if (message->protected_message.thread_id == identifierInfo.thread_id) {
568596
FIRCLSSDKLog("Find crashed thread: %d\n", threadList[i]);
569597
*crashedThread = threadList[i];
570598
break;

Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ typedef struct {
4343
mach_msg_trailer_t trailer;
4444
} MachExceptionProtectedMessage;
4545

46+
typedef struct {
47+
mach_msg_header_t head;
48+
/* start of the kernel processed data */
49+
mach_msg_body_t msgh_body;
50+
mach_msg_port_descriptor_t thread;
51+
mach_msg_port_descriptor_t task;
52+
/* end of the kernel processed data */
53+
NDR_record_t NDR;
54+
exception_type_t exception;
55+
mach_msg_type_number_t codeCnt;
56+
mach_exception_data_type_t code[EXCEPTION_CODE_MAX];
57+
mach_msg_trailer_t trailer;
58+
} MachExceptionDefaultMessage;
59+
60+
union MachExceptionMessage {
61+
MachExceptionProtectedMessage protected_message;
62+
MachExceptionDefaultMessage default_message;
63+
};
64+
4665
typedef struct {
4766
mach_msg_header_t head;
4867
NDR_record_t NDR;
@@ -65,6 +84,7 @@ typedef struct {
6584

6685
exception_mask_t mask;
6786
FIRCLSMachExceptionOriginalPorts originalPorts;
87+
exception_behavior_t behavior;
6888
} FIRCLSMachExceptionReadContext;
6989

7090
#pragma mark - API

0 commit comments

Comments
 (0)