2

我有一个具有一对多关系的 IOKit 基础驱动程序/守护程序项目(意味着多个客户端连接到单个驱动程序)。

核心驱动程序是一个 IOKit 对象IOService,它是从IOUserClient. 这些是用户空间客户端的代理(每个用户空间客户端一个)

我的目标是在具有root权限的命令的情况下防止驱动程序卸载kextunload,这样只有当最后一个客户端断开连接(进程终止或调用IOServiceClose)时,驱动程序才会自动关闭(无需kextunload手动执行)

为了检查我需要禁用/邮寄哪些 IOKit 命令,我已经用相关的打印消息包装了基本回调,并在连接 2 个客户端IOService的运行场景中观察了日志:kextunload

kernel: (driver) virtual bool com_osxkernel_driver::terminate(IOOptionBits)
kernel: (driver) virtual bool com_osxkernel_driverClient::terminate(IOOptionBits)
kernel: (driver) virtual bool com_osxkernel_driverClient::terminate(IOOptionBits)
kernel: (driver) virtual void com_osxkernel_driverClient::stop(IOService *)
kernel: (driver) virtual void com_osxkernel_driverClient::stop(IOService *)
kernel: (driver) virtual void com_osxkernel_driver::stop(IOService *)

--

似乎即使我从每个IOUserClient提供者那里获取参考,并在 上释放这些参考IOUserClient::clientClose ,该kextunload命令仍然成功。

我发现实现目标的唯一方法是推迟::terminate命令并从::clientClose.

所以我删除了对的调用IOService::terminate,而是从IOUserClient::clientClose(). 这里是相关代码:

IOReturn com_osxkernel_driverClient::clientClose() 
{
    myProvider->release();
    return super::terminate(kIOServiceSynchronous) ? kIOReturnSuccess : kIOReturnError;
}


bool com_osxkernel_driverClient::terminate(IOOptionBits options) {
    os_log_info(g_logger,"%s", __PRETTY_FUNCTION__);
    return true;
}

我想知道是否有任何不那么老套的方法来防止kextunload成功和控制驱动程序卸载的时间。

谢谢

4

1 回答 1

0

如果您查看源代码,您会看到它调用kextunloadIOCatalogueTerminate(). 在内核中,这最终会进入IOCatalogue::_terminateDrivers()函数。(xnu 源代码中的 IOCatalogue.cpp)您将看到以下内容针对属于正在卸载的 kext 的每个 IOKit 类实例运行:

if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) 
{
    ret = kIOReturnUnsupported;
    break;
}

这表明停止 kext 的 IORegistry 条目的唯一方法确实是从terminate().

像这样硬阻止它是否是一个好主意当然完全是另一个问题。我建议您仅在卸载会危及操作系统稳定性时才这样做。考虑到这kextunload需要 root 权限,因此在大多数情况下,最好在用户空间代码中简单地处理服务和用户客户端的终止。

如果您确实返回 false from terminate(),您还需要注意不要出于正当理由阻止终止。(例如,如果它是一个设备驱动程序,您的驱动程序匹配的小块,例如,如果设备是热拔出的,IOUSBInterface可能会尝试您的驱动程序实例。)terminate()

于 2017-11-29T14:34:03.940 回答