Hello, I am having some issues with running an XPC server on an endpoint security and connecting to it from the sandboxed host application.
I tried doing the following:
setting xpc server in endpoint security extension entitlements:
<key>com.apple.developer.endpoint-security.client</key>
<true/>
<key>com.apple.security.xpc.server</key>
<true/>
Adding the mach service with the plist:
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.system-extension-endpoint-security</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ESFExtension</string>
</dict>
<key>NSEndpointSecurityMachServiceName</key>
<string>[TEAMID]com.[UNIQUE_ID]</string>
</dict>
</plist>
Putting a mach-lookup in sandboxed host application entitlements
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.security.exception.mach-lookup.global-name</key>
<array>
<string>[TEAMID]com.[UNIQUE_ID]</string>
</array>
</dict>
Creating the server in the system extension using xpc_connection_create_mach_service(_service_name.c_str(), dispatch_get_main_queue(), XPC_CONNECTION_MACH_SERVICE_LISTENER);
with _service_name
being the same as in the mach-lookup
entitlement.
And connecting to it in the host app with:
xpc_connection_create_mach_service([self.serviceName UTF8String], dispatch_get_main_queue(), 0);
My problem is I get an xpc error 159 (sandbox restriction) in the lookup
(libxpc.dylib) [com.apple.xpc:connection] [0x600001a7db30] failed to do a bootstrap look-up: xpc_error=[159: Unknown error: 159]
I tried putting the sysex and the host app in the same app group, and it didn't help and I also read this is bad practice to have an app group between a sandboxed app and a system extension so I removed it.
I tried adding a temporary-exception
and with it, the code works properly.
I tried with the XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
flag but it still didn't work.
Is it possible to have an XPC connection between a ES sysex and it's host app? Should the service name have a prefix of the bundle name or does it must have a certain pattern? Do I need to add some capability in the Certificates, Identifiers & Profiles?
Thanks for helping.
First up, terminology. When talking about extensions on Apple platforms:
-
The container application is the application in which the extension is embedded.
-
The host application is the app uses the extension.
In the case of an ES sysex, the host application is the system itself.
It seems like you’re trying to sandbox your container app. That’s pretty rare, because the ES sysex itself can’t be sandboxed and thus ES clients can’t be distributed on the Mac App Store. The simplest option here would be to not sandbox your container app.
Beyond that, your description of how your ES sysex is constructed highlights a couple of oddities:
-
I’m not sure what you’re expecting
com.apple.security.xpc.server
to do, but it’s not a known entitlement and thus won’t do anything useful [1]. -
NSExtensionPrincipalClass
doesn’t make sense for an ES sysex because they don’t use Objective-C.
I tried with the XPC_CONNECTION_MACH_SERVICE_PRIVILEGED flag but it still didn't work.
You should set this flag because it prevents some other program in the GUI login session namespace from spoofing your named XPC endpoint. However, it applies more restrictions, so it’s fine to leave it off during the initial bring up.
I tried putting the sysex and the host app in the same app group …
Right. This is a common path forward.
The issue you’re having here is that the App Sandox is blocking the container app from connecting to the named XPC endpoint. There are three standard ways around this:
-
Disable App sandbox.
-
Punch a whole through the sandbox using a temporary exception entitlement.
-
Prefix the named XPC endpoint with an app group ID. The App Sandbox will not block connections to
x.y.z
if your app has access to the app groupx.y
.
I also read this is bad practice to have an app group between a sandboxed app and a system extension so I removed it.
You need to distinguish between app group IDs and app group containers. You can’t share an app group container between your container app and your ES sysex because they run as different users (the logged in user and root, respectively) and thus get different container paths.
It’s perfectly reasonable to share an app group ID between the two.
Note, however, that App Groups are tricky on macOS. App Groups: macOS vs iOS: Working Towards Harmony has all the details, but I suspect you’ll be OK because you’re building an ES sysex (rather than a daemon) and are working with modern tools.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] You’re lucky this is in the com.apple.security.
namespace, making it an unrestricted entitlement. See TN3125 Inside Code Signing: Provisioning Profiles for a definition of that term. If it were in any other namespace it’d block the process from launching.