3

The DiskArbitration framework on macOS provides a simple way to intercept volumes mounts and authorise it or not using DARegisterDiskMountApprovalCallback.

I'm looking for something similar for all the other USB devices like HID devices, network interfaces and in general every USB peripheral.

I'm moving in the direction of IOKit: Introduction to USB Device Interface Guide and I can see how to communicate with a USB device but I can't find anything similar to an arbitration mechanism.

Any idea? Kernel extension isn't an option.


macOS 11 update

With macOS a new AUTH event called ES_EVENT_TYPE_AUTH_IOKIT_OPEN has been introduced. The event is called correctly but digging in the object headers I fund:

/**
 * @brief Open a connection to an I/O Kit IOService
 *
 * @field user_client_type A constant specifying the type of connection to be
 *        created, interpreted only by the IOService's family.
 *        This field corresponds to the type argument to IOServiceOpen().
 * @field user_client_class Meta class name of the user client instance.
 *
 * This event is fired when a process calls IOServiceOpen() in order to open
 * a communications channel with an I/O Kit driver.  The event does not
 * correspond to driver <-> device communication and is neither providing
 * visibility nor access control into devices being attached.
 */
typedef struct {
    uint32_t user_client_type;
    es_string_token_t user_client_class;
    uint8_t reserved[64];
} es_event_iokit_open_t;

:(

This screws my plans:

The event does not correspond to driver <-> device communication and is neither providing visibility nor access control into devices being attached.

Any idea on how to get the device info in another way?

Kappe
  • 9,217
  • 2
  • 29
  • 41

2 Answers2

2

Since macOS 10.15, you can use the EndpointSecurity API to authorise IOKit user clients, i.e. get a callback whenever a user process attempts to IOServiceOpen().

The relevant event for this is ES_EVENT_TYPE_NOTIFY_IOKIT_OPEN/es_event_iokit_open_t.

I don't believe this applies in any way to in-kernel clients, for those you'd need to go down the kext route.

Prior to 10.15, a kext was the only option in general - the MAC framework kernel API has a similar policy callback to the new EndpointSecurity one.

pmdj
  • 22,018
  • 3
  • 52
  • 103
  • Thanks pmdj, I was exploring the same idea but from my interpretation of the headers looks like that the x_NOTIFY_x are "Notification" only and not "Authorization Event" (from https://developer.apple.com/documentation/endpointsecurity/es_event_type_t?changes=latest_minor&language=objc) do you think will be possible authorise ar not authorise that kind of events? – Kappe Oct 11 '19 at 10:20
  • 1
    You're right; the macOS 11 beta now contains a corresponding AUTH event at least. https://developer.apple.com/documentation/endpointsecurity/es_event_type_t/es_event_type_auth_iokit_open?changes=latest_minor&language=objc – pmdj Sep 02 '20 at 08:58
  • Playing around with the ES_EVENT_TYPE_NOTIFY_IOKIT_OPEN event, I can see that some processes like systemstats and configd are notified when a USB storage device is connected. @pmdj would you happen to know how these processes subscribe to/receive these notifications? – craig65535 Sep 04 '20 at 18:27
  • I think that the new `ES_EVENT_TYPE_AUTH_IOKIT_OPEN` is the solution I was looking for :) nice one thanks @pmdj – Kappe Sep 14 '20 at 09:37
  • have a look at my `macOS 11 update`, no luck with the new auth event. – Kappe Jan 11 '21 at 20:05
  • @Kappe yes, it's for gating access to `IOServiceOpen()` only. This does work for pure user space drivers, but it should come as no surprise that a user space program will not be queried before different kernel components are allowed to communicate. It sounds like you want to have complete control over whether devices are matched by their respective kernel, DriverKit, or userspace drivers. This sort of power is only available within the kernel itself. – pmdj Jan 14 '21 at 14:07
  • @pmdj with the KEXT been deprecated I can't see anymore a viable solution for securing a user device from the hardware point of view... nowadays a malicious USB-C charger can have HID, storage or wireless capabilities and not having a way to analyse what the hardware is in reality, seems quite concerning to me. – Kappe Jan 15 '21 at 15:11
  • @Kappe USB kexts are indeed deprecated, although I'm not sure if you can still make them load in Big Sur by linking against a KPI which doesn't have a DriverKit equivalent. (they will definitely load with SIP disabled, but that's even worse for security) The only thing I can think of other than a kext is to file an enhancement request (suggestion) with Apple's feedback assistant for such an API to be added to the EndpointSecurity API. Unfortunately, the chances of them acting on it are small. – pmdj Jan 15 '21 at 19:22
  • On the plus side, macOS in theory has a built-in defence against HID keyboard attacks: if you plug in a new keyboard it hasn't seen before, it will not accept key presses from it and instead shows the keyboard layout assistant. I don't know how easy this is to circumvent by a device pretending to be an Apple branded keyboard though. – pmdj Jan 15 '21 at 19:24
1

Not a complete answer, but it looks like there is a way to subscribe to device notifications with IOKit.

Apple has provided ionotifyCB.c here: https://opensource.apple.com/source/IOKitUser/IOKitUser-502/ionotifyCB.c.auto.html

It doesn't build for me as-is, but I was able to make it work with some minor patching:

@@ -23,5 +23,6 @@
 /*
-cc ionotifyCB.c -o /tmp/ion -Wall -Wno-four-char-constants -framework IOKit -undefined warning
+cc ionotifyCB.c -o /tmp/ion -Wall -Wno-four-char-constants -framework IOKit -framework CoreFoundation
 */
 
+#include <stdio.h>
 #include <ctype.h>
@@ -35,2 +36,3 @@
 #include <CoreFoundation/CFRunLoop.h>
+#include <IOKit/graphics/IOGraphicsLib.h>

craig65535
  • 3,439
  • 1
  • 23
  • 49
  • Not an expert in IOKit and digging in the code seems more a notification than an authorization request/arbitration. @craig have a look at my `macOS 11 update` update in the original question. – Kappe Jan 11 '21 at 20:04