网络内核扩展案例Mac内核恐慌

时间:2017-09-10 13:58:48

标签: objective-c macos kernel kernel-extension

我在Mac上编写了一个网络内核扩展,代码如下:,函数proxy_tcp_unregistered,proxy_tcp_attach,proxy_tcp_detach是空函数,什么都不做

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;
}

使用shell测试,在加载约50次后,卸载(kextload和kextunload),Mac内核恐慌发生了:

*** 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

我应该怎么做才能解决这个问题,它不会一直发生。

1 个答案:

答案 0 :(得分:1)

如果查看sflt_unregister的文档,您会注意到两件事:

1:

  

取消注册套接字过滤器。这不会脱离         套接字过滤器可以连接到所有套接字         时间,它只会阻止套接字过滤器的连接         任何新的插座。

这意味着在sflt_unregister返回后仍可以调用您的回调。在允许卸载kext之前,您需要正确清理可能仍附加到过滤器的任何套接字。

2:

  

成功时返回 0,否则发生错误。

如果取消注册失败,您可能不应该允许卸载kext。 (同样地,您可能甚至不应该尝试取消注册在kext启动期间最初注册失败的过滤器。)