macOS Network Extension deactivation fails with authorizationRequired

Hello,

I have a .app that runs as LaunchDaemon and configured to be an Agent (LSUIElement) that is stored in /Applications.

Installing network extensions works, but deactivation fails with OSSystemExtensionErrorDomain error 13 (authorization required).

requestNeedsUserApproval is not called for deactivation, but it's called when being activated.

Any ideas? Thank you!

P.S. It works on Debug, just not on Release...

Answered by DTS Engineer in 871284022
I have to add that the daemon is a NSApplication.

Hmmm, that’s not good. A launchd daemon runs in the global execution context. Code running in that context cannot safely use GUI frameworks like AppKit. It’s only safe to use GUI frameworks from a GUI user login context.

There’s a detailed description of this architecture in TN2083 Daemons and Agents. It’s super old, and there are a few areas where it’s suffering from bit rot, but the big picture stuff is still completely valid.

If you break these rules you will run into all sorts of weird problems. Some of them show up immediately, and some of them lurk, waiting to cause you grief as the system evolves. Given that, I strongly recommend that you move away from this design.


Coming back to System Extensions framework, it’s intended to be used by a GUI app to load and unload system extensions in response to user actions. Calling it from the global execution context, like your launchd daemon, is not supported.

Share and Enjoy

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

I have a .app that runs as LaunchDaemon and configured to be an Agent (LSUIElement) that is stored in /Applications.

Wow, that’s quite a combo. Lemme see if I understand this correctly:

  • You have a launchd daemon.
  • That’s embedded in an app-like wrapper.
  • Its Info.plist contains LSUIElement.
  • Presumably because the daemon displays UI.
  • And the daemon is run via a launchd property list in /Library/LaunchDaemons.

Is that right?

Share and Enjoy

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

Thanks for the reply!

You have a launchd daemon. ✅

That’s embedded in an app-like wrapper. ✅

Its Info.plist contains LSUIElement. ✅

Presumably because the daemon displays UI. ✅

And the daemon is run via a launchd property list in /Library/LaunchDaemons. ✅

I have to add that the daemon is a NSApplication.

Bonus, in order to clarify further:

  • this is an application created with "Application" -> "App" target
  • configured with LSUIElement so that it's not displayed to the user
  • I created a .plist and added to /Library/LaunchDaemons and then ran the commands to bootstrap the daemon
  • it also bundles NetworkExtensions and has the required entitlenments to install them (and my setup works for installation)
I have to add that the daemon is a NSApplication.

Hmmm, that’s not good. A launchd daemon runs in the global execution context. Code running in that context cannot safely use GUI frameworks like AppKit. It’s only safe to use GUI frameworks from a GUI user login context.

There’s a detailed description of this architecture in TN2083 Daemons and Agents. It’s super old, and there are a few areas where it’s suffering from bit rot, but the big picture stuff is still completely valid.

If you break these rules you will run into all sorts of weird problems. Some of them show up immediately, and some of them lurk, waiting to cause you grief as the system evolves. Given that, I strongly recommend that you move away from this design.


Coming back to System Extensions framework, it’s intended to be used by a GUI app to load and unload system extensions in response to user actions. Calling it from the global execution context, like your launchd daemon, is not supported.

Share and Enjoy

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

macOS Network Extension deactivation fails with authorizationRequired
 
 
Q