Unloading a system extension as a launchdaemon

Hello, I've got my system extension loading from my binary which is located in a *.app inside /Applications. I get the proper prompts to allow the system extension to load via System Preferences -> Security when my process is running in the context of a launchdaemon. However when my process attempts to call `deactivationRequestForExtension`, the request fails with "OSSystemExtensionErrorDomain error 13". Looking up this error it seems that it is defined as `OSSystemExtensionErrorAuthorizationRequired`. I also see the following in the Console regarding why this may have failed.


default 14:56:56.581780-0700 opendirectoryd getpwuid failed with result Not Found
error 14:56:56.583919-0700 authd Fatal: interaction not allowed (session has no ui access) (engine 237)
default 14:56:56.583939-0700 authd Failed to authorize right 'com.apple.system-extensions.admin' by client '/Applications/MyApp.app' [40455] for authorization created by '/Applications/MyApp.app' [40455] (3,0) (-60007) (engine 237)
default 14:56:56.584357-0700 MyApp failed to create authref: -60007


Is the deactivation request failing due to a bug in the System Extension framework or is this by design or perhaps I'm doing something wrong? Thanks!

Accepted Reply

The

launchd
daemon is the one that is currently attempting to load and unload the system extension.

Ah, I see. I think that explains your problem. This operation has to be authorised using Authorization Services — from the log snippet you posted, it looks like it requires the

com.apple.system-extensions.admin
authorisation right, although I’ve never dug into that myself — and there’s no way for a daemon to acquire that right because it’s running in a context that can’t present UI.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

I've submitted a bug report FB7458892

I’m somewhat confused by your question. First up, what sort of system extension are you building (EndpointSecurity, NetworkExtension, DriverKit)? Second, if you’re building a system extension, how do

launchd
daemons fit into the picture? Two out of three of our system extension mechanisms are only available via system extensions. The remaining one, EndpointSecurity, can be used from a
launchd
daemon but, in that case, you don’t usually need a system extension at all, so it’s kind of an either/or thing.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I am building a NetworkExtension. The launchd daemon is the one that is currently attempting to load and unload the system extension. Perhaps the .plist will make things a bit more clear


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>MyApp</string>
        <key>ProgramArguments</key>
        <array>
          <string>/Applications/MyApp.app/Contents/MacOS/MyApp</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>UserName</key>
        <string>root</string>
        <key>KeepAlive</key>
        <true/>
        <key>ThrottleInterval</key>
        <integer>5</integer>
        <key>StandardErrorPath</key>
        <string>/dev/null</string>
        <key>StandardOutPath</key>
        <string>/dev/null</string>
</dict>
</plist>


Once the launchd daemon starts, it will attempt to load the NetworkExtension that also located inside MyApp. The load succeeds and all the security prompts show up regarding loading a System Extension and allowing filtering of network traffic, however once we attempt to unload the System Extension, the call to deactivationRequestForExtension fails and we are unable to unload the System Extension unless we drag and drop MyApp to the trash bin. Is this correct behavior? There is also sample code attached with the bug report. Thanks!

The

launchd
daemon is the one that is currently attempting to load and unload the system extension.

Ah, I see. I think that explains your problem. This operation has to be authorised using Authorization Services — from the log snippet you posted, it looks like it requires the

com.apple.system-extensions.admin
authorisation right, although I’ve never dug into that myself — and there’s no way for a daemon to acquire that right because it’s running in a context that can’t present UI.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

It seems like to me that if I am able to load a system extension from the context of a launchdaemon I should also be able to unload a system extension from the context of a launchdaemon. However from your explanation it seems like the inablilty to unload a system extension from a launchdaemon is by design. Would that be an accurate statement? Thanks!

However from your explanation it seems like the inablilty to unload a system extension from a launchdaemon is by design.

I’m not able to definitively answer to that, but it seems likely. Frankly, I’m surprised that requesting a load works from a daemon context.

I’m happy to research a definitive answer for you, but that’d have to be in the context of a DTS tech support incident (and it’ll happen after Thanksgiving, because DTS is closed at the moment). Alternatively, you could file a bug against the documentation requesting that it clarify this situation.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

ps DTS is closed 25…29 Nov in observance of the US Thanksgiving holiday.