Mac app under Xamarin. When setting "Enable Hardened Runtime", syncing fails

Pretty much summed it in the title I think.

I have a mac/ios/ipados app, built using C#/Xamarin.
On the mac app, if I set “Enabled Hardened Runtime” when building for release,
build succeeds and the app runs, BUT
when I enable syncing, I get the following error passed to the Change Listener for the replication.

The type initializer for 'Couchbase.Lite.Support.MacProxy' threw an exception.

It runs fine if that option is not enabled.
Is there some incompatibility there?
Thx.
Paul

Does this happen with .NET Core mac? Xamarin mac is not a supported platform. Anyway I’d ask this over at Xamarin as well, and try to get the inner exception from that one. A type initializer exception only provides very minimal information.

Thanks for getting back to me, and apologies for the brief report. More details follow, plus possible causes…

Yes this is Xamarin Mac. The inner exception is:

Unable to find or open library at /System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork

which is interesting because CFNetwork.framework doesn’t exist under CoreServices.framework.
It does exist at /System/Library/Frameworks/CFNetwork.framework.

Here is the stack trace:

  at Couchbase.Lite.Support.MacProxy.GetPointer (System.String libPath, System.String symbolName) [0x00015] in C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\Couchbase.Lite.Shared\Support\netdesktop\MacProxy.cs:106 
  at Couchbase.Lite.Support.MacProxy..cctor () [0x00000] in C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\Couchbase.Lite.Shared\Support\netdesktop\MacProxy.cs:42 

Looking in your source code on GitHub in MacProxy.cs, I see some hard coded paths:

private const string CFNetworkLibrary =
            "/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork";

        private const string CoreFoundationLibrary =
            "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";

That first path doesn’t match my system.

According to this website (which lists all of the versions of all MacOS APIs), it seems that at 10.6, CFNetwork did live underneath CoreServices.framework, but by 10.10 it was not. CFNetwork now appears directly under /System/Library/Frameworks..

If this is all true, then the hard coded path should be /System/Library/Frameworks/CFNetwork.framework....
I don’t know how this works when hardened is off… but it does :-).

And lastly… one more thing that could also be a cause:
Here’s a comment I found:

The hardened runtime requires library validation, which in turn only works for 10.9 and later. I’ve seen problems like this where the library contains no deployment target info, and things go badly from there.

Looking at the libLiteCore.dylib:

$ otool -l libLiteCore.dylib | grep LC_VERSION    
$ 

So there is no deployment target info. That too may or may not be a cause.

Cheers.
Paul.

All interesting information. I can change the hardcoded string to something new, but I’m not sure what’s going on with the version info. When I compile it myself the information is present. If you find out how to get it working (or notice it failing for .NET Core) then let me know!

@borrrden
.NET Core apps dont have a “hardened” option, so I dont think this will impact your supported software. I appreciate I am out on the limb here :slight_smile:.

Looking at the ~/.nuget/ packages folder, I have quite a history of libLiteCore.dylib. So I decided to check what versions included the flag.

2.1.2 and 2.1.5 definitely have LC_VERSION_MIN_MACOSX.
2.5.0 and forward do not. This includes the latest 2.7.1.

Here it is from 2.1.2:

Load command 8
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.13
      sdk 10.13

[hmmm… I should clean out nuget now and then…]

One further possibility as to what is causing the problem is DYLD variables.

By a process of elimination, it seems that the particular hardened check that needs to be disabled is this one:

Allow DYLD Environment Variables
Allows an application to be impacted by DYLD environment variables, which can be used to inject code into the process

https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-dyld-environment-variables

Turning that on (allow) means that the app works on my dev machine with hardened enabled in debug and release. Turning it off, the app fails. I haven’t tried moving the app to test machines via package builds yet…

Fun times!
Cheers.
Paul.