I code a Network Kernel Extensions on Mac, code as follows:, the funcation proxy_tcp_unregistered,proxy_tcp_attach,proxy_tcp_detach are empty funcation which do nothing
const static struct sflt_filter tcp_filter =
{
PROXY_TCP_FILTER_HANDLE,
SFLT_GLOBAL,
BUNDLE_NAME,
proxy_tcp_unregistered, //do nothing
proxy_tcp_attach, //do nothing
proxy_tcp_detach, //do nothing
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
kern_return_t kerntest_start(kmod_info_t * ki, void *d)
{
sflt_register(&tcp_filter, PF_INET, SOCK_STREAM, IPPROTO_TCP);
return KERN_SUCCESS;
}
kern_return_t kerntest_stop(kmod_info_t *ki, void *d)
{
sflt_unregister(PROXY_TCP_FILTER_HANDLE);
return KERN_SUCCESS;
}
And use a shell to test, after about 50 times load, unload(kextload and kextunload), the Mac Kernel Panic happened:
*** Panic Report ***
panic(cpu 3 caller 0xffffff8009a065ea): Kernel trap at 0xffffff7f8c775ba0, type 14=page fault, registers:
....
Fault CR2: 0xffffff7f8c775ba0, Error code: 0x0000000000000010, Fault CPU: 0x3, PL: 0
Backtrace (CPU 3), Frame : Return Address
.....
Kernel Extensions in backtrace:
xxxx.xxxx.proxy.hook(1.0)[7A521823-D1CF-353E-93CA-0345CD6F5454]@0xffffff7f8c771000->0xffffff7f8c777fff
kmod dependency scan stopped due to missing dependency page: 0xc0ffee570a4457da
BSD process name corresponding to current thread: kernel_task
Mac OS version:
16B2555
Kernel version:
Darwin Kernel Version 16.1.0: Thu Oct 13 21:26:57 PDT 2016; root:xnu-3789.21.3~60/RELEASE_X86_64
Kernel UUID: 8941AC1C-B084-37DE-8A34-4CE638C5CFC9
Kernel slide: 0x0000000009600000
...
System uptime in nanoseconds: 28211489690166
last loaded kext at 28211416923440: com.test.kextext 1.0 (addr 0xffffff7f8c778000, size 40960)
last unloaded kext at 28211489331506: com.test.kextext 1.0 (addr 0xffffff7f8c771000, size 28672)
loaded kexts:
com.test.kextext 1.0
com.apple.filesystems.smbfs 3.1
What did i should do to deal with this, it not happend all the time.
If you look at the documentation for
sflt_unregister
, you'll notice 2 things:1:
The implication of this is that your callbacks can still be called after
sflt_unregister
returns. You need to properly clean up any sockets that might still be attached to your filter before you allow the kext to be unloaded.2:
You probably shouldn't allow unloading the kext if unregistering fails. (And likewise, you probably shouldn't even try to unregister a filter for which registration originally failed during kext start.)