在 High Sierra 上,第二次安装带有有效签名的 macOS Kext 被拒绝。

11

在已经安装了我的产品的机器上,第二次安装失败了,原因是 kext 签名被拒绝。

我在一些地方看到了相同的错误,例如:https://support.eset.com/kb6570,但即使在恢复模式下清除了 kext_policy 表并在下一次启动中手动批准了 kext,在设置 -> 安全性中,kext 仍然显示未批准。

例如,运行 kextutil 提供了以下输出:

Kalyan:~ KalyanPentakota$ sudo kextutil /Library/Extensions/mycompanyAT.kext/
Password:
Kext rejected due to insecure location: <OSKext 0x7f8e9ff02e20 [0x7fffa11c8af0]> { URL = "file:///Library/StagedExtensions/Library/Extensions/mycompanyAT.kext/", ID = "com.mycompany.at" }
Kext rejected due to insecure location: <OSKext 0x7f8e9ff02e20 [0x7fffa11c8af0]> { URL = "file:///Library/StagedExtensions/Library/Extensions/mycompanyAT.kext/", ID = "com.mycompany.at" }
Diagnostics for /Library/Extensions/mycompanyAT.kext:

数据库中的 kext 批准状态:
sqlite> select * from kext_policy;
XE2XNRRXZ5|jp.co.canon.bj.print.BJUSBLoad|1|Canon Inc.|8
KBVSJ83SS9|com.citrix.kext.gusb|1|Citrix Systems, Inc.|8
MK9BR98H51|com.mycompany.at|1|My Company Ltd|1

内核扩展证书验证:

Kalyan:~ KalyanPentakota$ codesign -dvv /Library/Extensions/mycompanyAT.kext/
Executable=/Library/Extensions/mycompanyAT.kext/Contents/MacOS/mycompanyAT
Identifier=com.mycompany.at
Format=bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=8179 flags=0x0(none) hashes=250+3 location=embedded
Signature size=4651
Authority=Developer ID Application: My Company Ltd (MK9BR98H51)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Signed Time=Jun 5, 2018 at 6:05:21 AM
Info.plist entries=22
TeamIdentifier=MK9BR98H51
Sealed Resources version=2 rules=13 files=1
Internal requirements count=1 size=212

我也尝试过删除/Library/StagedExtensions/Library/,但是它并没有改变任何东西。


我不知道这是否适用于10.13的kext授权,但我遇到了代码签名问题当使用cp在原地复制已签名可执行文件时。你是如何安装kext的?如果是通过pkg安装的,那就不应该有问题,如果你正在使用自定义机制,请考虑是否会影响kext授权系统。 - pmdj
另一个问题:是否已批准其他使用相同证书签名的内核扩展? - pmdj
大家好,所有的kext都使用相同的证书签名,并且该产品是使用标准pkg文件构建的。 - IdoT
嗯,恐怕我之前没有见过这个确切的错误。Kext授权“功能”确实给我们带来了很多麻烦,出现了一些不可重现的故障。由于您似乎在自己控制的机器上有一个可重现的案例,我建议您向苹果公司提交一个Radar和DTS事件,除非有人在这里解决了相同的问题。 - pmdj
3个回答

7
我遇到了同样的问题。
/Library/StagedExtensions文件夹的标志必须是“受限制的”:
ls -laO /Library/StagedExtensions/

drwxr-xr-x@ 4 root wheel restricted 128 Nov 15 2017 StagedExtensions

如果不行,请在恢复模式下尝试以下命令:

