`listener failed to activate: xpc_error=[1: Operation not permitted]`

Hi 👋

I started a new project to experiment with EndpointSecurity framework.

It seems to have been worked, but when I try to add XPC I face some troubles.

I am not able to send XPC message from my app to my system extension.

No runtime error, but when I'm inspecting logs:

That correspond to this code: https://github.com/tony-go/TestES/blob/main/Extension/main.swift#L21-L30

Full project: https://github.com/tony-go/TestES/

I thought at first that it could come from a missing @objc somehere but it does not seems ...

I also wonder why I cannot catch this error at runtime ?

Answered by DTS Engineer in 788934022

System extensions are very like launchd daemons but they are not launchd daemons. One place where they differ is in how you name your XPC endpoints. For an ES sysex, you should use NSEndpointSecurityMachServiceName. See the EndpointSecurity man page for the details.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

System extensions are very like launchd daemons but they are not launchd daemons. One place where they differ is in how you name your XPC endpoints. For an ES sysex, you should use NSEndpointSecurityMachServiceName. See the EndpointSecurity man page for the details.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hey Eskimo 👋

Really happy to see your answer.

I updated my info.plist: https://github.com/tony-go/TestES/commit/eda07758c37654fe7f428fb53689315ee221c4a6

But I still have the same error :/

I took a deeper look at logs, ans see these error logs:

Impossible to know if they are realted or not. I should investigate on my side.

That new error is likely going to return is your es_new_client call returning ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

That new error is likely going to return is your es_new_client call returning ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED.

Hmm it seems that at this point es_new_client is not even called.

Basically the extension resume the NSXPCListener, and expose a start function for the main app.

Then the main app send a message that should start the ES client.

It looks like the listenner does not even react to the message sent by the main app.

