Search code examples
macosiokitentitlementslaunch-daemondriverkit

Can I open a DriverKit user client with a daemon?


I'm building a virtual HID device in Driver Kit.

I was wanting to communicate with the virtual device driver from a daemon, as the daemon is necessary for generating the HID events that would be sent from the driver.

I'm matching on my driver service fine via the daemon, however when I attempt to open the service I get -536870174 which from what I see here means kIOReturnNotPermitted.

From what I've read about this, the device driver user client can only be opened via an application that has been granted the com.apple.developer.driverkit.userclient-access entitlement by Apple.

So, my question:

Is opening the user client of a device driver in Driver Kit with a daemon completely out of the question?

Is my only option here to have a intermediate application with the com.apple.developer.driverkit.userclient-access entitlement, which can act as a broker between the daemon and the driver?

So it would be something like:

Daemon <---xpc connection--> Intermediate App <--- user client ---> Virtual HID device

Edit: To add to Phil's answer below regarding running an app as a daemon, there's some Apple written guidance here.


Solution

  • The short of it: there's no need to go to such lengths. Daemons can have entitlements.

    The official solution is to make your daemon an application, from the OS's point of view. Essentially, build your daemon as an application bundle, just don't call it .app. Your launchd plist can point at the embedded executable and it will inherit the surrounding package's entitlements.

    Unofficially, I've also had success with directly embedding the Info.plist in the daemon's binary, without a surrounding bundle directory. This is commonly done for privileged helper tools for use with SMJobBless() and is described in a bunch of places including here. Essentially, enable the "Create Info.plist Section in Binary" build setting in Xcode, or add -sectcreate __TEXT __info_plist path/to/Info.plist to your linker flags when using another build system. However, I didn't end up shipping this (didn't need it in the end) so I only ever tested it with SIP disabled. So I currently can't say for certain if it will work when signed with an appropriate provisioning profile.

    Both methods allow you to give the binary an application bundle ID by specifying it in the Info.plist, which then also enables you to include an entitlements file during code signing. As com.apple.developer.driverkit.userclient-access is not one of the "open" entitlements from the com.apple.security.* namespace, you'll also need a provisioning profile that includes it, or the OS won't accept it with SIP enabled.