Cocoa Entitlements and EXC_BAD_INSTRUCTION

So I’ve been playing around with Lion sandboxing and using entitlements for a Cocoa app. (In case you didn’t hear, all apps submitted to the App Store have to be sandboxed come this November.) The first thing you may notice when you enable sandboxing for your app in Xcode is that it turns on code signing. It has to do this because entitlements don’t work unless you sign your code. Once code signing is turned on and you try to compile you may get an error:

[BEROR]Code Sign error: The identity '3rd Party Mac Developer Application' doesn't match any valid certificate/private key pair in the default keychain

This because by default Xcode will try to sign your code with an identity in your keychain that starts with 3rd Party Mac Developer Application. To be able to submit apps to the App Store you have to get a certificate from Apple so this is a sane default but I wasn’t signed up of the Mac Developer Program. I was however signed up for the iOS Developer Program so to fix the error for now I changed the Code Signing Identity build setting to iPhone Developer and away I went.

Fast forward a few days after I had signed up for the Mac Developer Program and I got my certificate. So I got rid of my change Code Signing Identity and restored the default. But I soon ran into a problem, my application now crashed while starting up no matter what I changed with a EXC_BAD_INSTRUCTION error in some random Apple code.

I quickly localized the problems to having entitlements on but the non-existance of any documentation on debugging sandbox errors from Apple I was frustrated. So I fired up my application without Xcode so there would be a error trace I could view in Console. This was a great idea because I was actually able to see what was the error was.

What immediately jumped out at me was

Code identity not in ACL for container ~/Library/Containers/org.samuelkadolph.Foo/Data

and I suddenly remembered something I read in the sandbox documentation. By default in the Lion sandbox, you can only access files in a special directory under ~/Library/Containers which is named after the bundle identifier for your app. And it’s protected to prevent someone from accessing the data in there with a fake app. This protection is achieved by using info from the app which was signed by your code signing identity to confirm a genuine app from a fake. So when I changed the keychain identity used to sign the code I was creating a fake app and trying to access the data.

The solution was simple after determining that was the problem. Just delete the container for your app (and only your app, every other sandboxed app has a container too and may store data in them). In my case it was rm -rf ~/Library/Containers/org.samuelkadolph.Foo.

It’s unfortunate that Xcode isn’t more helpful with this error and unfortunate that OS X will kill (with SIGKILL too) an application instead of using some error handling in the app itself. I hope this post helps you if you ever run into this problem.