I've got IOKit base Driver/Deamons project with relationship of one to many (meaning multiple clients attached to single driver).
The core driver is an IOKit object derived from IOService
and is also the provider of driver clients derived from IOUserClient
. Those are the agents of user-space clients (one per user-space client)
My goal was to prevent driver from unload in case of kextunload
command with root privileges, So that only when the last client disconnect (process terminate or call IOServiceClose
), the driver will be closed automatically (without the need to do kextunload
manually)
In order to check what IOKit commands i need to disable/postphone, I've wrapped the basid IOService
callbacks with the relevant print message and observed the logs in a scenario of running kextunload
where 2 clients are connected:
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 *)
--
It seems that even if I take reference from each IOUserClient
on its provider, and releasing those reference on IOUserClient::clientClose
, the kextunload
command still succeed.
The only way I've found to achieve my goal, is in postponing the ::terminate
command and call it explicitly from ::clientClose
.
So i removed the call to IOService::terminate
and instead called it from IOUserClient::clientClose()
.
Here the relevant code :
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;
}
I'd like to know if there are any, less hacky ways of preventing kextunload
from succeeding and controlling the timing of driver unload.
thanks