Skip to content

fix: strip at link time on macOS to keep arm64 signatures valid - #2000

Closed
klaustopher wants to merge 1 commit into
Return-To-The-Roots:masterfrom
klaustopher:fix/macos-arm64-signature
Closed

klaustopher wants to merge 1 commit into
Return-To-The-Roots:masterfrom
klaustopher:fix/macos-arm64-signature

Conversation

@klaustopher

@klaustopher klaustopher commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1998

CPack's strip step (CPACK_STRIP_FILES) runs strip -u -r after linking, which invalidates the ad-hoc signature the linker adds to arm64 binaries. Apple's strip re-signs, the cctools port in the osxcross image doesn't, so the arm64 slices of the universal nightly are rejected by macOS ("app is damaged").

This strips at link time instead (-Wl,-x -Wl,-S for Release), so the linker signs the already stripped binary, and disables CPACK_STRIP_FILES on Apple. No new tools needed in the docker image.

Tested natively on arm64 (Release, RTTR_BUNDLE=ON): s25client, s25edit, starter and both drivers pass codesign -v --strict.

Not tested inside the apple-docker image, so it would be great if the next nightly could be checked with codesign --verify -v on the arm64 slice, I can also do that if you don't have access to a mac.

CPack's strip step runs after linking and invalidates the ad-hoc
signature the linker adds to arm64 binaries. The cctools strip in the
osxcross image doesn't re-sign, so the arm64 slices of the universal
nightly are rejected by macOS. Strip via linker flags instead and
disable CPACK_STRIP_FILES on Apple.

Fixes Return-To-The-Roots#1998
@klaustopher

Copy link
Copy Markdown
Contributor Author

@Flow86 Flamefire suggested you as reviewer in #1998 since you did the apple.universal switch, but I can't request reviews on this repo. Could you take a look?

@Flow86

Flow86 commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

I would prefer fixing cctools strip instead of changing too much in some other places. I will have a look in the next days. Biggest issue is that I do not have access to an apple silicon device

@klaustopher

Copy link
Copy Markdown
Contributor Author

Also fine with this. Let me know if you need any verification on Apple Silicon Mac hardware

@Flow86

Flow86 commented Oct 24, 2026

Copy link
Copy Markdown
Member

Yes, I will tell you as soon as I have news to that. Thank you

@Flow86

Flow86 commented Oct 24, 2026

Copy link
Copy Markdown
Member

superseded by fc68502

Since we also use install_name_tool to fix the RPATHs in the bundles, I've added a step for codesign at the end of the apple bundle installation. Aswell as a signature verification step.
We now should get an information if a binary has an invalid (ad-hoc) signature and will fail the build.

I've added it in a way that it should support native codesign tool too (and ldid) but I can only test rcodesign for now

@Flow86 Flow86 closed this Oct 24, 2026
@klaustopher

Copy link
Copy Markdown
Contributor Author

I‘ll take a look at tomorrows nightly

@Flow86

Flow86 commented Oct 24, 2026

Copy link
Copy Markdown
Member

I've created a new nightly deployment, should be up any second. (broken signatures in an updater is always bad :-))

@klaustopher

klaustopher commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks! The arm64 slices of nightly 20261024-f23666865 now have valid signatures and the app runs natively once the quarantine flag is removed (xattr -dr com.apple.quarantine s25client.app).

Gatekeeper still rejects the downloaded bundle, though. starter, SDL2.framework and SDL2_mixer.framework were each signed as a single file, so they lack sealed resources (the code has no resources but the signature indicates they must be present).

I tested on a copy of the nightly: With slight modifications (moving share/ (RTTR data and docs) and rttr.terminal outside of the Contents/MacOS folder), I could generate a signed version of the application that only complained about an unverified developer.

With the current layout, it all gets broken already by the RTTR data in Contents/MacOS, and even more so as soon as we move the S2 resources into the Contents/MacOS bundle

$ cp -R /Volumes/S2_GOLD/DATA /Volumes/S2_GOLD/GFX s25client.app/Contents/MacOS/share/s25rttr/S2/
$ codesign --force --sign - s25client.app/Contents/Frameworks/SDL2.framework
$ codesign --force --sign - s25client.app/Contents/Frameworks/SDL2_mixer.framework

