I've got IOKit driver that derives from IOService
base class, and its raw pointer is delivered to some event callback function from kauth
framework that may be called very frequently.
In order to extract this instance out of the pointer I uses the safe method OSDynamicCast
, and I make sure that during driver teardown, I disable the kauth
calls and flush all existing calls BEFORE freeing the driver. However, sometimes I still get kernel panic on the OSDynamicCast
:
frame #0: [inlined] OSMetaClass::checkMetaCast(check=0xffffff802b28d3f0)
frame #1: [inlined] OSMetaClassBase::metaCast(OSMetaClass const*) const
frame #2: kernel`OSMetaClassBase::safeMetaCast
When I disabled and flushed the kauth
calls before the OSObject::free
on the IOService::stop
callback, the problem hasn't repeats itself (at least after dozens of tries).
Perhaps anyone have an idea if there's any memory being freed during the period between ::stop
and ::free
that trigger this panic ?
Here's a small code that emphasis my design when It trigger panic.
kauth_callback(kauth_cred_t credential,
void *idata, /* This is the RAW pointer for my IOService based instance */
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3)
{
...
// taking shared_lock with mutex
auto my_inst = OSDynamicCast(com_my_driver, reinterpret_cast<OSObject *>(idata));
...
}
void com_my_driver::free(IOService *provider)
{
kauth_unlisten_scope(my_listener_);
// taking unique lock with mutex to make sure no outstanding kauth calls.
super::free(provider); //calling OSObject free
}
And if I move the logic from ::free
to ::stop
it works :
void com_my_driver::stop(IOService *provider)
{
kauth_unlisten_scope(my_listener_);
// taking unique lock with mutex to make sure no outstanding kauth calls.
super::stop(provider); // Calling IOService::stop()
}