Synchronizing data between an System Extension and Container App

I'm building a macOS application with an Endpoint Security System Extension.

I expect the system extension to always be running (i.e. it's effectively a daemon). My extension will gather information about processes and make that data available to the container app.

The container app is a UI app and won't always be running. This means that I can't send data from the system extension at an arbitrary time.

As far as I understand it, if I ship a macOS app in the App Store then I can't have a launch agent/daemon.

I'm looking for a good way/the recommended way to solve this problem.

Some specific thoughts/questions:

  • Is it indeed the case that for an App Store app there's no way to create anything like a daemon?
  • Do System Extensions always run as root? I couldn't see anything explicitly in the docs about this. However, given its effectively a daemon that would make sense.
  • I believe using App Groups could be a solution. Specifically, I can just write data to a file in the Sys Ext and have the container app asynchronously pick that up later. However, since the Sys Ext is running as root, that app group will appear in a system folder and I'm not clear that the container app will actually be able to access that.
  • XPC should be a solution, but then I have to put a lot more business logic in the Sys Ext. Specifically, the Sys Ext will need to keep track of what data has been sent to the Container App. Not a huge issue, but I was hoping to make my Sys Ext as dumb as possible.

Longer term, I'd like to make the Sys Ext be interactive rather then just informative. In the language of the API that would mean an auth approach rather than a notify approach. Specifically, I want the user to be alerted when certain processes start and have the choice to block/allow those processes.

This necessitates the Sys Ext somehow being able to alert the user. If the Container App isn't open then I guess I can send a local notification? Is that the only approach? Is there another way to handle this situation?

Hmmm, I think you’re confused here. You wrote:

I'm building a macOS application with an Endpoint Security System Extension.

… if I ship a macOS app in the App Store

You can’t ship an ES sysex in the Mac App Store. Currently the Mac App Store only supports NE, DriverKit, and CMIO sysexes.

Is it indeed the case that for an App Store app there's no way to create anything like a daemon?

A sysex is effectively a daemon, but you are correct that there’s no way to ship a launchd daemon per se in the Mac App Store.

Do System Extensions always run as root?

Yes.

I believe using App Groups could be a solution.

No. App groups let you share data between multiple apps run by the same user, but your sysex and its container app are run by different users (root and one of the logged in GUI users).

If the Container App isn't open then I guess I can send a local notification?

Doing that is going to be tricky. Which local user are expecting to notify here? You can have more than one logged into the GUI. And you can also have zero logged into the GUI.

My general advice in this front is that you run an agent in each GUI login session so those can work with the daemon to decide who is the best person to notify. I go into this more in Technote 2083 Daemons and Agents (it’s in desperate need of an update, but most of the fundamentals are still OK).

Share and Enjoy

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

You can’t ship an ES sysex in the Mac App Store. Currently the Mac App Store only supports NE, DriverKit, and CMIO sysexes.

Ah interesting. I hadn't spotted that. I assumed that the move away from kexts would mean that ES's could be shipped in the store. That doesn't really change a lot for me. I guess it means I could use a launchd agent/daemon, but I'd rather code for the future and assume that maybe one day I can publish it and thus such things would be disallowed.

No. App groups let you share data between multiple apps run by the same user, but your sysex and its container app are run by different users (root and one of the logged in GUI users).

Yeah, I figured this out with a bit more poking. Clearly not a solution.

Doing that is going to be tricky. Which local user are expecting to notify here? You can have more than one logged into the GUI. And you can also have zero logged into the GUI.

That was useful rubber ducking. It's obvious to me now what the problem is.

My general advice in this front is that you run an agent in each GUI login session so those can work with the daemon to decide who is the best person to notify.

The problem for me is that agents are not allowed in the app store. I appreciate that ES apps are also not allowed - so that's kind of a moot point - but as per above I'd like to design my app to be future proof. I'd also like to understand how to handle this for App Store apps as a useful learning exercise e.g. assume I were building a NE, DriverKit, or CMIO and had the same requirements.

As far as I can see it. If I can't use agents or daemons then my solution would be:

  • 3 Bundles: Client (UI) App (the main container app), ES Sys Ext, XPC Service
  • Sys Ext always running in the background. This connects to the XPC service on startup and waits to hear from the client app.
  • User opens the client app which connects to the XPC.
  • The Sys Ext syncs data with the Client App as needed

As far as I can see this still precludes the possibility of me alerting the user to something if the Client App isn't running.

Questions:

  • Am I right in thinking the above solution is my only/best option if I assume no agents/daemons?
  • Is there any way to solve the alerting problem when the app is shut?
  • Am I making my life too complicated? Would you recommend just using an agent?

Separately, I'm having problems getting the XPC working. My container app can connect to it but my service can't. I'll post that as a separate question though as it's getting out of scope.

Thanks for the quick answers and all the info btw!

Synchronizing data between an System Extension and Container App
 
 
Q