Search code examples
macosstoragelibusbiokitkernel-extension

Codeless kext for usb storage device


In a project I am recently trying to access a usb storage device via libusb on osx 10.9.5. But apparently some default driver claims the device and I'm unable to access it. When I try to access it via libusb it returns I'd have "insufficient permissions".

When I execute the (java) application in Ubuntu, everything works as it should.

My researches on the Internet turned out that providing a codeless kext that matches the device on a higher probescore would prevent the default driver from claiming the device. This would completely solve the issue, as unloading the IOUSBMassStorage kext made it possible to execute our desired actions with the device.

My attempts at creating a codeless kext did not work out as I hoped they would, as it seems that it does neither load on startup nor when I use kextload. At least thats what I guess, as I cant unload it, nor am able to find it anywhere listed.

The latest version of my Info.plist looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>OSBundleLibraries</key>
    <dict/>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleGetInfoString</key>
    <string>Test USB Stick</string>
    <key>CFBundleIdentifier</key>
    <string>de.mischok.testkext</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>Test USB Device</string>
    <key>CFBundlePackageType</key>
    <string>KEXT</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>1.0.0</string>
    <key>IOKitPersonalities</key>
    <dict>
        <key>Device Driver</key>
        <dict>
            <key>CFBundleIdentifier</key>
            <string>de.mischok.testkext</string>
            <key>IOClass</key>
            <string>IOUSBUserClientInit</string>
            <key>IOProviderClass</key>
            <string>IOUSBDevice</string>
            <key>idProduct</key>
            <integer>357</integer>
            <key>idVendor</key>
            <integer>4871</integer>
            <key>bcdDevice</key>
            <integer>4352</integer>
            <key>bConfigurationValue</key>
            <integer>1</integer>
            <key>bInterfaceNumber</key>
            <integer>0</integer>
        </dict>
        <key>Interface Driver</key>
        <dict>
            <key>CFBundleIdentifier</key>
            <string>de.mischok.testkext</string>
            <key>IOClass</key>
            <string>IOUSBUserClientInit</string>
            <key>IOProviderClass</key>
            <string>IOUSBInterface</string>
            <key>idProduct</key>
            <integer>357</integer>
            <key>idVendor</key>
            <integer>4871</integer>
            <key>bcdDevice</key>
            <integer>4352</integer>
            <key>bConfigurationValue</key>
            <integer>1</integer>
            <key>bInterfaceNumber</key>
            <integer>0</integer>
        </dict>
    </dict>
    <key>OSBundleRequired</key>
     <string>Local-Root</string>
</dict>
</plist>

when running sudo kextutil -t -n /path/to/my.kext these diagnostics are returned:

Diagnostics for /Users/user/Desktop/testv1-0.kext:
Warnings: 
    Personality CFBundleIdentifier names a kext that doesn't declare an executable: 
        'Interface Driver' -> 'de.mischok.testkext'
        'Device Driver' -> 'de.mischok.testkext'

Code Signing Failure: not code signed
Warnings: 
    Personality CFBundleIdentifier names a kext that doesn't declare an executable: 
        'Interface Driver' -> 'de.mischok.testkext'
        'Device Driver' -> 'de.mischok.testkext'

/Users/user/Desktop/testv1-0.kext appears to be loadable (including linkage for on-disk libraries).

As it says the kext should be loadable, I assume it should work. But instead of working, the system.log logs this, when loading the kext with sudo kextload /path/to/my.kext:

Nov  5 12:28:58 users-MacBook-Pro.local sudo[528]: user : TTY=ttys000 ; PWD=/Users/user ; USER=root ; COMMAND=/sbin/kextload /Users/user/Desktop/testv1-0.kext
Nov  5 12:28:58 users-MacBook-Pro.local com.apple.kextd[12]: WARNING - Invalid signature -67062 0xFFFFFFFFFFFEFA0A for kext "/Users/user/Desktop/testv1-0.kext"

As it is a warning only, I thought it was loaded successfully. But as soon as I plug the device in, the usb prober output looks like this:

Nov  5 12:57:11.911  [6]    Device Descriptor Dump
Nov  5 12:57:11.911  [6]        bLength 18
Nov  5 12:57:11.911  [6]        bDescriptorType 1
Nov  5 12:57:11.911  [6]        bcdUSB 768 (0x0300)
Nov  5 12:57:11.911  [6]        bDeviceClass 0
Nov  5 12:57:11.911  [6]        bDeviceSubClass 0
Nov  5 12:57:11.911  [6]        bDeviceProtocol 0
Nov  5 12:57:11.911  [6]        bMaxPacketSize0 9
Nov  5 12:57:11.911  [6]        idVendor 4871 (0x1307)
Nov  5 12:57:11.911  [6]        idProduct 357 (0x0165)
Nov  5 12:57:11.911  [6]        bcdDevice 4352 (0x1100)
Nov  5 12:57:11.911  [6]        iManufacturer 1 
Nov  5 12:57:11.911  [6]        iProduct 2 
Nov  5 12:57:11.911  [6]        iSerialNumber 3
Nov  5 12:57:11.911  [6]        bNumConfigurations 1
Nov  5 12:57:11.916  [5]    Finding device driver for DEVICE, matching personality using com.apple.iokit.IOUSBUserClient, score: 106999, wildCard = 3
Nov  5 12:57:11.916  [6]        Matched: idVendor (4871) idProduct (357) bcdDevice (4352) 
Nov  5 12:57:11.916  [6]        Didn't Match: nothing
Nov  5 12:57:11.917  [5]    Finding device driver for DEVICE, matching personality using com.apple.driver.AppleUSBComposite, score: 50000, wildCard = 0
Nov  5 12:57:11.917  [6]        Matched: bDeviceClass (0) bDeviceSubClass (0) 
Nov  5 12:57:11.917  [6]        Didn't Match: nothing
Nov  5 12:57:11.918  [5]    Finding device driver for DEVICE, matching personality using com.apple.driver.AppleUSBCDC, score: 60000, wildCard = 0
Nov  5 12:57:11.918  [6]        Matched: bDeviceClass (0) bDeviceSubClass (0) bDeviceProtocol (0) 
Nov  5 12:57:11.918  [6]        Didn't Match: nothing

These are the only personality matches taking place, so I wonder, what I am supposed to do so my kext would match to my device or even load?


Solution

    1. Use kextutil, not kextload. It gives much better diagnostics.
    2. I/O Kit personalities that specify an IOClass of IOUSBUserClientInit must specfiy a CFBundleIdentifier of com.apple.iokit.IOUSBUserClient because that's where that class lives.
    3. To load an unsigned kext, it must reside in /System/Library/Extensions on 10.9.x.