macOS:无法解析自定义内核扩展的符号
我正在尝试为 macOS catalina 10.15.7 和 XCode 12.4 构建自定义内核扩展,以访问第三方 USB-Wifi 适配器(带有 Atheros AR9271 芯片组的 Alfa Network AWUS036NHA)。 由于制造商并未正式支持 macOS Catalina 10.15 及更高版本,因此必须通过自定义 USB 驱动程序访问 Wifi dongle。
我发现了一个有前途的存储库,声称支持该芯片组: https://github.com/T1T4N/Atheros- AR9271。 构建内核扩展成功,但加载失败。
不管怎样,你几乎可以忽略背景,因为我认为这是最新 macOS 版本的自定义内核开发中的一个普遍问题。
有两种方法可以从不受信任的来源加载 kext。首先,通过完全或部分禁用 SIP
# in recovery mode:
$ csrutil disable
$ csrutil enable --without kext
;其次,通过将 TEAMID 添加到可信源,
$ codesign --display --verbose <name-of-kext>
# do this in recovery mode:
$ /usr/sbin/spctl kext-consent add <TEAMID>
我选择了第一个选项,暂时完全禁用了 SIP。我完全了解禁用 SIP 的后果,稍后将再次启用 SIP。
我要编译的驱动程序依赖于对 StandardUSB.h
库的以下函数调用。此标头是 IOKit kext 的一部分。
CleanAtheros.cpp
...
funcDesc = (const FunctionalDescriptorHeader *) StandardUSB::getNextDescriptorWithType(fInterface->getConfigurationDescriptor(), (const Descriptor *) funcDesc, CS_INTERFACE);
...
我成功编译了代码并尝试使用以下命令加载 kext:
$ sudo chmod -R 755 CleanAtheros.kext
$ sudo chown -R root:wheel CleanAtheros.kext
$ sudo kextutil -v CleanAtheros.kext
这给了我输出:
> Defaulting to kernel file '/System/Library/Kernels/kernel'
> Notice: /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext has debug properties set.
> Kext with invalid signature (-67050) allowed: <OSKext 0x7ff510d2f1b0 [0x7fff85288ce0]> { URL = "file:///Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext/", ID = "com.gubawang.AR9271.CleanAtheros" }
> Code Signing Failure: code signature is invalid
> /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext appears to be loadable (not including linkage for on-disk libraries).
> Loading /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext.
> Disabling KextAudit: SIP is off
> KextAudit initialized: audit=F
> (kernel) Notice - new kext com.apple.driver.usb.AppleUSBHostPlatformProperties, v1.2 matches prelinked kext but can't determine if executables are the same (no UUIDs).
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: The following symbols are unresolved for this kext:
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN11StandardUSB25getNextDescriptorWithTypeEPKNS_23ConfigurationDescriptorEPKNS_10DescriptorEh
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN15IOUSBHostDevice9metaClassE
> (kernel) Can't load kext com.gubawang.AR9271.CleanAtheros - link failed.
> (kernel) Failed to load executable for kext com.gubawang.AR9271.CleanAtheros.
> (kernel) Kext com.gubawang.AR9271.CleanAtheros failed to load (0xdc008016).
> (kernel) Failed to load kext com.gubawang.AR9271.CleanAtheros (error 0xdc008016).
> Failed to load /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext - (libkern/kext) link error.
> Failed to load /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext - (libkern/kext) link error.
> Check library declarations for your kext with kextlibs(8).
注意两个错误消息:
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: The following symbols are unresolved for this kext:
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN11StandardUSB25getNextDescriptorWithTypeEPKNS_23ConfigurationDescriptorEPKNS_10DescriptorEh
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN15IOUSBHostDevice9metaClassE
当我搜索丢失的符号时,我得到了定义这些符号的 kext 模块:
$ kextfind -dsym "__ZN11StandardUSB25getNextDescriptorWithTypeEPKNS_23ConfigurationDescriptorEPKNS_10DescriptorEh"
> /System/Library/Extensions/IOUSBHostFamily.kext
$ kextfind -dsym "__ZN15IOUSBHostDevice9metaClassE"
> /System/Library/Extensions/IOUSBHostFamily.kext
这似乎是没事。我已经验证该 kext 已加载:
$ kextstat | grep "com.apple.iokit.IOUSBHostFamily"
> 27 20 0xffffff7f8112e000 0xfa000 0xfa000 com.apple.iokit.IOUSBHostFamily (1.2) 14D49A36-567A-3AA7-9449-EA6615643E1A <26 25 24 8 7 6 5 3 1>
此外,正如上面的输出所建议的,我使用 kextlibs 检查了 kext 需要哪些内核扩展:
$ kextlibs CleanAtheros.kext
> For x86_64:
> com.apple.iokit.IOUSBHostFamily = 1.2
> com.apple.kpi.iokit = 19.6
> com.apple.kpi.libkern = 19.6
> For arm64e:
> No libraries found.
>
> 297 symbols not found in any library kext.
我不知道如何解决丢失的符号。 这些是我的问题:
- 我是否遗漏了一些明显的东西?
- 即使 SIP 已禁用,是否仍需要对 kext 进行签名?
- 如果是这样,我可以在没有苹果开发者帐户的情况下签署 kext 供个人使用吗?我尝试对其进行签名,但是,无论我做什么,错误都是
代码签名无效
。 - 我尝试将 IOUSBHost.framework 添加到项目中,因为缺少的符号也在该框架中定义。但是,仍然找不到符号,并且尝试对 kext 进行签名失败。
此外,以下是我更改构建设置的尝试:
希望,在这种情况下,任何人都比我有更好的洞察力......
I am trying to build a custom kernel extension for macOS catalina 10.15.7 and XCode 12.4 to access a third-party USB-Wifi dongle (Alfa Network AWUS036NHA with Atheros AR9271 chipset).
Since the manufacturer does not officially support macOS Catalina 10.15 and later versions, the Wifi dongle must be accessed via custom USB drivers.
I found a promising repository that claims support for this chipset: https://github.com/T1T4N/Atheros-AR9271.
Building the kernel extension succeeds, however, loading fails.
Anyway, you can pretty much ignore the background since I think this is a general problem in custom kernel development for latest macOS versions.
There are two ways of loading a kext from an untrusted source. First by completely or partially disabling SIP via
# in recovery mode:
$ csrutil disable
$ csrutil enable --without kext
or second, by adding the TEAMID to the trusted sources
$ codesign --display --verbose <name-of-kext>
# do this in recovery mode:
$ /usr/sbin/spctl kext-consent add <TEAMID>
I went with the first option and disabled SIP completely for now. I am fully aware of the consequences of disabling SIP and will later enable SIP again.
The driver, which I want to compile, relies on the following function call to the StandardUSB.h
library. This header is part of the IOKit
kext.
CleanAtheros.cpp
...
funcDesc = (const FunctionalDescriptorHeader *) StandardUSB::getNextDescriptorWithType(fInterface->getConfigurationDescriptor(), (const Descriptor *) funcDesc, CS_INTERFACE);
...
I successfully compiled the code and tried to load the kext with the following commands:
$ sudo chmod -R 755 CleanAtheros.kext
$ sudo chown -R root:wheel CleanAtheros.kext
$ sudo kextutil -v CleanAtheros.kext
This gave me the output:
> Defaulting to kernel file '/System/Library/Kernels/kernel'
> Notice: /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext has debug properties set.
> Kext with invalid signature (-67050) allowed: <OSKext 0x7ff510d2f1b0 [0x7fff85288ce0]> { URL = "file:///Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext/", ID = "com.gubawang.AR9271.CleanAtheros" }
> Code Signing Failure: code signature is invalid
> /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext appears to be loadable (not including linkage for on-disk libraries).
> Loading /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext.
> Disabling KextAudit: SIP is off
> KextAudit initialized: audit=F
> (kernel) Notice - new kext com.apple.driver.usb.AppleUSBHostPlatformProperties, v1.2 matches prelinked kext but can't determine if executables are the same (no UUIDs).
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: The following symbols are unresolved for this kext:
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN11StandardUSB25getNextDescriptorWithTypeEPKNS_23ConfigurationDescriptorEPKNS_10DescriptorEh
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN15IOUSBHostDevice9metaClassE
> (kernel) Can't load kext com.gubawang.AR9271.CleanAtheros - link failed.
> (kernel) Failed to load executable for kext com.gubawang.AR9271.CleanAtheros.
> (kernel) Kext com.gubawang.AR9271.CleanAtheros failed to load (0xdc008016).
> (kernel) Failed to load kext com.gubawang.AR9271.CleanAtheros (error 0xdc008016).
> Failed to load /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext - (libkern/kext) link error.
> Failed to load /Users/kesenheimer/tools/Atheros-AR9271/CleanAtheros.kext - (libkern/kext) link error.
> Check library declarations for your kext with kextlibs(8).
Note the two error messages:
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: The following symbols are unresolved for this kext:
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN11StandardUSB25getNextDescriptorWithTypeEPKNS_23ConfigurationDescriptorEPKNS_10DescriptorEh
> (kernel) kxld[com.gubawang.AR9271.CleanAtheros]: __ZN15IOUSBHostDevice9metaClassE
When I search for the missing symbols, I get the kext module where these symbols are defined:
$ kextfind -dsym "__ZN11StandardUSB25getNextDescriptorWithTypeEPKNS_23ConfigurationDescriptorEPKNS_10DescriptorEh"
> /System/Library/Extensions/IOUSBHostFamily.kext
$ kextfind -dsym "__ZN15IOUSBHostDevice9metaClassE"
> /System/Library/Extensions/IOUSBHostFamily.kext
which seems to be fine. I have verified that this kext is loaded:
$ kextstat | grep "com.apple.iokit.IOUSBHostFamily"
> 27 20 0xffffff7f8112e000 0xfa000 0xfa000 com.apple.iokit.IOUSBHostFamily (1.2) 14D49A36-567A-3AA7-9449-EA6615643E1A <26 25 24 8 7 6 5 3 1>
Additionally, as suggested by the output above, I checked with kextlibs which kernel extensions are needed by the kext:
$ kextlibs CleanAtheros.kext
> For x86_64:
> com.apple.iokit.IOUSBHostFamily = 1.2
> com.apple.kpi.iokit = 19.6
> com.apple.kpi.libkern = 19.6
> For arm64e:
> No libraries found.
>
> 297 symbols not found in any library kext.
I can not figure out how to resolve the missing symbols.
These are my questions:
- Am I missing something obvious?
- Is it necessary to have the kext signed, even though SIP is disabled?
- If so, can I sign a kext without an apple developer account for personal use? I tried signing it, however, no matter what I do the error is
code signature is invalid
. - I tried to add
IOUSBHost.framework
to the project, since the missing symbols are defined in this framework as well. However, the symbols can still not be found, and attempts to sign the kext fail.
Additionally, here are my attempts changing the build settings:
Hope, anyone has a better insight than me in this case...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
更新的答案:
所以,我最初假设这里有可在以前的 macOS 版本上运行的实际驱动程序代码。更深入地查看并跟踪源代码链接可以清楚地看出,这只是某人开始的驱动程序的代码片段,但他们显然没有走得太远。因此,此代码永远不会在任何版本的 macOS/OS X 上用作网络驱动程序。
链接器问题:
为了完整起见,直接链接问题源自列出
IOUSBFamily
(在 OS X 之前使用) 10.11) 在依赖项中:(link)
而实际代码使用更多现代但已弃用
IOUSBHostFamily
:(链接)
所以链接错误的解决方案是链接到
com.apple.iokit.IOUSBHostFamily
。在现代 macOS 上使用不受支持的网络设备的实际问题的解决方案是:
您需要基于
USBDriverKit
和NetworkingDriverKit
. 这个细节当然超出了 Stack Overflow 答案的范围。原始答案:(
实际上并没有错,但事实证明,这不是最大的问题。)
Xcode 12.4 附带 macOS 11.1 SDK。与用户空间不同,对于 kext,您应该使用您所定位的最旧 macOS 版本的 SDK。
根据 xcodereleases.com,Xcode 版本 12.1.1 是最后一个附带 10.15.x (10.15 .6 特别),所以在我看来,这是首先要尝试的事情:使用 Xcode 12.1.1 或旧版本来构建您的 kext。
是的,当旧版 Xcode 不再在现代版本的 macOS 上运行时,这可能会出现问题;除了简单地保留虚拟机或仍然运行兼容 macOS 版本的真实 Mac 之外,没有什么好的替代方案。尝试将较旧的 SDK 与较新的 Xcode 版本混合搭配往往会带来更多麻烦,而不是其价值(有时无论如何都不起作用)。
请注意,网络和 USB 系列内核 API 均已弃用,因此您可能会发现 kext 在更高版本的 macOS 中完全停止工作;您当然不能再在启用 SIP 的情况下使用它们。
关于代码签名:
这主要在之前的各种问题和答案中得到解决,例如:
本质上,您需要 Apple 提供的“开发者 ID”证书的特殊变体(现在他们很少授予该证书),并且随后需要对 kext 进行公证。不过,这两者都不会帮助您,因为您要链接到过时的内核 API,只有在禁用 SIP 的情况下才允许这样做,这反过来意味着无论如何都没有 kext 签名要求。
长期:
正如我所指出的,这可能是一个短期解决方案,但可能不适用于所有未来的 macOS 版本。最终,驱动程序需要移植到 DriverKit 才能继续使用它。
Updated answer:
So, I originally assumed there was actual driver code here that worked on previous macOS versions. Looking deeper and following the source code link makes it clear that this is just a fragment of code for a driver somebody started but with which they apparently didn't get very far. So this code will never have worked as a network driver on any version of macOS/OS X.
Linker issue:
For the sake of completeness, the immediate linking problem arises from listing
IOUSBFamily
(used prior to OS X 10.11) in the dependencies:(link)
whereas the actual code uses the more modern but already deprecated
IOUSBHostFamily
:(link)
So the solution for the link errors is to link against
com.apple.iokit.IOUSBHostFamily
instead.The solution to your actual problem of using an unsupported network device on modern macOS is:
You'll need to build a new driver from scratch, based on
USBDriverKit
andNetworkingDriverKit
. The details of this are of course outside the scope of a Stack Overflow answer.Original answer:
(Factually not incorrect, but as it turns out, not the biggest problem here.)
Xcode 12.4 ships with the macOS 11.1 SDK. Unlike in user space, for kexts, you should use the SDK for the oldest macOS version you are targeting.
According to xcodereleases.com, Xcode version 12.1.1 is the last to ship with an SDK for 10.15.x (10.15.6 specifically), so in my opinion that would be the first thing to try: use Xcode 12.1.1 or an older version to build your kext.
And yes, this can become problematic when the older Xcode version no longer runs on your modern version of macOS; there's no good alternative to simply keeping either a VM or real Mac around that still runs a compatible macOS version. Trying to mix and match older SDKs with newer Xcode versions tends to be more trouble than it's worth (and sometimes doesn't work anyway).
Note that both the networking and USB family kernel APIs are deprecated, so you might find that the kext stops working altogether in a later version of macOS; you certainly can no longer use them with SIP enabled.
Regarding code signing:
This has mostly been tackled in various previous questions and answers, e.g.:
Essentially, you need a special variant of "Developer ID" certificate from Apple (which they rarely grant these days), and you subsequently need to notarise the kext. Neither will help you though, as you're linking against obsolete kernel APIs, which is only allowed if SIP is disabled, which in turn means there is no kext signing requirement anyway.
Long term:
As I've pointed out, this may work as a short term solution, but probably won't work in all future macOS versions. Eventually, the driver will need to be ported to DriverKit to be able to continue using it.