I dug a bit more and when I explictly call the start function I exposed, I have (Call start is my app log`)

We clearly see libxpc claiming:

[0x13be058c0] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()

So there is another issue with my XPC connection at some points.

it seems that at this point es_new_client is not even called.

Well, my advice is that you not try to debug your XPC stuff until you have the ES basics working.

Then the main app send a message that should start the ES client.

That doesn’t make sense. An ES client is a system extension that doesn’t launch on demand. Rather, the system launches when you successfully activate it (and also on each restart).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Well, my advice is that you not try to debug your XPC stuff until you have the ES basics working.

I had one on that commit: https://github.com/tony-go/TestES/commit/26d13577e96f7d2af4f00c4a26e2d0035212612b

This logged appeared: https://github.com/tony-go/TestES/commit/26d13577e96f7d2af4f00c4a26e2d0035212612b#diff-ce8a6f64bfbfec9d1d2a908e35f81afeae2cae4d09f5a318c61e7d64b68b3a83R27

Then I tried to add XPC above it.


That doesn’t make sense. An ES client is a system extension that doesn’t launch on demand. Rather, the system launches when you successfully activate it (and also on each restart).

Okay so the system launch it and the client should be created at this moment. My initial concern was if I had to send messages from the main App, I would like to be sure that the client is working. But my appraoch was wrong. Thanks :)

So the next things to do is:

  • Start the ES client direclty
  • Expose a isExtensionRunning or something like that
  • Use XPC message for pure business logic.

Sounds good?

I did not resolved the bug we had (but at least it avoided to do wrong stuff).

Now I try to go back to the first logs I got:

debug	14:25:16.056727+0200	TestES	SystemExtensionInstaller - Install extension...
default	14:53:35.302403+0200	TestES	[0x600003ce0000] activating connection: mach=true listener=false peer=false name=com.apple.sysextd

...

default	14:53:35.312582+0200	TestES	[0x120756c90] activating connection: mach=false listener=false peer=false name=(anonymous)
default	14:53:35.312657+0200	TestES	[0x600003ce0000] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()

....

default	14:53:35.312657+0200	TestES	[0x600003ce0000] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()


....

debug	14:53:35.439389+0200	TestES	SystemExtensionInstaller - didFinishWithResult: 0

SystemExtensionInstaller - * are my logs.

So I'm not even sur that other logs are related to my xpc listenner as these messages happen during extension installation.

But what Im sure is that later, when the extension is installed and that the XPCClient has established the conneciton I saw:

debug	14:53:46.575298+0200	TestES	Call start
default	14:53:46.576719+0200	tonygo.TestES.Extension	[0x14c604b00] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
default	14:53:46.577816+0200	TestES	[0x121a0a870] Re-initialization successful; calling out to event handler with XPC_ERROR_CONNECTION_INTERRUPTED
default	14:53:46.577229+0200	tonygo.TestES.Extension	[0x14c604b00] activating connection: mach=false listener=false peer=true name=tonygo.TestES-group.xpc.peer[18172].0x14c604b00
error	14:53:46.577939+0200	TestES	Remote process crashed or exited! (Catched with `interruptionHandler`)

(First and last lines is my logs)


The funny part is that if I filter to my logs only:

debug	15:15:47.541145+0200	TestES	SystemExtensionInstaller - Install extension...
debug	15:15:47.562760+0200	TestES	SystemExtensionInstaller - request actionForReplacingExtension
debug	15:15:47.657196+0200	TestES	SystemExtensionInstaller - didFinishWithResult: 0
debug	15:15:47.667428+0200	tonygo.TestES.Extension	Starting ES client
debug	15:15:47.669392+0200	tonygo.TestES.Extension	ES client started!
debug	15:15:47.676040+0200	tonygo.TestES.Extension	Resuming XPC Listener
debug	15:15:47.676227+0200	tonygo.TestES.Extension	Resumed
debug	15:15:50.839447+0200	TestES	Establishing IPC Client
debug	15:15:50.840981+0200	TestES	Connection established
debug	15:15:53.668402+0200	TestES	Call ping
error	15:15:53.670891+0200	TestES	Remote process crashed or exited!

All seem to happen in the right order.

I’m not 100% sure what’s going on here but, looking at your project as of today, I have some advice:

  • Remove com.apple.security.automation.apple-events from your sysex entitlements. No good can come from that.

  • Remove com.apple.security.application-groups from your sysex entitlements. That won’t help [1] and can cause problems [2].

  • Put something into NSSystemExtensionUsageDescription. You don’t need a real string, but don’t leave it empty.

Regarding the invalidation handler being called, where are two common causes for that:

  • The remote process did actually crash.

  • The remote process cancelled the XPC connection (in NSXPCConnection that’s done with the -invalidate method).

If it crashed, you should get a crash report. Check for that.

On the invalidation front, I don’t see any obvious flaws in your logic but they are rather had to spot. My advice is that you test your XPC first, in a standalone project, using the technique I explain in TN3113 Testing and debugging XPC code with an anonymous listener.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Because your app and your sysex are running as different users, so a a shared app group container isn’t going to happen. And you don’t need it to authorise your use of the Mach service name because the sysex isn’t sandboxed.

[2] I go into more detail about this in App Groups: macOS vs iOS: Fight!.

Thanks :) @DTS Engineer

So the idea is: no app groups as on the end the extension won't be sandboxed?

But what about the GUI application? It is sandboxed right? I asked because the goal of this research work is to have a boilerplate that would be ready for distribution at least standalone with notarization.

There are changes, you adviced: https://github.com/tony-go/TestES/commit/f5dce4ec3226875d68370fa7cd7819d648ecaba8


debug	11:37:26.013395+0200	TestES	Establishing IPC Client

default	11:37:26.013593+0200	TestES	[0x118005020] activating connection: mach=false listener=false peer=false name=tonygo.TestES.Extension

default	11:37:26.013801+0200	TestES	[0x118005020] failed to do a bootstrap look-up: xpc_error=[3: No such process]

default	11:37:26.013825+0200	TestES	[0x118005020] invalidated after a failed init

error	11:37:26.016406+0200	TestES	Connection has not being established!

So it seems that it is a look up error.

I catched the last one from the invalidationHandler


In parallel, I'll try:

TN3113 .

I did some progress:

  • I realized that there was a memory issue within the sysex.
  • After that I had another message telling that there is look up issue due to Sandbox
  • I disabled sandbox for the main app
  • Now I have another error:
error	10:19:41.751935+0200	TestES	Connection will be invalitaded
default	10:19:41.752088+0200	TestES	[0x14bf04fd0] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
error	10:19:41.755230+0200	TestES	Connection has not being established!
debug	10:19:41.860192+0200	TestES	Call ping
default	10:19:41.861541+0200	tonygo.TestES.Extension	[0x123104100] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
default	10:19:41.861728+0200	tonygo.TestES.Extension	[0x123104100] activating connection: mach=false listener=false peer=true name=com.tonygo.TestES.Extension.peer[39800].0x123104100
default	10:19:41.861886+0200	TestES	[0x14bf04280] Re-initialization successful; calling out to event handler with XPC_ERROR_CONNECTION_INTERRUPTED
error	10:19:41.861974+0200	TestES	Remote process crashed or exited!

So when I send the actual message, the process crashes.

no app groups as on the end the extension won't be sandboxed?

Yes, kinda. There are two common reasons to use an app group:

  • To authorise the use of an IPC primitive in a sandboxed app

  • To access a shared container

Neither is relevant to an ES sysex:

  • An ES sysex isn’t sandboxed, so the first is irrelevant.

  • An ES sysex runs as root, so a shared container is unlikely to be useful because it won’t be shared with the container app, which is running as a logged in GUI user.

But what about the GUI application? It is sandboxed right?

That’s up to you. You can’t ship an ES sysex is the App Store [1], so sandboxing is optional for your container app.

So when I send the actual message, the process crashes.

What does the crash report look like? You can post it here, using the instructions in Posting a Crash Report.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] The App Store requires that all code be sandboxed, and an ES sysex can’t be sandboxed, thus it can’t ship on the App Store.

`listener failed to activate: xpc_error=[1: Operation not permitted]`
 
 
Q