$ codesign --force --sign - s25client.app
s25client.app: code object is not signed at all
In subcomponent: …/Contents/MacOS/share/s25rttr/S2/DATA/MAPS/MISS202.WLD

$ codesign --force --deep --sign - s25client.app
s25client.app: bundle format unrecognized, invalid, or unsuitable
In subcomponent: …/Contents/MacOS/share/s25rttr/RTTR/assets/nations/Babylonians/jobs.bob

So for a real runnable arm64 bundle that Gatekeeper accepts, you would need to:

  1. Move the data out of Contents/MacOS (as described in macOS: move bundle data to Contents/Resources and S2 game files out of the app bundle #1999).
    • RTTR's data, the docs and rttr.terminal go to Contents/Resources.
    • The S2 files go to ~/Library/Application Support/Return To The Roots/S2 (or something similar), outside the bundle. Otherwise every user who adds S2 files breaks the seal again.
  2. Keep signing the individual binaries as the script already does. Then sign SDL2.framework and SDL2_mixer.framework as directories, and sign s25client.app last.
  3. And of course to get fully rid of all Gatekeeper warnings, the app has to be notarized by a paid Developer account. But that would be up to you if you want to go that far or live with the unverified warning.
Detailed output:

Running apple's codesign verification:

$ codesign --verify --strict --verbose=2 --arch arm64 s25client.app/Contents/MacOS/s25client
s25client.app/Contents/MacOS/s25client: valid on disk
s25client.app/Contents/MacOS/s25client: satisfies its Designated Requirement

Same results for:

  • Contents/MacOS/s25edit
  • Contents/MacOS/s25update
  • Contents/MacOS/libminiupnpc.2.3.3.dylib
  • Contents/MacOS/driver/video/libvideoSDL2.dylib
  • Contents/MacOS/driver/audio/libaudioSDL.dylib

But those are failing:

$ codesign --verify --strict --verbose=2 --arch arm64 s25client.app/Contents/MacOS/starter
s25client.app/Contents/MacOS/starter: code has no resources but signature indicates they must be present
$ codesign --verify --strict --verbose=2 --arch arm64 s25client.app/Contents/Frameworks/SDL2.framework/Versions/A/SDL2
s25client.app/Contents/Frameworks/SDL2.framework/Versions/A/SDL2: code has no resources but signature indicates they must be present
$ codesign --verify --strict --verbose=2 --arch arm64 s25client.app/Contents/Frameworks/SDL2_mixer.framework/Versions/A/SDL2_mixer
s25client.app/Contents/Frameworks/SDL2_mixer.framework/Versions/A/SDL2_mixer: code has no resources but signature indicates they must be present

Same for the bundled .frameworks and .app itself:

$ codesign --verify --strict --verbose=2 s25client.app/Contents/Frameworks/SDL2.framework
s25client.app/Contents/Frameworks/SDL2.framework: code has no resources but signature indicates they must be present
$ codesign --verify --strict --verbose=2 s25client.app/Contents/Frameworks/SDL2_mixer.framework
s25client.app/Contents/Frameworks/SDL2_mixer.framework: code has no resources but signature indicates they must be present
$ codesign --verify --strict --verbose=2 s25client.app
s25client.app: code has no resources but signature indicates they must be present

Running the gatekeeper check:

$ syspolicy_check distribution s25client.app
Only one signature found in file:///…/s25client.app, skipping dual signature check
App has failed one or more pre-distribution checks.
---------------------------------------------------------------
Codesign Error
    File: s25client.app
    Severity: Fatal
    Full Error: Code has no resources but signature indicates they must be
        present. Please re-sign using the latest version of macOS and codesign.
    Type: Notary Error
    Suggested Fix: Re-sign the application using the codesign command.
    Documentation:
        https://developer.apple.com/library/archive/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919

Adhoc Signed App
    Severity: Warning

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.

macOS universal nightly: arm64 code signatures are invalid, app is "damaged" on Apple Silicon

2 participants