1

I am writing a driverkit extension whose goal is to block some categories of USB devices, such as flash drives. The driver should block (match to) any device of the relevant device classes, except those, which are whitelisted (based on their vendor and product ID). The whitelist can be set dynamically by user of the application.

The question is, how to pass these data to the driver as reading from a file or something like Windows registry is not available in the DriverKit. The tricky part is that the driver requires the whitelist data before the device is matched.

From what I understood, rejection of device is possible by returning an error from Start() method and returning from it prematurely. I got an idea to send the data while the driver is running this function, however this is not possible as the communication via IOUserClass is not available until the Start method returns.

Is this somehow doable?

pmdj
  • 22,018
  • 3
  • 52
  • 103
TomasKenny
  • 43
  • 3

1 Answers1

2
  1. As far as I'm aware, communicating with user space apps from the initial Start() method is not possible from DriverKit extensions. As you say, IOUserClients are the mechanism to use for user space communication, and those aren't available until the service is started and registered. You can have your driver match IOResources/IOUserResources so it is always loaded, but each matched service starts up an independed process of your dext, and I'm not aware of a way to directly communicate between these instances.
  2. If I understand you correctly, you're trying to block other drivers from acquiring the device. I don't think the solution you have in mind will help you with this. If you return success from Start(), your dext will drive the device. If you return failure, no driver is loaded for the device, because matching has already concluded. So other drivers would never get a chance anyway, regardless of whether the device is on your allow-list or deny-list.
  3. It's new in DriverKit 21 (i.e. macOS Monterey), and I've not had a chance to try it yet, but there is an API for reading files, OSMappedFile. I would imagine that the DriverKit sandbox will have something to say about which files a dext can open, but this seems like an avenue worth exploring whether you can open configuration files this way.
  4. Note that none of this will help you during early boot, as your dext will never be considered for matching at that time. And you may not be able to get required entitlements from Apple to build a dext which matches USB device classes rather than specific product/vendor ID patterns. (Apologies for repeating myself, but other users may come across this answer and not be aware of this issue.)
pmdj
  • 22,018
  • 3
  • 52
  • 103
  • Yeah, adding a driver's personality matching IOResources solves the problem that the driver is running and ready to receive the data at the right time, but as you say, there is no way to pass it to the "real" driver, so this is not a solution :-( – TomasKenny May 06 '22 at 14:42
  • Are you sure about the second point? Based on my experimentation, if I don't call IOUSBHostDevice::SetConfiguration and exit Start() method with an error, the device seems to be controlled by the system driver and works normally. – TomasKenny May 06 '22 at 14:46
  • @TomasKenny re: point 2. I've just checked the kernel source, and I stand corrected, thanks! I could have sworn that used to be different, but perhaps that was a **long** time ago. (I've been working with IOKit since Mac OS X 10.6.) I've also just added a reference to a new DriverKit API which might solve the issue for you! – pmdj May 06 '22 at 15:06
  • Thank you @pmdj , according to the description in the header file, OSMappedFile is exactly what I am looking for. Unfortunately I haven't managed to open a file in the driver yet, as OSMappedFile::createFromPath returns a general error so it is quite hard to guess what is wrong. I wrote a post at the official apple forum and asked them to share more details about the API, so we'll see. Any idea what to try next is welcomed – TomasKenny May 12 '22 at 12:37
  • @ThomasKenny I'm purely guessing here, but I suspect the failure might be related to code signing entitlements. I'd check if there is anything useful in the system logs. (Try: `log stream --predicate 'processID == 0 OR process == "sysextd" OR process == "taskgated-helper" OR process == "syspolicyd" OR process == "kernelmanagerd"`) Unfortunately, and very suspiciously, `OSMappedFile` does not appear in the xnu kernel source code, so you can't even straightforwardly check the source to see how it's supposed to work. – pmdj May 12 '22 at 12:55
  • I can confirm that: kernel: (Sandbox) Sandbox: com.mycompany.troll(9944) deny(1) file-read-data /Library/Application Support/mycompany/troll.conf – TomasKenny May 12 '22 at 13:28
  • Perhaps setting the [`com.apple.security.temporary-exception.files.absolute-path.read-only` entitlement](https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AppSandboxTemporaryExceptionEntitlements.html#//apple_ref/doc/uid/TP40011195-CH5-SW7) to an array containing a string with the path of your file will help? However, I have never tried this on a DriverKit extension, so perhaps those are mutually exclusive. – pmdj May 12 '22 at 14:08
  • I put this permission to my entitlement file and it seems to be removed (maybe not validated?) during the build process. When applying command "codesign --display --entitlements :- " to the built dext bundle, it is missing. – TomasKenny May 13 '22 at 12:08
  • @TomasKenny This seems sufficiently orthogonal from the original question and you’ll need to add a whole bunch of extra info that I’d recommend posting this entitlements/OSMappedFile problem as a new question. If you tag it with [driverkit] I’ll definitely see it (I monitor that tag) and can try to help. – pmdj May 14 '22 at 11:01
  • In the end it showed that this was not related to permissions. The driver doesn't require any additional entitlements, however it can read only files inside its bundle. Passing a method OSMappedFile::createFromPath a full path inside the bundle gives expected results. The problem in my case was a mismatch between the path I was trying to open and a path where the driver was running. – TomasKenny May 26 '22 at 07:08