Skip to content

apple-bundles: fix iOS framework signing#46

Closed
kabiroberai wants to merge 4 commits into
indygreg:mainfrom
kabiroberai:fix-ios
Closed

apple-bundles: fix iOS framework signing#46
kabiroberai wants to merge 4 commits into
indygreg:mainfrom
kabiroberai:fix-ios

Conversation

@kabiroberai

Copy link
Copy Markdown
Contributor

Submitted to this repo per indygreg/PyOxidizer#640 (comment).

@indygreg indygreg left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the fix!

@kabiroberai

Copy link
Copy Markdown
Contributor Author

fwiw you might wanna hold off on merging for a few minutes, adding a quick unit test for this

@indygreg indygreg closed this in 0617f8b Nov 8, 2022
@kabiroberai

Copy link
Copy Markdown
Contributor Author

@indygreg erm I probably should've run the existing tests too, because it looks like this breaks non-"shallow" frameworks. Mind reverting the merge so that I can patch those up?

@indygreg indygreg reopened this Nov 8, 2022
@indygreg

indygreg commented Nov 8, 2022

Copy link
Copy Markdown
Owner

Yeah, I just noticed it broke tests too :/

I reverted it on main and reopened the PR for you.

When you fix this up, feel free to cherry-pick the changelog updates from 0617f8b.

@dvc94ch

dvc94ch commented Nov 8, 2022

Copy link
Copy Markdown
Collaborator

can you elaborate on why you think signing frameworks doesn't work on ios? I've been signing flutter applications which include the flutter framework just fine.

@dvc94ch

dvc94ch commented Nov 8, 2022

Copy link
Copy Markdown
Collaborator

actually this looks like a regression. I made exactly the same change here: indygreg/PyOxidizer@main...dvc94ch:PyOxidizer:nested-frameworks

@kabiroberai

Copy link
Copy Markdown
Contributor Author

@dvc94ch iOS frameworks are structurally different from macOS frameworks, in that the only requirement is an Info.plist file inside the framework at the root level. While a macOS framework looks something like

Foo.framework/
  Resources/
    Info.plist

potentially with multiple nested versions, an iOS framework has the form

Foo.framework/
  Info.plist

This structure isn't correctly detected by apple-bundles, in turn leading to the framework being handled incorrectly in the CodeResources file. The unit tests that I add should hopefully illustrate the issue better.

@dvc94ch

dvc94ch commented Nov 8, 2022

Copy link
Copy Markdown
Collaborator

@indygreg rejected this change as incorrect indygreg/PyOxidizer#539 I'm pretty sure he was right although I don't remember the reason. can you show me all the "code" you're using? I'll try to figure out what the correct solution was.

@kabiroberai

Copy link
Copy Markdown
Contributor Author

I'm using this in a relatively large private project so unfortunately I can't share all the code atm, but you should be able to repro the issue by signing an iOS app with an embedded dynamic framework. I'll try to create a minimal reproducible example and share it here.

@dvc94ch

dvc94ch commented Nov 8, 2022

Copy link
Copy Markdown
Collaborator

can you try building with xbuild? if it builds with xbuild something else is wrong here: [0] although the signing part looks pretty boring, so don't see what mistake could have caused this [1]. so maybe there is something wrong.

@kabiroberai

Copy link
Copy Markdown
Contributor Author

Do you have a sample project I can test with xbuild? Also, is the Flutter framework dynamic or static?

@kabiroberai

Copy link
Copy Markdown
Contributor Author

SigningIssue.zip here's a sample project that fails to be signed correctly (just Xcode's SwiftUI template with an empty dynamic framework added). To verify this for yourself, try:

xcodebuild CODE_SIGNING_ALLOWED=NO
rcodesign sign build/Release-iphoneos/SigningIssue.app
codesign -vvvv build/Release-iphoneos/SigningIssue.app

@kabiroberai

Copy link
Copy Markdown
Contributor Author

looks like it's still signing incorrectly with my new changes (the old three-line diff was making it sign correctly, but it turns out it was erroneously identifying the .app as a BundlePackageType::Framework). Still working on modifying the new patch set to fix this, but it looks like there are indeed other bugs at play as well.

@dvc94ch

dvc94ch commented Nov 8, 2022

Copy link
Copy Markdown
Collaborator

what you're describing sounds awefully familiar.

@kabiroberai

Copy link
Copy Markdown
Contributor Author

Ah it looks like the other necessary change is to prevent framework digests from being included in the CodeResources of iOS app bundles, i.e. changing this line

if self.bundle.package_type() != BundlePackageType::Framework {

to

if !self.bundle.shallow() {

@kabiroberai

Copy link
Copy Markdown
Contributor Author

This seems to line up with what other tools like ldid do as well: https://github.com/ProcursusTeam/ldid/blob/f0b3af5c0336acf97f87c7f8984771224c8b3483/ldid.cpp#L3194-L3200

@dvc94ch dvc94ch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need some time to complete my investigation. most likely culprit (having experienced exactly the same issue) is that the rcodesign cli doesn't use the correct settings on ios.

@kabiroberai

Copy link
Copy Markdown
Contributor Author

Curious what you mean by "correct settings" — if you're referring to the fact that macOS and iOS have different base CodeResources rules then yeah I agree that's probably the root cause. Though the fact that iOS frameworks aren't recognized is definitely one of the issues at play.

FWIW with 4577b8e in place things seem to be working correctly on both iOS and macOS, though I can't be 100% sure that we haven't missed an edge case. Additionally, there are likely other signing issues on iOS that we're missing, but this PR is an incremental step that at least fixes the simple case of an app with a nested dynamic framework.

@dvc94ch

dvc94ch commented Nov 8, 2022

Copy link
Copy Markdown
Collaborator

well, I might be completely wrong but some git digging showed this:

  1. same fix was proposed
  2. fix was rejected as being wrong
  3. I managed to fix the issue in a different way

later you mentioned that the fix was actually wrong (erroneously identifying as a framework), I had the exact same thing. but I'm having a really hard time coming up with what the actual solution was.

the issue you're having is:

SigningIssue.app: a sealed resource is missing or invalid
file missing: SigningIssue.app/Frameworks/DummyLib.framework

and yes the flutter framework is a dynamic framework:

file Flutter.framework/Flutter
Flutter.framework/Flutter: Mach-O 64-bit arm64 dynamically linked shared library, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|BINDS_TO_WEAK|NO_REEXPORTED_DYLIBS|HAS_TLV_DESCRIPTORS>

@dvc94ch dvc94ch self-requested a review November 8, 2022 08:09
@dvc94ch

dvc94ch commented Nov 8, 2022

Copy link
Copy Markdown
Collaborator

well, I'm coming up empty. so if @indygreg thinks the changes make sense, they probably do.

@indygreg indygreg left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. The narrow scoping of the change should be low risk and fixes identification of iOS framework bundles.

As for why I rejected a similar change months ago, that's because bundle signing was completely broken at the time and the change didn't make sense in the context of everything is broken.

I'll patch this slightly locally to fix a merge conflict.

Thanks for the fix!

@indygreg indygreg closed this in c9227cd Dec 18, 2022
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.

3 participants