Guidance requested: DriverKit entitlement follow-up for DLP application (Endpoint Security entitlement already granted)

Entitlements requested:

com.apple.developer.driverkit.userclient-access
com.apple.developer.driverkit.transport.usb
com.apple.developer.driverkit.transport.hid
com.apple.developer.driverkit.family.hid.eventservice
com.apple.developer.driverkit.family.serial
com.apple.developer.driverkit.family.scsicontroller
com.apple.developer.driverkit.family.networking
com.apple.developer.driverkit.family.hid.device

, and the base com.apple.developer.driverkit entitlement

Hi all,

We recently received a decline on the DriverKit entitlement set listed above. The response noted:

"Technical details within DriverKit mean that it is not a viable solution for security block or broad-scale system modifications."

I'd like to get some clarity on how to bring our request in line with what's approvable, and I'm hoping the forum (or a Code-Level Support engineer) can point us in the right direction.

Context on what we're building: We develop a Data Loss Prevention (DLP) product for macOS. We already hold the Endpoint Security entitlement (com.apple.developer.endpoint-security.client) and use it in production today for our core monitoring and policy-enforcement functionality.

Why we're requesting DriverKit specifically: ESF gives us visibility and the ability to authorize/deny many file and process events, but it does not give us the control we need over removable/peripheral hardware. Two concrete gaps in our DLP policy enforcement that we're trying to close:

  1. Blocking data exfiltration via USB-connected Android devices — when an Android phone is plugged in, it mounts as a USB mass-storage/MTP-style device, and our policy needs to be able to prevent it from mounting or being written to, on a per-policy basis (e.g., disable an endpoint's ability to copy files to a connected Android device).
  2. Camera blocking — disabling the built-in/USB camera device at the hardware transport level as part of a DLP policy, rather than a userspace toggle that a privileged process could bypass.

Our understanding was that "com.apple.developer.driverkit.transport.usb" combined with the HID/USB family entitlements would let us implement a DriverKit-based USB filtering driver to enforce this. Given the decline language about "security block or broad-scale system modifications," it sounds like Apple's position is that DriverKit is not intended to be used to build a general device-blocking layer this way.

What I'm hoping to learn:

  • Is per-policy USB mass-storage/MTP mounting control (blocking a specific class of device, e.g., Android phones, from mounting or transferring files) something DriverKit is intended to support at all for third-party DLP vendors, or is this fundamentally out of scope regardless of how the request is written up?
  • If it is in scope, what should we change in the entitlement request write-up (use case description, scoping of which entitlements we actually need vs. what we requested) to make it approvable? We may have over-requested — for example, do we need family.networking and family.serial at all for USB mass-storage/camera blocking, or should we narrow the request to just the USB transport + HID/SCSI entitlements?
  • Is there a preferred way to demonstrate that our use case is a scoped, policy-driven enterprise DLP control (with IT/MDM deployment, not a consumer app) rather than "broad-scale system modification," or does the entitlement review not distinguish on that basis?

Any pointers — either on scoping this request correctly, or on whether this is simply not achievable via DriverKit and we should be looking at a different API — would be much appreciated. Happy to provide more detail on our exact enforcement flow if that's useful for a Code-Level Support ticket.

Thanks in advance

Any pointers — either on scoping this request correctly, or on whether this is simply not achievable via DriverKit and we should be looking at a different API — would be much appreciated.

So, my immediate question is why aren't you just doing this through Endpoint Security?

I'm happy to discuss these issues in more detail, but keeping things brief:

Our policy needs to be able to prevent it from mounting.

I recommend blocking mount by using DiskArbitration as the initial "barrier" with EndpointSecurity acting as the "backstop". DiskArb provides a better API and user experience for "normal" usage patterns, while EndpointSecurity ensures that nothing can mount without your approval.

or being written to, on a per-policy basis.

EndpointSecurity lets you block any open you want, and you can't modify a file you can't open.

Camera blocking — disabling the built-in/USB camera device at the hardware transport level as

Cameras are either accessed through the filesystem (which you'd block using the techniques above) or through IOKit access. IOKit access can be blocked through ES_EVENT_TYPE_AUTH_IOKIT_OPEN. Note that looking online you may find forum posts (some written by me) saying that this won't really work because you can't reliably determine what device you're actually interacting with. That used to be true, but since then we've expanded es_event_iokit_open_t to include both the parent_registry_id and parent_path. That's exactly the information you'd need to validate anything you'd want to look at.

Note that those two values are basically different ways of accessing exactly the same data, but we've provided both because they're useful in different contexts:

  1. parent_path is useful for static blocking or caching, as you can use a string of prefix comparison to quickly identify anything you want to block.

  2. parent_registry_id is used with IORegistryEntryIDMatching to get you to the actual io_object_t that's the target.

One subtle issue to be aware of: registry ID's are "unique" to a given object entry, while paths are a particular "location" in the registry. Putting that in more concrete terms, if you hot plug a device, then the device will have a new registry ID (its new object), but it might* have the same path, since it's the same device plugged into the same place.

*The actual behavior depends on the implementation details of the family.

Our understanding was that "com.apple.developer.driverkit.transport.usb" combined with the HID/USB family entitlements would let us implement a DriverKit-based USB filtering driver to enforce this.

In practice, no, I don't think this would actually work all that well. The biggest issue is that DriverKit loading doesn't occur during boot, which means devices come up with the default system driver even if a DEXT is installed. Because of that, I don't think DriverKit can actually block a mass storage device that was attached at boot.

Beyond that, I just don't think it will really work. Once your DEXT takes control of a device it owns, that device and it can't really "release" that device, as unloading your driver doesn't necessarily (the details depend on the family) trigger a new matching cycle. That means there isn't any good way for you to "give back" control of a device you no longer want to block.

Also, being a DEXT means that all that’s required to bypass your DEXT is for some other DEXT to match with a higher priority than you. There isn't any magic "I'm always most important" switch, so now you're having to fiddle with every possible family trying to play games to make sure you always be first. That's not a game you want to be playing.

Finally, I want to be clear that this is just the list of problems I came up with off the top of my head, not anything close to a complete list. I can actually think of a variety of "tricks" that would get you around several of these issues, but the real problem is that... the problems don't really end. Case in point, below you say:

blocking a specific class of device, e.g., Android phones

How? How do you match a DEXT to that?

At the USB level, "Android phones" don't really exist. Each device provides fairly minimal metadata and it's often the case that this data is simply wrong. You're either going to have a match dictionary that's WAY too broad or you'll be ignoring a vast number of devices. And, of course, USB's the easy case. PCI/Thunderbolt has exactly the same general issues, except now the ONLY information you really have is the pid/vid AND the hardware ecosystem is much weirder*.

*PCI/Thunderbolt doesn't have the concept of class driver, which means there isn't really a standardized way to identify what kind of device something "is". Even more fun, being PCI means that you can be dealing with full-fledged host bus adapters, not just individual storage devices.

Is per-policy USB mass-storage/MTP mounting control (blocking a specific class of device, e.g., Android phones, from mounting or transferring files) something DriverKit is intended to support at all for third-party DLP vendors, or is this fundamentally out of scope regardless of how the request is written up?

This is not something DriverKit is designed to support.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Guidance requested: DriverKit entitlement follow-up for DLP application (Endpoint Security entitlement already granted)
 
 
Q