Closed cstkingkey closed 10 months ago
Which version of rcodesign is this? We had some bugs in this area in earlier releases that should now be fixed. Steps to reproduce would be greatly appreciated. You can email/dropbox/gdrive a binary to me at gregory.szorc@gmail.com.
Which version of rcodesign is this? We had some bugs in this area in earlier releases that should now be fixed. Steps to reproduce would be greatly appreciated. You can email/dropbox/gdrive a binary to me at gregory.szorc@gmail.com.
the version is 0.22.0. the binary is sent to your email. the issue is present with am64 binary, not with aarch64 binary.
I received the binary and can reproduce the failure. Thank you so much!
OK I see what is happening.
Here are the initial Mach-O segments in your binary:
segments count: 4
segment #0; __PAGEZERO; offsets=0x0-0x0 (0-0); addresses=0x0-0x100001000; vm/file size 4294971392/0; section count 0
segment #1; __TEXT; offsets=0x1000-0x458000 (4096-4554752); addresses=0x100001000-0x100458000; vm/file size 4550656/4550656; section count 12
segment #1; section #0: __text; offsets=0x1300-0x32c880 (4864-3328128); addresses=0x100001300-0x10032c880; size 3323264; align=6; flags=2147484672
segment #1; section #1: __stubs; offsets=0x32c880-0x32d144 (3328128-3330372); addresses=0x10032c880-0x10032d144; size 2244; align=1; flags=2147484680
segment #1; section #2: __stub_helper; offsets=0x32d144-0x32dff0 (3330372-3334128); addresses=0x10032d144-0x10032dff0; size 3756; align=2; flags=2147484672
What's happening is that when we finish writing out the Mach-O header and load commands, we're at 0x1060 / 4192. But the __TEXT segments begins at 0x1000 and that is tripping up our code validating that segments don't overlap.
Most Mach-O binaries I've seen have TEXT begin at 0x0 and they leave plenty of space for an additional LC_CODE_SIGNATURE if needed. Yours leaves enough space before the text section but the __TEXT segment begins at 0x1000.
I suppose we need to tweak the logic to look at the section offsets.
Out of curiosity, can you share details on how this binary was built/linked? I'm just curious what tools in the wild are emitting __TEXT segments in this manner.
OK I see what is happening.
Here are the initial Mach-O segments in your binary:
segments count: 4 segment #0; __PAGEZERO; offsets=0x0-0x0 (0-0); addresses=0x0-0x100001000; vm/file size 4294971392/0; section count 0 segment #1; __TEXT; offsets=0x1000-0x458000 (4096-4554752); addresses=0x100001000-0x100458000; vm/file size 4550656/4550656; section count 12 segment #1; section #0: __text; offsets=0x1300-0x32c880 (4864-3328128); addresses=0x100001300-0x10032c880; size 3323264; align=6; flags=2147484672 segment #1; section #1: __stubs; offsets=0x32c880-0x32d144 (3328128-3330372); addresses=0x10032c880-0x10032d144; size 2244; align=1; flags=2147484680 segment #1; section #2: __stub_helper; offsets=0x32d144-0x32dff0 (3330372-3334128); addresses=0x10032d144-0x10032dff0; size 3756; align=2; flags=2147484672
What's happening is that when we finish writing out the Mach-O header and load commands, we're at 0x1060 / 4192. But the __TEXT segments begins at 0x1000 and that is tripping up our code validating that segments don't overlap.
Most Mach-O binaries I've seen have TEXT begin at 0x0 and they leave plenty of space for an additional LC_CODE_SIGNATURE if needed. Yours leaves enough space before the text section but the __TEXT segment begins at 0x1000.
I suppose we need to tweak the logic to look at the section offsets.
Out of curiosity, can you share details on how this binary was built/linked? I'm just curious what tools in the wild are emitting __TEXT segments in this manner.
I‘m using osxcross (https://github.com/tpoechtrager/osxcross.git) with clang 17.0.2 with centos as the host, which is specified as the linker in the rust toolchain.
I added a failing test reproducing the failure then made a code change to hopefully fix this. I confirmed the binary you sent me now appears to sign correctly. However, codesign -v
is saying it isn't signed correctly. I'll need to look into this further.
it's the cargo strip option causing the issue. Macos refuse to run the binary complaining it's malformed, though the codesign can sign the binary without error.
@cstkingkey I recently encountered an issue using rust's built-in strip when cross-compiling from linux to macos: https://github.com/rust-lang/rust/issues/114411 . I believe you're encountering the same issue.
Essentially, cargo will simply run strip path/to/binary
when stripping a Mach-O, but that obviously fails on linux where the strip binary is from GNU binutils and only works on ELFs. Worse: The GNU binutils version of strip will sometimes still try to strip the MachO, and corrupt it in the process.
When cross-compiling from linux to macos, it's safer to strip the binary yourself, outside of the cargo command.
Oh interesting. So you are saying the Mach-O binary is already corrupted in the email you sent me? If so, should we close this issue?
today I run into this error: Error: error writing Mach-O: Mach-O segment corruption: cursor at 0x1060 but segment begins at 0x1000 (please report this bug)