chflags -R restricted /V*/*/Library/StagedExtensions

重新启动并尝试安装kext驱动程序。


我不知道你是怎么想出来的,但它起作用了。由于公司的卷锁定,我无法在恢复模式下设置受限标志。然而,我通过以下步骤成功设置了标志:1)在恢复模式下禁用SIP 2)在正常模式下设置受限标志 3)在恢复模式下启用SIP - Anders Larsen
1
在使用磁盘工具挂载系统驱动器后,这对我起作用了。 - user2892047

4

这个解决方案目前已经解决了我们在生产中遇到的所有情况:

你需要在恢复模式下加载,禁用sip,重启,使kext缓存失效,再次在恢复模式下重启,然后重新启用sip。

详细步骤:

  1. 从苹果菜单中选择重新启动。
  2. 当您的Mac重新启动时,立即按住Command(⌘) + R键直到听到启动音。保持按住这些键直到出现苹果标志进入恢复模式。
  3. 计算机现在处于恢复模式。从苹果菜单中选择实用工具 -> 终端
  4. 运行命令:csrutil disable
  5. 从苹果菜单中选择重新启动。
  6. macOS加载完成后,在终端中打开并输入:sudo kextcache -invalidate /
  7. 如果你的kext位于非标准位置,请添加自定义kext路径,例如:
    sudo kextcache -invalidate /Library/MyApp/MyApp.kext
  8. 从苹果菜单中选择重新启动。
  9. 当您的Mac重新启动时,立即按住Command(⌘) + R键直到听到启动音。保持按住这些键直到出现苹果标志进入恢复模式。
  10. 计算机现在处于恢复模式。从苹果菜单中选择实用工具 -> 终端
  11. 运行命令:csrutil enable
  12. 从苹果菜单中选择重新启动。
  13. 现在应该可以运行你的kext了。

数据库中的 kext 状态是什么? - IdoT
我在加载Logitech Yeti Blue X驱动程序时遇到了问题。上面的步骤非常有效。谢谢。 - tachijuan

4

更新

至少有一种可能导致这个问题,现在已经确切知道了,请参见下面的更新(2020-04-10)


Kext rejected due to insecure location 并不意味着缺少签名。它在哪里说有关签名的信息?当签名是问题时,会明确提到。对我来说,该消息表示位置不安全。

您是否检查了 /Library/Extensions 的访问权限?如果权限过于开放,系统将拒绝使用 kextloadkextutil 加载内核扩展。文件夹 /Library/Extension 必须属于 root:wheel,只有 root 能够写入该文件夹。

同样适用于扩展的访问权限,它们是捆绑包(.kext),因此实际上是目录。它们必须属于 root:wheel,并且只有 root 可以对它们进行写入操作。

如果您查看 macOS 的源代码(是的,macOS 是广泛开放源代码的,人们往往会忘记这一点),您会发现此错误仅在一个地方抛出:

if (authOptions->requireSecureLocation) {
    if (!kextIsInSecureLocation(theKext)) {
        OSKextLogCFString(NULL,
                          kOSKextLogErrorLevel | kOSKextLogValidationFlag,
                          CFSTR("Kext rejected due to insecure location: %@"),
                          theKext);
        result = false;
        goto finish;
    }
}

现在kextIsInSecureLocation()非常简单:
Boolean
kextIsInSecureLocation(OSKextRef theKext)
{
    NSURL *url = (__bridge NSURL *)OSKextGetURL(theKext);
    if (!url) {
        return false;
    }
    return pathIsSecure(url.path);
}

同样适用于pathIsSecure():

Boolean
pathIsSecure(NSString *path) {
    Boolean is_secure = false;
    BOOL is_protected_volume = rootless_protected_volume(path.UTF8String) ? YES : NO;
    BOOL is_trusted_path = rootless_check_trusted_class(path.UTF8String, "KernelExtensionManagement") == 0 ? YES : NO;

    if (isSIPDisabled()) {
        // SIP is disabled so everything is considered secure.
        is_secure = true;
    } else if (!is_protected_volume) {
        // SIP is enabled and the volume is not protected, so it's insecure.
        is_secure = false;
    } else {
        // SIP is enabled and it is a protected volume, so it's only secure if it's trusted.
        is_secure = is_trusted_path;
    }
    return is_secure;
}

如果禁用SIP,任何路径都是安全的,启用SIP时,不支持SIP的卷永远不安全,否则似乎存在一些可信任的路径列表,我确定/Library/Extensions是这样一个可信任的路径,只要它的权限设置正确。

要检查您的卷是否支持SIP,请打开Disk Utility应用程序,选择您的启动卷并按下CMD+I。 一个窗口将打开,列出各种属性,其中之一应该是以下内容:

System Integrity Protection supported : Yes

如果显示为“否”,那么您肯定会遇到问题,但是我不知道具体是哪个问题,因为没有办法单独启用或禁用 SIP,我只能想象某些在网络上挂载的文件系统或卷可能无法支持 SIP。
更新(2018-07-31)
联系苹果后,他们给了我以下提示:
此外,如果有用的话,“sudo kextcache --clear-staging” 允许用户在不进入恢复模式的情况下清除 “/Library/StagedExtensions” 文件夹。
不确定是否可以解决类似情况下的问题,只是在这里与您分享这些信息。
更新(2020-04-10)
显然,“ls -alO@u /Library/Extensions”的输出应该像这样:
drwxr-xr-x 5 root wheel restricted 160 Oct 24 12:18 .
drwxr-xr-x@ 3 root wheel restricted 96 Mar 25 13:00 ..
com.apple.rootless 25
drwxr-xr-x 15 root wheel restricted 480 Oct 24 12:18 Extensions

但在某些受影响的系统上,它看起来像这样:

drwxr-xr-x 4 root wheel - 128 Apr 6 18:58 .
drwxr-xr-x 3 root wheel - 96 Apr 6 18:56 ..
drwxr-xr-x 13 root wheel - 416 Apr 6 18:57 Extensions

正如你所看到的,com.apple.rootless文件属性丢失,并且文件夹未被标记为restricted请注意,这是启用了SIP并且用户从未禁用过它的系统的输出结果。 不幸的是,恢复该属性是不可能的。该属性的值为:
# xattr -p com.apple.rootless /Library/StagedExtensions
KernelExtensionManagement

即使关闭了 SIP,仍然会执行以下命令失败:
sudo xattr -w com.apple.rootless KernelExtensionManagement \
    /Library/StagedExtensions

它返回[Errno 1] Operation not permitted。因此,如果这里其他人发布的一些解决技巧都不起作用(对于一些人来说,没有任何一个解决方法有效!),请准备重新设置系统,因为它严重损坏了,而这不是您的错,但苹果在这里没有提供任何帮助。


嘿@Mecki,感谢回复,所有位于/Library/Extensions目录下的文件夹都属于有效的所有权(root:wheel)。 - IdoT
@IdoT 请查看更新后的信息,也许由于某种原因您的音量不支持SIP。除非我能够访问rootless_check_trusted_class()的源代码,否则没有其他已知原因。 - Mecki
1
再次感谢,预料之中,在禁用 SIP 后,驱动程序已加载,然后重新启用 SIP 将导致它们无法再次加载。我的合作伙伴发现,如果您安装它们,禁用 SIP,然后使 kext 缓存失效,然后重新启用 SIP,则可以正确加载驱动程序,因此我怀疑这是缓存问题,而不是 SIP 的卷支持问题,无论如何,苹果有一个未解决的 bug,我会在这里更新一旦我收到回复。 - IdoT
@Idot,你的电脑型号是什么?有多位用户遇到了相似的情况。 - kainjow
@kainjow 这个问题出现在不同的机型和操作系统版本上,看起来是 kext 缓存中的一个 bug。尝试安装、重置 kext 缓存、重新启动并检查是否已加载。 - IdoT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接