Hi,
We’re developing a DriverKit extension for iPadOS. In local Debug and Release builds, everything works as expected, but the same build uploaded to TestFlight fails at IOServiceOpen with the following errors:
-536870212 (0xE00002EC) kIOReturnUnsupported
-536870201 (0xE00002F7) kIOReturnNotPermitted
What we’ve verified so far
- App entitlements
We checked our main app entitlements file, and it has the correct capabilities for the driverkit communication
<?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>com.apple.developer.driverkit.communicates-with-drivers</key>
<true/>
<key>com.apple.developer.driverkit.userclient-access</key>
<array>
<string>abc.def.ABCDriver</string>
</array>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
- we also checked the Provisioning profile (as shown on the portal) and the “Enabled Capabilities” seems to have the correct DriverKit Capabilities enabled.
Enabled Capabilities
Access Wi-Fi Information, DriverKit, DriverKit (development), DriverKit Communicates with Drivers, DriverKit USB Transport (development), DriverKit USB Transport - VendorID, DriverKit UserClient Access, iCloud, In-App Purchase, Sign In with Apple, System Extension
- When we download and inspect the provisioning profile as plain text, we notice that some expected DriverKit entitlements appear to be missing from the <Entitlements> section.
<key>Entitlements</key>
<dict>
<key>beta-reports-active</key>
<true/>
<key>com.apple.developer.networking.wifi-info</key>
<true/>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.communicates-with-drivers</key>
<true/>
<key>application-identifier</key>
<string>ABC123456.abc.def</string>
<key>keychain-access-groups</key>
<array>
<string>ABC123456.*</string>
<string>com.apple.token</string>
</array>
<key>get-task-allow</key>
<false/>
<key>com.apple.developer.team-identifier</key>
<string>ABC123456</string>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>ABC123456.*</string>
<key>com.apple.developer.icloud-services</key>
<string>*</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array></array>
<key>com.apple.developer.icloud-container-development-container-identifiers</key>
<array></array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array></array>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>1234</integer>
</dict>
</array>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
</dict>
We have a couple of questions:
-
Could the missing com.apple.developer.driverkit.userclient-access entitlement in the provisioning profile alone explain the kIOReturnUnsupported / kIOReturnNotPermitted failures from IOServiceOpen?
-
Why do some DriverKit capabilities appear in the Apple Developer portal UI but vanish from the actual profile we download? Is there an extra step we’re overlooking when regenerating profiles after toggling those capabilities?
Thanks
Below are the Info.plist, entitlements, and App Store profiles for our driver and client app.
So, as a quick side comment, when looking into an issue like this, it's critical to look at the actual Info.plist file, not just the Xcode project settings. I happened to have been sent your DEXT by one of our evangelists, but without the actual data, I probably wouldn't have thought of this.
In any case, here is the CFBundleVersion of your development DEXT:
CFBundleVersion = 1
And here is your TestFlight version:
CFBundleVersion = 3433099.287482533
You can read the full details here, but that second version simply will not work in a DEXT/KEXT.
I suspect that's the problem here, but covering a few odds and ends:
- Our driver’s Info.plist specifies both idVendor and idProduct, but our entitlements and provisioning profiles currently include only the idVendor. Do we need to request approval or entitlement inclusion for the idProduct as well?
No. There are actually two mechanisms at work here that operate independently.
-
Your codesign configuration determines what device you’re "eligible" to be matched with. In your case, that means your DEXT is a candidate to be loaded for any USB device with an
idVendor = 1234.
This is what controls whether or not the kernel "sees" your DEXT for any given device. -
The contents of your IOKitPersonalities are what the kernel ACTUALLY uses for matching. In your case, that means that this particular DEXT will match with a device that has this configuration:
bConfigurationValue = 1
bInterfaceNumber = 0
idProduct = 5678
idVendor = 1234
It's actually fairly normal for #1 to be significantly broader than #2, as that's how vendors ship different drivers for different hardware without needing a different entitlement set for EVERY single device they ship.
- We’ve noticed that our development provisioning profiles use wildcard matching for idVendor:
This is normal, as this is how the development only variants allow matching to "any" hardware.
Is there a way to update our development profiles to match the App Store versions?
Theoretically, yes. In theory, you could generate manual provisioning profiles for the DEXT and then switch to "manual" codesigning in Xcode. However, I would strongly recommend against doing so. When it comes to DEXT signing, there are basically two cases in Xcode 16:
-
Your team configuration is simple enough that automatic code-signing actually works.
-
Your team configuration is complex enough that distribution signing breaks, forcing you to manually sign distribution builds.
In the first case, you should enjoy that fact and ignore this issue. In the second case, you should celebrate the fact that at least you don't have to deal with development builds... and ignore this issue.
One thing to understand here is what "wrongly" signed would actually mean. There are basically two cases:
-
Your entitlement is misconfigured in a way that makes your DEXT nonfunctional. For example, if your entitlement is configured as
"idVendor=4321"
but your hardware is"idVendor=1234",
then that DEXT is incapable of EVER actually running against hardware. This is a case you might want to check for, but it's not something that will really "break" once it's been properly configured on our side. -
"Something" about your configuration is "wrong" that makes your app signing configuration incapable of running.
My experience has been that, at least for DEXT, all signing errors seem to happen at build time, NOT install or run time. That is, once you get a DEXT signed it won't fail because of codesigning. That's definitely the case here, as that KEXT version check is basically as old as the system is.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware