I am trying to create a client connection to a SystemExtension IOService. I can see that my IOUserClient
subclass is created (init()
and Start(IOService*)
is called), but the return code from IOServiceOpen
returns kIOReturnNotPermitted
.
I am making the call to IOServiceOpen
from the same app that creates the activation request.
Entitlements for app that makes the activation request / call to IOServiceOpen
:
<?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>com.apple.developer.driverkit.userclient-access</key>
<array>
<string>sc.example.MyUserUSBInterfaceDriver</string>
</array>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.system-extension.uninstall</key>
<true/>
</dict>
</plist>
Entitlements for the dext:
<?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>com.apple.developer.driverkit.userclient-access</key>
<array>
<string>sc.example.USBApp</string>
</array>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.usb</key>
<true/>
</dict>
</plist>
MyUserClient:
#ifndef MyUserClient_h
#define MyUserClient_h
#include <DriverKit/IOUserClient.iig>
class MyUserClient : public IOUserClient {
public:
bool init() override;
kern_return_t Start(IOService* provider) override;
kern_return_t Stop(IOService* provider) override;
void free() override;
};
#endif /* MyUserClient_h */
bool MyUserClient::init() {
LOG();
if (!super::init()) {
LOG("super::init() failed");
return false;
}
return true;
}
kern_return_t IMPL(MyUserClient, Start) {
LOG();
auto ret = Start(provider, SUPERDISPATCH);
if (ret != kIOReturnSuccess) {
LOG("SUPERDISPATCH Start failed, ret: %{public}d", ret);
}
return ret;
}
kern_return_t IMPL(MyUserClient, Stop) {
LOG();
auto ret = Stop(provider, SUPERDISPATCH);
if (ret != kIOReturnSuccess) {
LOG("SUPERDISPATCH Stop failed, ret: %{public}d", ret);
}
return ret;
}
void MyUserClient::free() {
super::free();
LOG();
}
LOG
is just a macro that does os_log(OS_LOG_DEFAULT, ...
NewUserClient
implementation:
kern_return_t IMPL(MyUserUSBInterfaceDriver, NewUserClient) {
LOG("%{public}d:", type);
IOService* client;
auto ret = Create(this, "UserClientProperties", &client);
*userClient = OSDynamicCast(IOUserClient, client);
if (!(*userClient) || ret != kIOReturnSuccess) {
LOG("Failed to create IOUserClient, %{public}d", ret);
}
return ret;
}
Code to connect to system extension:
void connectToDext(io_service_t* serviceObject) {
io_connect_t dataPort;
kern_return_t kernResult =IOServiceOpen(*serviceObject, mach_task_self(), 123, &dataPort);
if (kernResult != KERN_SUCCESS) {
printf("IOServicceOpen failed: %d, %s
", kernResult, kern_return_t_toCStr(kernResult));
}
kernResult = IOServiceClose(dataPort);
if (kernResult != KERN_SUCCESS) {
printf("IOServicceClosed failed: %d, %s
", kernResult, kern_return_t_toCStr(kernResult));
}
}
int connectToFirstDext() {
CFMutableDictionaryRef matchingDict;
matchingDict = IOServiceMatching("IOService");
if (matchingDict == 0) {
return -1;
}
io_iterator_t iter;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter) !=
KERN_SUCCESS) {
printf("IOServiceGetMatchingServices failed.
");
return -1;
}
io_service_t device;
while ((device = IOIteratorNext(iter))) {
io_name_t deviceName;
if (IORegistryEntryGetName(device, deviceName) == KERN_SUCCESS) {
printf("name: %s
", deviceName);
if (strcmp(deviceName, "MyUserUSBInterfaceDriver") == 0) {
printf("Calling connect
");
connectToDext(&device);
}
}
IOObjectRelease(device);
}
IOObjectRelease(iter);
return 0;
}
Edit:
Info.plist of app
<?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>BuildMachineOSBuild</key>
<string>19E287</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>USBApp</string>
<key>CFBundleIdentifier</key>
<string>sc.example.USBApp</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>USBApp</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>11E503a</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>19E258</string>
<key>DTSDKName</key>
<string>macosx10.15</string>
<key>DTXcode</key>
<string>1141</string>
<key>DTXcodeBuild</key>
<string>11E503a</string>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright ? 2020 Example. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticTermination</key>
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
</dict>
</plist>
Info.plist of dext:
<?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>BuildMachineOSBuild</key>
<string>19E287</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>sc.example.MyUserUSBInterfaceDriver</string>
<key>CFBundleIdentifier</key>
<string>sc.example.MyUserUSBInterfaceDriver</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>sc.example.MyUserUSBInterfaceDriver</string>
<key>CFBundlePackageType</key>
<string>DEXT</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>11E503a</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string></string>
<key>DTSDKName</key>
<string>driverkit.macosx19.0</string>
<key>DTXcode</key>
<string>1141</string>
<key>DTXcodeBuild</key>
<string>11E503a</string>
<key>IOKitPersonalities</key>
<dict>
<key>example_device</key>
<dict>
<key>CFBundleIdentifier</key>
<string>sc.example.MyUserUSBInterfaceDriver</string>
<key>IOClass</key>
<string>IOUserService</string>
<key>IOProviderClass</key>
<string>IOUSBHostInterface</string>
<key>IOUserClass</key>
<string>MyUserUSBInterfaceDriver</string>
<key>IOUserServerName</key>
<string>sc.example.MyUserUSBInterfaceDriver</string>
<key>UserClientProperties</key>
<dict>
<key>IOClass</key>
<string>IOUserUserClient</string>
<key>IOServiceDEXTEntitlements</key>
<string></string>
<key>IOUserClass</key>
<string>MyUserClient</string>
</dict>
<key>bConfigurationValue</key>
<integer>1</integer>
<key>bInterfaceNumber</key>
<integer>0</integer>
<key>idProduct</key>
<integer>8</integer>
<key>idVendor</key>
<integer>1234</integer>
</dict>
</dict>
<key>OSBundleUsageDescription</key>
<string>Example user space USB driver</string>
<key>OSMinimumDriverKitVersion</key>
<string>19.4</string>
</dict>
</plist>
See Question&Answers more detail:
os