4

我正在尝试创建到 SystemExtension IOService 的客户端连接。我可以看到我的IOUserClient子类已创建(init()并被Start(IOService*)调用),但返回代码来自IOServiceOpenreturns kIOReturnNotPermitted

我正在IOServiceOpen从创建激活请求的同一个应用程序中进行调用。

发出激活请求/调用的应用程序的权利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>

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>

我的用户客户端:

#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只是一个宏os_log(OS_LOG_DEFAULT, ...

NewUserClient执行:

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;
}

连接系统扩展的代码:

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\n", kernResult, kern_return_t_toCStr(kernResult));
  }
  kernResult = IOServiceClose(dataPort);
  if (kernResult != KERN_SUCCESS) {
    printf("IOServicceClosed failed: %d, %s\n", 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.\n");
        return -1;
      }

      io_service_t device;
      while ((device = IOIteratorNext(iter))) {
        io_name_t deviceName;
        if (IORegistryEntryGetName(device, deviceName) == KERN_SUCCESS) {
          printf("name: %s\n", deviceName);
          if (strcmp(deviceName, "MyUserUSBInterfaceDriver") == 0) {
            printf("Calling connect\n");
            connectToDext(&device);
          }
        }
        IOObjectRelease(device);
      }

      IOObjectRelease(iter);

    return 0;
}

编辑:

应用程序的Info.plist

<?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>

dext的Info.plist:

<?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>
4

2 回答 2

4

更新的答案:

IOServiceDEXTEntitlementsIOKitPersonality 的 用户Info.plist客户端属性字典中的属性应该是以下之一:

  1. 完全失踪;这意味着:不要检查我原始答案中列出的基本知识之外的客户权利。
  2. 我想一个字符串数组;客户端必须具有内部数组之一中列出的所有权利。(注意:我没有对后一种情况进行任何测试。)

非数组或空数组IOServiceDEXTEntitlements属性意味着客户端无法匹配其中一个内部数组中的权利,因为没有任何. 因此,检查总是kIOReturnNotPermitted. 这就是您的(空)字符串值发生的情况。

有关详细信息,请在xnu 源代码的 IOUserServer.cpp 中检查代码IOUserServer::checkEntitlements()及其调用位置。IOUserServer::serviceNewUserClient()

原答案:

(在发布 s 的内容之前给出Info.plist。)

我看不出您发布的内容有任何明显错误,因此我怀疑您的问题可能是由您尚未发布的内容引起的。需要注意的事项:

  • 用户客户端应用程序的com.apple.developer.driverkit.userclient-access数组必须包含 dext 的包 ID。也许仔细检查这个 ID 是否真的等于sc.example.MyUserUSBInterfaceDriverkIOReturnNotPermitted(当我在这里有一个错字时,我之前已经花了一个多小时来解决这个错误。)
  • 必须允许用户客户端应用程序与 IOKit 对话。这是默认情况下的情况,除非您的应用程序是沙盒的。假设您发布的权利是完整的,您的应用程序没有沙盒,所以这不应该是问题。
  • 如果用于创建新用户客户端的字典包含IOServiceDEXTEntitlements密钥,则用户空间应用程序必须在此处列出所有权利。(这本词典来自 dext 的 info.plist,在撰写本文时您尚未发布。)
  • 我相信 dext 和应用程序必须使用相同的团队 ID 进行签名。(我似乎记得您可以在 dext 上设置一项权利来解决此要求。)也许仔细检查TeamIdentifierusingcodesign -dv path/to/your.dextcodesign -dv path/to/your.app
于 2020-05-06T08:37:09.063 回答
2

与您的问题相切-我将尝试单独回答您的实际问题-但我注意到您通过遍历所有IOService对象来定位您的服务。通过使用属性匹配直接匹配它,您可以更优雅地找到它。我使用辅助函数来生成看起来像这样的匹配字典:

// Creates IOKit matching dictionary for locating driverkit-based service objects
// (Corresponds to kext services' IOServiceMatching())
static CFMutableDictionaryRef user_service_matching(CFStringRef driverkit_classname, CFStringRef driverkit_server_bundle_id) CF_RETURNS_RETAINED
{
    CFMutableDictionaryRef match = IOServiceMatching("IOUserService");
    CFTypeRef match_property_keys[]   = { CFSTR("IOUserClass"), kIOBundleIdentifierKey };
    CFTypeRef match_property_values[] = { driverkit_classname,  driverkit_server_bundle_id };
    CFDictionaryRef match_properties = CFDictionaryCreate(
        kCFAllocatorDefault,
        match_property_keys, match_property_values, 2,
        &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionaryAddValue(match, CFSTR(kIOPropertyMatchKey), match_properties);
    CFRelease(match_properties);
    return match;
}

这匹配:

  • 类型的对象IOUserService(这是一个比dexts 中的IOService所有直接子类更小的搜索空间,实际上是“真实”(内核)I/O 注册表中的对象。)IOServiceIOUserService
  • 使用与IOUserClass提供的属性匹配的属性driverkit_classnameCFSTR("MyUserUSBInterfaceDriver")在您的情况下)
  • CFBundleIdentifier提供的匹配。( CFSTR("sc.example.MyUserUSBInterfaceDriver"))

虽然相对不太可能,但在您发布的代码中检索到的服务名称IORegistryEntryGetName理论上可能会与其他 kext 或 dext 发生冲突,而捆绑标识符中不应有歧义,并且当您的驱动程序实现多个时匹配用户类很有帮助类。

于 2020-05-06T08:17:20.970 回答