Hello everyone,
I am migrating a legacy KEXT to a DriverKit (DEXT) architecture. While the DEXT itself is working correctly, I am completely blocked by a code signing issue when trying to establish the UserClient connection from our SwiftUI management app.
Project Goal & Status:
- Our DEXT (com.accusys.Acxxx.driver) activates successfully (systemextensionsctl list confirms [activated enabled]).
- The core functionality is working (diskutil list shows the corresponding disk device node).
The Core Problem: The userclient-access Signing Error
-
To allow the app to connect to the DEXT, the com.apple.developer.driverkit.userclient-access entitlement is required in the app's .entitlements file.
-
However, as soon as this entitlement is added, the build fails.
-
Both automatic and manual signing fail with the same error:
`Provisioning profile ... doesn't match the entitlements file's value for the ... userclient-access entitlement.`
-
This build failure prevents the generation of an .app bundle, making it impossible to inspect the final entitlements with codesign.
What We've Confirmed:
- The necessary capabilities (like DriverKit Communicates with Drivers) are visible and enabled for our App ID on the developer portal.
- The issue persists on a clean system state and on the latest macOS Sequoia 15.7.1.
Our Research and Hypothesis:
- We have reviewed the official documentation "Diagnosing issues with entitlements" (TN3125).
- According to the documentation, a "doesn't match" error implies a discrepancy between the entitlements file and the provisioning profile.
- Given that we have tried both automatic and manual profiles (after enabling the capability online), our hypothesis is that the provisioning profile generation process on Apple's backend is not correctly including the approved userclient-access entitlement into the profile file itself. The build fails because Xcode correctly detects this discrepancy.
Our Questions:
Did we misunderstand a step in the process, or is the issue not with the entitlement request at all? Alternatively, are there any other modifications we can make to successfully connect our App to the DEXT and trigger NewUserClient?
Thank you for any guidance.
Following up with this to clear up some odds and ends:
Provisioning profile ... doesn't match the entitlements file's value for the ... userclient-access entitlement.
One thing to be aware of her is that Xcode has a "bias" in the way it presents codesign errors where it assumes the Entitlement.plist is "correct" and the profile is "wrong". However, in practice that's basically "never" the case with DriverKit entitlements and tends to lead to a lot of "flailing" trying to somehow "fix" the provisioning profile. This error ALWAYS means that "the entitlement.plist doesn't match the profile". You fix that by:
-
Changing the Entitlement.plist to match the profile.
-
Changing the actual profile. That means either:
-
Submitting a new request to correct any mistake (this case).
-
IF you have been granted multiple instances of the same entitlement, then you switch to manual profile generation and manual codesigning. See this forum post for more details on that flow.
However, the key here is to understand that this:
...our hypothesis is that the provisioning profile generation process on Apple's backend is not correctly including the approved userclient-access entitlement into the profile file itself.
...basically never happens. That is, the backend side of this doesn't really "fail"*, so these issue are always about feeding the "right" data into Xcode, not that the portal didn't generate what it was "told" to generate.
*While I'm sure that the portal has in fact had bugs and issues, I have never actually seen this occur and don't think that kind of failure would look anything like yours.
com.apple.developer.driverkit.userclient-access: com.accusys.Acxxx.app
Yes, this is the core problem as the bundle ID in the request value needs to be the DEXT you'll be communicating with.
The communicates-with-drivers entitlement is not working as expected, as it fails to grant the app visibility of the IOKit service.
No, unfortunately, that's not correct. It doesn't work on macOS because it's an iPad Only Entitlement:
"A Boolean value that indicates whether an iPadOS app can communicate with drivers."
Shifting to the problem here:
The IOServiceGetMatchingService("DriverKitAcxxx") call fails to find the service, and no logs from NewUserClient() are ever generated on the DEXT side.
What's makes this complicated is to talk through is that there are two different "sides" to the connection, both of which get to "veto" the connection attempt:
-
The DEXT/Kernel connection, which "com.apple.developer.driverkit.allow-any-userclient-access" disables.
-
The app side, particularly the app sandbox, which is what's actually failing here.
On that second point if you test with "IOServiceGetMatchingService", I think you'll find that it can't actually find "any" services (or at least, not the full set). In other words, the problem here isn't that you can't connect to "your driver", it's that your app can't really interact with IOKit. In any case, I believe there are three ways you can make this work:
-
Disable the sandbox in the app, as the app sandbox is what's actually blocking the request.
-
Adding the "com.apple.developer.driverkit.userclient-access" with the correct value, which is what you're currently trying to fix.
-
I believe self adding the "right" "IOKit User Client Class Temporary Exception" value would make this work. Note that the value here is the kernel's "view" of reality, so you'd use the value "IOUserUserClient"*, NOT the class name your DEXT uses.
*IOUserUserClient is the class in the kernel that handles routing user space requests coming into the kernel "over" to your DEXT.
Note that that term "Temporary Exception" can be somewhat misleading. These entitlements where labeled as "temporary" when we introduced them because they were all cases where we didn't think the entitlement was a "good" solution to the issue and we expected to introduce new entitlements that were the "right" solution (which we largely have). However, I don't think we've actually disabled any of them. I'd probably avoid shipping code that used #3, but that's only because #2 is fairly straight forward. If I had to ship something "now" and couldn't get #2 sorted out, then I would certainly try #3 before resorting to #1.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware