Mac M1 `cp`ing binary over another results in crash

Mac M1 `cp`ing binary over another results in crash

最近,我一直在观察一个问题,即在我的 M1 上将一个二进制文件复制到另一个二进制文件上而没有先将其删除。经过一些实验(在点击 this issue 之后),我想出了一个可重现的方法来在最新的 Big Sur 11.3 版本的 Apple 新硬件上解决这个问题。

在至少 运行 一次后将不同的二进制文件复制到另一个二进制文件上时会出现此问题。不确定是什么导致了这个问题,但它非常令人困惑并且可能会导致一些安全问题。

例如,这会产生错误:

> ./binaryA
# output A
> ./binaryB
# output B
> cp binaryA binaryB
> ./binaryB
Killed: 9 

设置

为了重现上述行为,我们可以创建两个包含以下内容的简单 C 文件:

// binaryA.c
#include<stdio.h>

int main() {
    printf("Hello world!");
}
// binaryB.c
#include<stdio.h>
const char s[] = "Hello world 123!"; // to make sizes differ for clarity

int main() {
    printf("%s", s);
}

现在,您可以 运行 以下命令并得到描述的错误(程序必须 运行 才能重现问题,因此 运行 使用下面的程序 是必须的):

> gcc -o binaryA binaryA.c
> gcc -o binaryB binaryB.c
> ./binaryA
Hello world!
> ./binaryB
Hello world 123!
> cp binaryA binaryB
> ./binaryB
Killed: 9

如您所见,binaryB 二进制文件不再有效。出于所有意图和目的,两个二进制文件是相等的,但一个 运行s 而一个不相等。两个二进制文件的 diff returns 什么都没有。

我假设这是某种签名问题?但这不应该是因为两个二进制文件都没有签名。

有人知道这种行为背后的理论吗?或者这是一个错误?另外,如果它是一个错误,我什至可以将其归档到哪里?

每当更新签名文件时,都需要创建一个新文件。

具体来说,代码签名信息(代码目录哈希)挂在内核中的vnode之外,修改那个缓存后面的文件会导致问题。你需要一个新的vnode,也就是说一个新的文件,也就是一个新的inode。记录在 WWDC 2019 Session 703 All About Notarization - 请参阅幻灯片 65。

这是因为 ARM M1 处理器上的 Big Sur 要求所有代码都经过有效签名(如果只是临时的),否则操作系统将不会执行它,而是在启动时将其杀死。