Apple Silicon 上关于 CodeSign 的 bug 及解决方案

date
Jan 10, 2021
slug
m1-mac-code-sign-bug-fix
status
Published
tags
Apple
MacOS
summary
用基于 M1 处理器的 Mac 开发时遇到了这个问题。记录一下解决的过程
type
Post

现象

一个包含 JNI库的 Java 程序,jnilib 在修改一次后 Java 程序运行到调用 JNI 代码的部分就会被系统 SIGKILL
在系统的控制台里查看到的错误信息类似于:
Exception Type:        EXC_BAD_ACCESS (Code Signature Invalid)
Exception Codes:       0x0000000000000032, 0x00000001048bc440
Exception Note:        EXC_CORPSE_NOTIFY
Termination Reason:    Namespace CODESIGNING, Code 0x2Process:               java [14975]
Path:                  /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/bin/java
Identifier:            java
Version:               1.0 (11.0.9.1)
Code Type:             ARM-64 (Native)
Parent Process:        idea [11170]
Responsible:           idea [11170]
User ID:               501
Date/Time:             2021-01-06 14:06:05.231 +0800
OS Version:            macOS 11.1 (20C69)
Report Version:        12
Anonymous UUID:        BBD882B7-940B-9C71-996E-3EE7BC2270AE
Sleep/Wake UUID:       E94FED61-D91E-49B2-99A6-C34EFD728322
Time Awake Since Boot: 150000 seconds
Time Since Wake:       12000 seconds
System Integrity Protection: enabled
Crashed Thread:        2
Exception Type:        EXC_BAD_ACCESS (Code Signature Invalid)
Exception Codes:       0x0000000000000032, 0x00000001048bc440
Exception Note:        EXC_CORPSE_NOTIFY
Termination Reason:    Namespace CODESIGNING, Code 0x2

解决

网上搜了一下,大概就是说 jnilib 签名的问题。
查到了通过 codesign -s - libxxx.jnilib 重新签名应该可以解决。
然而,在执行 codesign 的时候报了错 the codesign_allocate helper tool cannot be found or used,这就让人有点迷惑了。
再看了一下系统控制台,codesign 调用codesign_allocate,然后 codesign_allocate 也因为签名问题被系统杀了??? 这系统简直六亲不认啊,这我该怎么办。
后来想到了把 SIP (System Integrity Protection)关掉,终于能正常替换使用 jnilib 了,快乐。。结果各种 iOS 就不让启动了,这方法不太好。

最终方案

后面终于搜到了 https://github.com/Homebrew/brew/issues/9082,看起来是一个操作系统的 Bug,只需要把 jnilib copy到一个新路径,然后 mv 回来,就能正常使用了,不需要把 SIP 关掉。(估计是因为 codesign 针对 inode,直接替换文件会复用原来的 inode)
写了一个简单的 zsh function 用来方便操作:
fixsign() {
  cp $1 $1.1
  mv $1.1 $1
  codesign -s - $1
}
以后在 shell 里只需要 fixsign libxxx.jnilib 就可以了。

© yooyi 2020 - 2021