In macOS Mojave, Apple has introduced support for Hardened Runtime. (This is fully explained somewhere in the WWDC 2018 slides, but I cannot right now find exactly where.) One of the hardening mechanisms is a limitation on JIT techniques. It is still fully possible and supported, but the MAP_JIT flag must be passed to mmap() calls, and a specific entitlement must also be present in the code signature. Would it be possible for, when running on or deploying for macOS Mojave or later, to inject this entitlement automatically (similar to what we do with entitlements required for debugging), and to adjust Mono to use the appropriate flag?
This is currently not that high-priority a task, because use of Hardened Runtime is currently optional (and unsupported on macOS High Sierra and earlier). However, Apple has indicated that it will become mandatory for Developer ID apps in a future macOS update; also, apps that are submitted to Apple to be notarized must have Hardened Runtime enabled, effective immediately. Thanks!
Vital for us is to identify what the performance of this new API is. Our JIT is only just barely better than our AOT backend. It sounds like they're adding a lot of overhead. If it's bad enough, it'll make more sense to do AOT+interp. We should measure before we commit to it.
A quick look into this suggests at least two sets of changes will be needed:
I've filed https://github.com/mono/mono/issues/9210 for mono to look into their part. Once that is done, we can look at the entitlement (since we can't test it without the runtime JIt actually working).
Thanks for the Issue!
We also have AOT available in XM today, but unless you enable Hybrid we still JIT in places.
Good point about performance. I checked https://asciiwwdc.com/ but I couldn't find the session in question easily.
Found it! It's WWDC 2018 session 702, "Your Apps and the Future of macOS Security." It hasn't yet been transcribed, so that's why searching asciiWWDC found nothing.
Furthermore, as far as I can tell, there should be no performance impact compared to prior macOS versions, assuming mmap() is already being used. It's simply another flag you pass to the syscall alongside MAP_PRIVATE or MAP_ANON. In fact, the symbol is already present in the macOS 10.13 SDK in Xcode 9.4.1.
https://developer.apple.com/videos/play/wwdc2018/702/ 20 minute mark.
While some of this still is in research, I believe the following task list is needed for the hardened runtime support:
After all of that lands, we can look into the notary feature.
I've created a "hand-crafted" app by:
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
-o runtimeWhich crashes (as expected) on launch. I'm now testing with MAP_JIT enabled mono with:
CODE SIGNING: 23936[ManangedHardTime] vm_map_enter: curprot cannot be write+execute. failing
The MAP_JIT patch is in 2018-08, 2018-10, and master.
I tested with the latest package off of 2018-08:
-o runtimeSo we are through the test hand crafted stage, we need to add support to msbuild \ IDE for the various entitlements, but users that are comfortable with command line hacking could make it work if they use a sufficiently new mono (master is not on -08+ yet, so it'd be a custom build or system mono).
@chamons Where are we on this at this moment for Xamarin.Mac projects? I can see the MAP_JIT flag is done for mono.
@xfortin-devolutions We have sufficient infrastructure that you can enable the hardened runtime in your project if you don't mind using a text editor \ signing again by hand.
The following are required:
<key>com.apple.security.cs.allow-jit</key>
<true/>
-o runtime argumentThe work to fully complete finish and complete this is on our backlog. We just have not completed it yet.
Thanks for the info. Should be feasible. I'm not sure about using a development version of Xamarin though. Do we have an idea on when those changes will trickle down to a released version?
Hardened runtime requires mono changes, as you found, and those are only in the latest bits.
16-0 is in the early stages of preview (we just had the first preview) and I don't have a release date yet to share. I would expect something in the order of months.
The change to use MAP_JIT in Mono regressed a few scenarios:
https://github.com/mono/mono/issues/13445
So we are going to need Mono to surface an API to toggle MAP_JIT on, and the MacOS launcher will need to enable that before launching Mono.
I am looking at PRing Miguel's launcher patch, landing when https://github.com/mono/mono/pull/13446 lands.
I polished up @migueldeicaza 's patch but I can't PR it until we have a mono that supports that option (all tests fail with Unknown command line option: '--use-map-jit').
Living here for now - https://github.com/chamons/xamarin-macios/pull/new/xm_jit_patch
Looks like my app won't make it into the Mac app store so I'd like to get it notorized. I'd be happy to try this out and give feedback prior to it being merged into the main branches.
@DamianMehers So the steps are roughly listed here:
https://github.com/xamarin/xamarin-macios/issues/4288#issuecomment-454053834
Let me break it down in a bit more detail:
<key>com.apple.security.cs.allow-jit</key>
<true/>
is added.
You can poke me on https://gitter.im/xamarin/xamarin-macios if you have questions, since you are testing a new feature.
@chamons my app is built on Windows and I just update the MonoBundle contents of the bundle on each update, how could I notarize it? Thanks in advance.
@DanWBR Notarization must be done from a Mac, so you'll need to copy your finished bundle there. The programs you鈥檒l need are part of the Xcode tools; look at the manpages for altool(1) and stapler(1). Unfortunately, I鈥檝e never notarized an app by hand using these tools, so I can鈥檛 tell you how to use them in any more detail. Hope this helps!
@DanWBR you can get the standard help that you'd expect from a manpage with xcrun altool -h and xcrun stapler -h. This page is also pretty helpful in describing how to use altool and stapler
Thanks @wjk and @rajivshah3 I've read the info about altool and stapler, but I'm wondering if I need to create a new Xamarin.Mac project and compile my bundle from scratch, since the procedure in here involves updating the csproj file, assuming that you're creating the bundle from a Xamarin.Mac project in macOS.
If the whole procedure to make my existing app bundle notarizable involves just updating Xamarin.Mac.dll and the info.plist file, then I'm ok with that. On the other hand, if it somehow modifies the MacOS/Launcher.exec file, then I'll be in trouble, I guess.
Two days ago I've tried to upload my app to the Mac App Store but got a lot of errors regarding some native libs which support i386 and shouldn't (including libMonoPosix), etc etc... makes me wonder if a XamMac app can still be distributed in the App Store these days.
@DanWBR - XamMac apps, which by definition are 32-bit, can not be distributed on the App Store. Apple is rejecting all 32-bit apps. Full stop.
This documentation may be useful in updating your apps.
Folks I created https://github.com/xamarin/xamarin-macios/issues/5896 to more directly talk about the notary support and status. I'll have it updated with status and steps I used shortly.
@wjk / @rajivshah3 - See #5896 where I have the invocation I used to test things out. Let me know (on that issue) if you are having any troubles.
@chamons In an earlier comment you mentioned that after providing the necessary entitlements (sandbox, jit, read-only files) the app crashed on launch, which was 'as expected'.
Is this because it wasn't notarized yet, implying that, once hardened AND notarized, it won't crash. Is that correct? (apologize for the noub question).
Correct, I was comparing two builds:
Without those change, we should and did crash on launch. With those changes, we were able to launch successfully. It matched my expectations that we needed those changes to opt into the hardened runtime.
The blog post may have some useful information for you if you're just getting started on this topic.
@chamons I've started looking at Notarizing our app, so as a first step I tried signing it with the hardened runtime (manually, using codesign --option runtime). I expected it to crash as I haven't specified any entitlements at all, however it seems to run without any issues.
You noted above your test app crashed as expected - any idea why I am not seeing the same behaviour on my end?
Thanks
(It's a Developer ID app, using Xamarin.Mac 5.2.1.16)
I would check activity monitor to confirm you are running under the hardened runtime. Without passing in the entitlements, your option might be ignored?
@chamons Regarding my earlier comment about crashing on launch, I forgot to mention the app is not going into the app store. It crashed because I had listed the sandbox entitlement. Once I removed the sandbox entitlement and included the following:
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
then notarize and staple the app, it launches successfully.
All done command-line via terminal.
Thank you for your quick reply! Cheers.
Similar to @gcadmes above, I was getting launch crashes on the macOS 10.14.5 beta until I added those additional entitlements (wasn't using sandbox anyway)
@DamianMehers So the steps are roughly listed here:
Let me break it down in a bit more detail:
- Enable Code Signing
Install Xamarin.Mac from d16-1
- You can mostly get this working on stable \ d16-0 but it involves more manual steps.
- Open mac signing build tab and make sure you have an entitlement file listed
- Open that entitlement and make sure:
<key>com.apple.security.cs.allow-jit</key> <true/>is added.
- Open your csproj and in the release section add `true
- Run your release app and try it out.
You can poke me on https://gitter.im/xamarin/xamarin-macios if you have questions, since you are testing a new feature.
Thanks - I got it working and detailed all the steps here https://damian.fyi/2019/07/30/build-notarize-repeat/ On reflection the title is more negative than intended ... I just spent a day building, submitting to be notarized, being rejected and trying again ... it reminded me of the movie/book "Live, Die, Repeat" AKA "The Edge of Tomorrow" ... but I got it working in the end and thought I'd share my learnings.
My App keeps crashing on startup after turning "Hardened Runtime" on, even after the App is notarized. Earlier in this topic App crashes were mentioned, but this doesn't seem to be the same.
I tried the suggestions of @gcadmes , but still get the startup crash.
Here is the crashlog that shows what I get:
crashlog.txt
Just to be clear, turning "Hardened Runtime" off makes the crash go away.
Anyone has insight into this crash?
Where the crashes reported here earlier the same?
@mbmleone This github issues isn't exactly the best place to ask for help on this. If your application is failing with hardened runtime enabled, you likely need additional entitlements disabling the part you are hitting.
0 com.leonemusicreader.MusicReader5 0x00000001080ffc2a mono_arch_create_sdb_trampoline + 122
Suggests either a JIT or a debugging one is needed.
@chamons
My app is failing for the same reason as @mbmleone
0 com.leonemusicreader.MusicReader5 0x00000001080ffc2a mono_arch_create_sdb_trampoline + 122
@mbmleone Did it work for you?
@chamons @prathusingh The suggestion didn't work for me. I have tried to enable many options in entitlements, but have not yet found any that helps.
Folks, without a concrete sample showing specifically what you are doing, it will be almost impossible to help you figure out what's wrong.
The general use case of "Xamarin.Mac apps working with Hardened Runtime / Notarization" works however, and so I'm going to close this issue. Please feel free to open specific new issues with steps to reproduces / samples.