Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rcodesign does not work with go-made binaries that use cgo; getting __LINKEDIT isn't final Mach-O segment #17

Closed
igor-hnizdo opened this issue Sep 6, 2022 · 4 comments
Labels
apple-codesign apple-codesign crate and rcodesign CLI tool enhancement New feature or request

Comments

@igor-hnizdo
Copy link

rcodesign does not work on binaries, built with go, that use cgo.

To reproduce:

  1. clone this simple cgo example and on macos, do GOOS=darwin GOARCH=arm64 go build

https://github.com/igor-hnizdo/cgo-example

OR

get the binary from here

https://github.com/igor-hnizdo/cgo-example/releases/tag/v1

  1. rcodesign sign --p12-file <file> --p12-password-file <password> --code-signature-flags runtime cgo-example

expected:

everything works.

What I got:

registering signing key
automatically registered Apple CA certificate: Developer ID Certification Authority
automatically registered Apple CA certificate: Apple Root CA
using time-stamp protocol server http://timestamp.apple.com/ts01
automatically setting team ID from signing certificate: <skip>
signing cgo-example in place
signing cgo-example as a Mach-O binary
inferring default signing settings from Mach-O binary
preserving existing binary identifier in Mach-O
using team ID from settings
using code signature flags from settings
setting binary identifier to cgo-example
parsing Mach-O
signing Mach-O binary at index 0
Error: __LINKEDIT isn't final Mach-O segment
@igor-hnizdo
Copy link
Author

igor-hnizdo commented Sep 6, 2022

I have found this random thread

golang/go#11887

I tried to put -ldflags=-s to go build, which does "fix" the issue.

-s seems to do this

$ go tool link
...
-s  disable symbol table

However, that issue above should be fixed in go for about 7 years.

@igor-hnizdo
Copy link
Author

I tried "regular" Apple codesign, and it can sign the linked binary.

So, the issue is on rcodesign side.

igor-hnizdo referenced this issue in igor-hnizdo/trezord-go Sep 6, 2022
I have simplified signing and enabled notarization in docker
with rcodesign (a Rust-based tool, fully open-source; but it does connect to Apple servers for notarization).

This tool enables notarization and signing fully in Docker on any OS,
so it should work in CLI too.

There is some prep-work that needs to be done on Mac OS side and on Apple website;
but after that, the signing and notarization works automatically.

It's not directly relevant to this commit, but I think you can also use it on Trezor Suite;
a cursory glance there tells me that Trezor Suit is using electron-notarize, which needs to be run on Mac OS;
rcodesign does not need that.

Note that we need to use ldflags -s because of this issue of rcodesign
https://github.com/indygreg/PyOxidizer/issues/636
igor-hnizdo referenced this issue in igor-hnizdo/trezord-go Sep 6, 2022
I have simplified signing and enabled notarization in docker
with rcodesign (a Rust-based tool, fully open-source; but it does connect to Apple servers for notarization).

This tool enables notarization and signing fully in Docker on any OS,
so it should work in CLI too.

There is some prep-work that needs to be done on Mac OS side and on Apple website;
but after that, the signing and notarization works automatically.

It's not directly relevant to this commit, but I think you can also use it on Trezor Suite;
a cursory glance there tells me that Trezor Suit is using electron-notarize, which needs to be run on Mac OS;
rcodesign does not need that.

Note that we need to use ldflags -s because of this issue of rcodesign
https://github.com/indygreg/PyOxidizer/issues/636
igor-hnizdo referenced this issue in igor-hnizdo/trezord-go Sep 7, 2022
I have simplified signing and enabled notarization in docker
with rcodesign (a Rust-based tool, fully open-source; but it does connect to Apple servers for notarization).

This tool enables notarization and signing fully in Docker on any OS,
so it should work in CLI too.

There is some prep-work that needs to be done on Mac OS side and on Apple website;
but after that, the signing and notarization works automatically.

It's not directly relevant to this commit, but I think you can also use it on Trezor Suite;
a cursory glance there tells me that Trezor Suit is using electron-notarize, which needs to be run on Mac OS;
rcodesign does not need that.

