Signing modified binaries

Big Sur on the M1 processor seems to prevent modified binaries from running. For instance, a simple C hello world:
Code Block c
#import <stdio.h>
int main(void) {
printf("Hello World!\n");
}

If I compile this with Clang and run it, everything works as expected. However, if I go into a hex editor and change the 'H' => 'h' (or something else trivial), the kernel immediately sends a SIGKILL, i.e.
Code Block
➜ ~ ✗ ./a.out
[1] 943 killed ./a.out

This is expected, since modifying the binary's hex would invalidate the signature, but when I try to resign the executable, I get the following non-descipt error:
Code Block
➜ ~ ✗ codesign -s zbaylin a.out
a.out: the codesign_allocate helper tool cannot be found or used

From other posts I've seen online, this is often the result of codesign_allocate not being in one's path, but I know codesign_allocate is in my PATH, and I am able to sign unmodified executables, but any binary that has been modified refuses to sign.

Is this behavior documented anywhere, and would I be able to sign these executables? I should mention that all of this works on my 2019 MacBook Pro (x86, obviously), so I think it has something to do with the M1 in particular.
Post not yet marked as solved Up vote post of zbaylin Down vote post of zbaylin
4.4k views

Replies

I'm facing exactly this issue. Have you found a work-around for it?
Actually, the hack described in this changelist is working for me:

https://github.com/Homebrew/brew/pull/9102/files/4665bb8e663c6d0ef452f4c124742732c96f8fd6#diff-f7b3993a53e62a7bdff250c5b7b176cc03232622c2a3c9912a496a3f82211884

Specifically this:

Code Block
# If the codesigning fails, it may be a bug in Apple's codesign utility
# A known workaround is to copy the file to another inode, then move it back
# erasing the previous file. Then sign again.
#
# TODO: remove this once the bug in Apple's codesign utility is fixed
Dir::Tmpname.create("workaround") do |tmppath|
FileUtils.cp file, tmppath
FileUtils.mv tmppath, file, force: true
end

I don't think this is documented, but when I asked about it was told by an Apple employee that this is a result of caching behavior. Copying it to a new location and then back dirties the cache and allows codesign to work. I still think this is a bug that should be fixed (at a minimum provide better messaging), but that Feedback remains open.

I don't think this is documented

Actually this cames up as part of WWDC 2019 Session 703 All About Notarization. To quote slide 65:

Recommended Solution

Whenever you update a signed file, create a new file

We’ve seen folks try to get around this by setting com.apple.security.cs.disable-executable-page-protection, which is not the right answer.

Copying it to a new location and then back dirties the cache and
allows codesign to work.

Specifically, code signing information is hung off the vnode within the kernel, and modifying the file behind that cache will cause problems. You need a new vnode, which means a new file, that is, a new inode.

that Feedback remains open

What was your bug number?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Actually this cames up as part of WWDC 2019 Session 703 All About Notarization.

I took the info from that talk and rolled it into a new article, namely Updating Mac Software.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"