Mac OS X:如何处理iflt_detach()未在KEXT停止功能中完成

时间:2014-01-31 17:38:24

标签: macos kernel-extension

在我的kext的stop()函数中,我调用iflt_detach()来分离注册的iff过滤器。但是,似乎(无论出于何种原因),可以在stop()函数之外调用过滤器的detach()函数。在那种情况下,我应该在stop函数中做什么?我无法返回KERN_SUCCESS,因为这会导致KEXT被卸载,对延迟调用detach()函数有明显的副作用。

以下代码片段来自enetlognke.c并显示了stop()函数:

kern_return_t com_dts_apple_kext_enetlognke_stop(kmod_info_t * ki,void * d)
{     kern_return_t retval = KERN_FAILURE; //默认结果,除非我们知道我们是
                                                //从界面分离。

if (gFilterRegistered == FALSE) 
    return KERN_SUCCESS; 

if (gUnregisterProc_started == FALSE) 
{ 
    // only want to start the detach process once. 
    iflt_detach(gEnetFilter); 
    gUnregisterProc_started = TRUE; 
} 

if (gUnregisterProc_complete) 
{ 
    retval = KERN_SUCCESS; 
} 
else 
{ 
    el_printf("enetlognke_stop: incomplete\n"); 
} 

if (retval == KERN_SUCCESS) 
{ 
// Free KEXT resources
} 
return retval; 

}

gUnregisterProc_complete从此模块的dispatch()函数中设置为TRUE。因此,如果该函数调用被延迟(并且gUnregisterProc_complete为FALSE),则stop函数将通过返回KERN_FAILURE来否决卸载。

所以,我的问题是:

  1. 如果返回KERN_FAILURE,内核会再次调用KEXT的stop()函数吗?如果没有,是什么触发了重试KEXT卸载和调用stop()函数?

  2. KERN_FAILURE要返回的正确代码是否过滤器尚未分离?

1 个答案:

答案 0 :(得分:0)

据推测,一旦没有线程继续运行你的回调,detach函数在这种情况下会在另一个线程上调用吗?

如果是这样,这将成为一个相当简单的线程同步问题。设置一个标志变量,例如has_detached并通过递归互斥锁保护它。

在停止功能中:在调用iflt_detach()之前锁定互斥锁。如果返回,则标志尚未设置,在挂起互斥锁时暂停标志的地址,直到标志置位。最后,解锁,并从停止功能返回。

在分离功能的最后:锁定互斥锁,设置标志,向可能正在休眠的线程发送唤醒并解锁。如果解锁调用处于尾部位置,则在执行分离函数的代码和卸载所述代码之间没有竞争条件。

实际上,这将阻止卸载kext,直到您的过滤器完全分离为止。

注意:我没有尝试过这种网络过滤器的特殊情况(我还没有编写过滤器kext),但它通常是我在其他文件夹中使用过的模式

注2:我说使用递归锁来防止死锁,以防你在iflt_detach()内部的同一线程上调用detach函数。