I've got this chunk of code that calls AuthorizationExecuteWithPrivileges(). So far I've seen 5 crashes all with the same stack trace, all running as 64-bit on 10.6.x, but unreproducible on my end:
Now 5 crashes isn't really that much, since this code runs every single time on launch of the app, for every architecture supported on 10.4 and up, so I'm not overly concerned with it, but I'm guessing that there is some memory corruption going on.
I've been staring at this code all morning and am going a little crazy. The one idea I have is the call to calloc which *should* properly separate the count and size arguments instead of combining them like a call to malloc. However, would this really make a difference? The only thing I can think of is separating them might help prevent overflows but in this specific situation there is only 1 argument so that shouldn't apply.
Any other ideas?
Code:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000001029e77fe
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libSystem.B.dylib 0x00007fff8725cf6b small_malloc_from_free_list + 912
1 libSystem.B.dylib 0x00007fff87259741 szone_malloc_should_clear + 2070
2 libSystem.B.dylib 0x00007fff87258eea malloc_zone_malloc + 82
3 libSystem.B.dylib 0x00007fff872571e8 malloc + 44
4 libSystem.B.dylib 0x00007fff8726e7f2 _pthread_work_internal_init + 180
5 libSystem.B.dylib 0x00007fff87330231 pthread_workqueue_atfork_child + 39
6 libSystem.B.dylib 0x00007fff87318ebc _cthread_fork_child + 180
7 libSystem.B.dylib 0x00007fff872b8923 fork + 83
8 com.mycompany.myapp 0x000000010004d648 AuthorizationExecuteWithPrivileges
...
Code:
+ ([color=#5c2699]OSStatus[/color])launchAuthorizedTaskForPath:([color=#5c2699]NSString[/color] *)taskPath arguments:([color=#5c2699]NSArray[/color] *)arguments output:([color=#5c2699]NSString[/color] **)output
{
[color=#aa0d91]if[/color] (!taskPath || ![[[color=#5c2699]NSFileManager[/color] [color=#2e0d6e]defaultManager[/color]] [color=#2e0d6e]fileExistsAtPath[/color]:taskPath])
[color=#aa0d91]return[/color] [color=#2e0d6e]errAuthorizationToolExecuteFailure[/color];
[color=#5c2699]AuthorizationRef[/color] authorizationRef = [color=#aa0d91]NULL[/color];
[color=#5c2699]OSStatus[/color] status = [color=#2e0d6e]AuthorizationCreate[/color]([color=#aa0d91]NULL[/color], [color=#643820]kAuthorizationEmptyEnvironment[/color], [color=#2e0d6e]kAuthorizationFlagDefaults[/color], &authorizationRef);
[color=#aa0d91]if[/color] (status != [color=#2e0d6e]errAuthorizationSuccess[/color])
[color=#aa0d91]return[/color] status;
[color=#aa0d91]const[/color] [color=#aa0d91]char[/color] *path = [taskPath [color=#2e0d6e]fileSystemRepresentation[/color]];
[color=#5c2699]AuthorizationItem[/color] right = {[color=#643820]kAuthorizationRightExecute[/color], [color=#2e0d6e]strlen[/color](path), ([color=#aa0d91]void[/color] *)path, [color=#2e0d6e]kAuthorizationFlagDefaults[/color]};
[color=#5c2699]AuthorizationRights[/color] rightSet = {[color=#1c00cf]1[/color], &right};
[color=#5c2699]AuthorizationFlags[/color] flags = [color=#2e0d6e]kAuthorizationFlagDefaults[/color] | [color=#2e0d6e]kAuthorizationFlagPreAuthorize[/color] | [color=#2e0d6e]kAuthorizationFlagInteractionAllowed[/color] | [color=#2e0d6e]kAuthorizationFlagExtendRights[/color];
status = [color=#2e0d6e]AuthorizationCopyRights[/color](authorizationRef, &rightSet, [color=#643820]kAuthorizationEmptyEnvironment[/color], flags, [color=#aa0d91]NULL[/color]);
[color=#aa0d91]if[/color] (status != [color=#2e0d6e]errAuthorizationSuccess[/color])
{
[color=#2e0d6e]AuthorizationFree[/color](authorizationRef, [color=#2e0d6e]kAuthorizationFlagDestroyRights[/color]);
[color=#aa0d91]return[/color] status;
}
[color=#aa0d91]char[/color] **args = [color=#aa0d91]NULL[/color];
[color=#aa0d91]if[/color] ((arguments != [color=#aa0d91]nil[/color]) && ([arguments [color=#2e0d6e]count[/color]] > [color=#1c00cf]0[/color]))
{
args = [color=#2e0d6e]calloc[/color]([color=#1c00cf]1[/color], [color=#aa0d91]sizeof[/color]([color=#aa0d91]char[/color]*) * ([arguments [color=#2e0d6e]count[/color]] + [color=#1c00cf]1[/color]));
[color=#3f6e74]NSUInteger[/color] i=[color=#1c00cf]0[/color];
[color=#aa0d91]for[/color] (i=[color=#1c00cf]0[/color]; i<[arguments [color=#2e0d6e]count[/color]]; i++)
{
[color=#5c2699]NSString[/color] *arg = [arguments [color=#2e0d6e]objectAtIndex[/color]:i];
[color=#aa0d91]if[/color] ([arg [color=#2e0d6e]isKindOfClass[/color]:[[color=#5c2699]NSString[/color] [color=#2e0d6e]class[/color]]])
args[i] = ([color=#aa0d91]char[/color] *)[arg UTF8String];
}
}
[color=#5c2699]FILE[/color] *file = [color=#aa0d91]NULL[/color];
status = [color=#2e0d6e]AuthorizationExecuteWithPrivileges[/color](authorizationRef, path, [color=#2e0d6e]kAuthorizationFlagDefaults[/color], args, (output != [color=#aa0d91]NULL[/color] ? &file : [color=#aa0d91]NULL[/color]));
...
Now 5 crashes isn't really that much, since this code runs every single time on launch of the app, for every architecture supported on 10.4 and up, so I'm not overly concerned with it, but I'm guessing that there is some memory corruption going on.
I've been staring at this code all morning and am going a little crazy. The one idea I have is the call to calloc which *should* properly separate the count and size arguments instead of combining them like a call to malloc. However, would this really make a difference? The only thing I can think of is separating them might help prevent overflows but in this specific situation there is only 1 argument so that shouldn't apply.
Any other ideas?
Last edited: