Skip to content

Check for room before touching the Mach-O header - #5

Open
TartanLeGrand wants to merge 7 commits into
xtool-org:masterfrom
TartanLeGrand:fix/check-space-before-write
Open

TartanLeGrand wants to merge 7 commits into
xtool-org:masterfrom
TartanLeGrand:fix/check-space-before-write

Conversation

@TartanLeGrand

@TartanLeGrand TartanLeGrand commented Oct 12, 2026 •

Copy link
Copy Markdown

What does this PR do?

Fixes two problems behind ">>> Can't find free space of LoadCommands for CodeSignature!", both in ZArchO:

  1. The free space was measured up to __text only. Init computed the room left after the load commands from the offset of the __text section. A binary without __text (for example an app extension whose code was dead-stripped) always reported zero, however much padding it had: with -headerpad_max_install_names and about 15 KB actually free, signing still failed. The room is now measured up to the first section with content in any segment (non-zero offset and size, so zerofill sections are ignored).
  2. The header was modified before the check. ReallocCodeSignSpace resized __LINKEDIT first and only then found out there was no room for LC_CODE_SIGNATURE. Since the header is a shared mapping of the file, a failure left a half-applied, corrupted header in the binary. The check now happens before the first write, and it compares against the size of the codesignature_command it writes (16 bytes) instead of 4.

This overlaps with #2, which addresses the first point (smallest gap over all sections); I left a note there. This PR also skips empty sections and fixes the second point. Happy to fold it into #2 or rebase on it, whichever you prefer.

How was it tested?

zsign has no test suite of its own; these run in xtool against hand-built Mach-O fixtures (SignerLayoutTests, part of xtool-org/xtool#326), with xtool depending on this branch (Linux x86_64, Podman):

  • A binary with too little room fails to sign, and its bytes are unchanged afterwards. Fails on zsign 1.9.0 (the header is modified), passes with this change.
  • A binary whose first section is not __text signs. Fails on 1.9.0, passes with this change.
  • xtool's full suite against a zsign branch combining this change with Apply per-bundle entitlements #3 and Sign with a single SHA-256 CodeDirectory #4.
  • swift build of the Zupersign target on this branch alone.

Not tested: the standalone zsign builds (linux/, macos/, windows/) and fat binaries specifically.

Known remaining edge: if writing the new file fails after the checks, the header edits already made through the mapping are not rolled back.

Developed with AI assistance; validated on device and against App Store Connect as described in #3 and #4.

kabiroberai and others added 7 commits September 20, 2026 05:13
ReallocCodeSignSpace resized __LINKEDIT (through the shared mapping, so in the file itself) before finding out that there was no room for LC_CODE_SIGNATURE, leaving a corrupted header behind on failure. Test for room first.

The room left by the load commands was measured up to the __text section only, so a binary without one always reported none, headerpad or not. Measure it up to the first section of any segment.
@TartanLeGrand TartanLeGrand mentioned this pull request Oct 12, 2026
3 tasks done
@coderabbitai

coderabbitai Bot commented Oct 12, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 66be8dbe-b0e1-45dd-9943-2eb177959916

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants