I need to disable access to certain devices (the built-in FaceTime Camera, for example), and have been trying to do so by providing a simple kext with a higher probe score than what is currently attached.
My kext matches and attaches to the camera as both IOProviderClass IOUSBInterface
and IOProviderClass IOUSBDevice
, but all of the original kexts still attach to it as well. This is how it looks in IORegistryExplorer:
FaceTime HD Camera (Built-in)@14700000 # USB device
+-- FaceTime HD Camera (Built-in)@0 # USB interface
| +-- FaceTimeDisabler # my kext matching as IOUSBInterface
| +-- IOUSBInterfaceUserClientV3 # original
+-- IOUSBDeviceUserClientV2 # original
+-- IOUSBInterface@1 # original
| +-- IOUSBInterfaceUserClientV3 # original
+-- IOUSBInterface@2 # original
+-- FaceTimeDisabler # my kext matching as IOUSBDevice
I thought the point of device and driver matching was to select a single kext to attach to the device, so I expected that if my kext matched with the highest probe score, it would gain exclusive control of the device, but that clearly isn't the case.
My questions are these:
If you want to claim exclusive access to a USB device or interface, you will need to open()
the nub object, specifying the kUSBOptionBitOpenExclusivelyMask
bit in the options
argument.
So in your FaceTimeDisabler
's start()
method, do something like:
IOUSBNub* usb_provider = OSDynamicCast(IOUSBNub, provider);
if (usb_provider == nullptr)
{
IOLog("FaceTimeDisabler: Provider is not USB nub\n");
return false;
}
bool got_exclusive_access = usb_provider->open(this, kUSBOptionBitOpenExclusivelyMask);
this->opened = got_exclusive_access;
if (!got_exclusive_access)
{
IOLog("FaceTimeDisabler: failed to acquire exclusive access to camera USB device/interface.\n");
return false;
}
And then in your stop()
method, make sure you make the corresponding close()
call if and only if the open()
succeeded (this->opened
is true in the above example).
Note that the kUSBOptionBitOpenExclusivelyMask
flag only works for the USB family, even though open()
exists everywhere. On IOPCIDevice
objects, exclusivity is implicit in the open()
, so don't pass the USB exclusive bit when you're trying to block access to PCI-based FaceTime cameras, but do call open
/close
. (My 2015 13" rMBP's camera is PCI based - vendor ID 0x14e4
, device ID 0x1570
, class code 04 80 00
)