我正在开发一种包含内核扩展的产品,并且在我们的一台测试机器中发现了一个我找不到解决方案的奇怪问题。
在我的开发机器(OSX 10.8.3 和最新的 Xcode)中,我像这样对我们的 kext 进行代码设计:
$ codesign -s "Developer ID Application: Mycompany" my.kext
my.kext: signed bundle with Mach-O thin (x86_64) [com.mycompany.kext]
一切正常,修改了 my.kext/Contents/MacOS/mykext 二进制文件(添加了签名),并创建了一个文件夹 my.kext/Contents/_CodeSignature,其中包含一个文件 CodeResources。
在我们的一台测试机器(OSX 10.7.5 和 Xcode 3.2.6,Darwin Kernel 11.4.2 x86_64)上加载这个 kext 时,它拒绝这样做:
kxld[com.mycompany.kext]: The Mach-O file is malformed: Invalid segment type in MH_KEXT_BUNDLE kext: 29.
Can't load kext com.mycompany.kext - link failed.
Failed to load executable for kext com.mycompany.kext.
Kext com.mycompany.kext failed to load (0xdc008016).
如果我加载未签名的模块,则没有问题。还尝试从 Xcode 而不是从命令行对 kext 进行签名,结果相同。
我将签名证书移到那台麻烦的计算机上,并在那里签署了 kext。签名过程有所不同:
$ codesign -v -s "Developer ID Application: Mycompany" my.kext
my.kext: signed bundle with generic [com.mycompany.kext]
签名后,my.kext/Contents/MacOS/mykext 中的 kext 可执行文件未修改,文件夹 Contents/_CodeSignature 包含更多文件:CodeDirectory、CodeRequirements、CodeResources 和 CodeSignature。到目前为止,这个签名的 kext 似乎适用于所有设备。
所以问题是:
这是怎么回事?我在签名过程中做错了什么?如何在可在此“过时”机器上运行的更新设备中创建签名?我知道目标机器拒绝加载 kext,因为它不理解签名的二进制文件。从此设备进行签名会创建某种分离的签名,其中二进制文件未被触及。我无法让我的 codesign 做到这一点, -D 选项似乎没用,并且不会在包中创建 _CodeSignature 文件夹。
更新
从 XCode 4.6 开始,问题仍然存在。只有 i386 kext 以向后兼容的方式签名。某些 10.6 和 10.7 内核无法加载 x64 和混合的 arch kext,因为它们不了解嵌入到二进制文件中的签名。
用于此目的的codesign命令行工具有一个未记录的--no-macho标志,但似乎未实现。
更新 2
从 Xcode 4.6.2 4.6.3开始,问题仍然存在