Note that we need to use ldflags -s because of this issue of rcodesign
https://github.com/indygreg/PyOxidizer/issues/636
tsusanka referenced this issue in trezor/trezord-go Sep 7, 2022
I have simplified signing and enabled notarization in docker
with rcodesign (a Rust-based tool, fully open-source; but it does connect to Apple servers for notarization).

This tool enables notarization and signing fully in Docker on any OS,
so it should work in CLI too.

There is some prep-work that needs to be done on Mac OS side and on Apple website;
but after that, the signing and notarization works automatically.

It's not directly relevant to this commit, but I think you can also use it on Trezor Suite;
a cursory glance there tells me that Trezor Suit is using electron-notarize, which needs to be run on Mac OS;
rcodesign does not need that.

Note that we need to use ldflags -s because of this issue of rcodesign
https://github.com/indygreg/PyOxidizer/issues/636
@igor-hnizdo igor-hnizdo changed the title rcodesign does not work with go-made binaries that use cgo; getting __LINKEDIT isn't final Mach-O segment [apple-codesign] rcodesign does not work with go-made binaries that use cgo; getting __LINKEDIT isn't final Mach-O segment Sep 9, 2022
@indygreg indygreg transferred this issue from indygreg/PyOxidizer Sep 18, 2022
@indygreg indygreg added enhancement New feature or request apple-codesign apple-codesign crate and rcodesign CLI tool labels Sep 19, 2022
@indygreg indygreg changed the title [apple-codesign] rcodesign does not work with go-made binaries that use cgo; getting __LINKEDIT isn't final Mach-O segment rcodesign does not work with go-made binaries that use cgo; getting __LINKEDIT isn't final Mach-O segment Sep 19, 2022
@indygreg
Copy link
Owner

Thank you for the detailed bug report!

Since Apple's tooling supports this scenario and CGO is kind of popular, we should definitely try to make this work.

Our logic for embedding code signatures in Mach-O binaries is somewhat conservative, as we don't want to be in the business of implementing a fully-featured Mach-O linker. That's why there are various assertions and limitations sprinkled throughout.

For the sample binary you pointed me at, the Mach-O segment layout is thus:

segment #0; __PAGEZERO; offsets=0x0-0x0; vm/file size 4294967296/0; section count 0
segment #1; __TEXT; offsets=0x0-0xb0000; vm/file size 720896/720896; section count 7
segment #2; __DATA_CONST; offsets=0xb0000-0x128000; vm/file size 491520/491520; section count 6
segment #3; __DATA; offsets=0x128000-0x140000; vm/file size 311296/98304; section count 5
segment #4; __LINKEDIT; offsets=0x1cc000-0x1ed3b2; vm/file size 136114/136114; section count 0
segment #5; __DWARF; offsets=0x140000-0x1cbc5c; vm/file size 0/572508; section count 12

The segment order in the Mach-O headers defines __LINKEDIT before __DWARF. But if you look at the file offsets, __DWARF actually comes before __LINKEDIT!

If __LINKEDIT wasn't the final segment in file order, this would be concerning, as the code signature inside the __LINKEDIT segment is supposed to be the final meaningful data in a Mach-O binary. (In reality I think you can sneak extra data after the code signature - but I'm unsure under what circumstances the Mach-O runtime loader and other OS level primitives will allow this, as it is a security issue.)

But since in this case it is only the segment definition order that is out-of-order, I think we're fine and this is simply a case of the logic checking for the segment order checking the definition order instead of the more semantically correct file order.

I think it should be safe for us to simply update the logic checking the segment order and this should just work. But I also wouldn't be surprised if the Mach-O rewriting code made assumptions about the segment definition order. So we need to check for that as well.

Thanks again for the bug report!

@igor-hnizdo
Copy link
Author

I did not upload you the signed binary if I sign by Apple own codesign; I don't want to do that as there are info I don't want to share (sorry). But you can do that yourself :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
apple-codesign apple-codesign crate and rcodesign CLI tool enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants