3 Replies
      Latest reply on Mar 25, 2020 3:33 AM by capella_markus
      capella_markus Level 1 Level 1 (0 points)

        Dear Apple folks,

         

        we develop a C++ application that depends on another 3rd party

        library which is installed under /Library/frameworks.

         

        This library is optionally loaded dynamically at runtime by a call to

        dlopen().

         

        So far, we have signed our application successfully with our

        Developer ID Application certificate.

        For notarization, we have enabled the hardened runtime option in our

        application signature process.

        With hardened runtime enabled, this library loading does not work

        anymore on MacOS 10.14 and 10.15.

         

        Following the Apple documentation and several developer forum threads

        I have already checked the following constraints:

         

        * The application is signed using a secure timestamp.

        * The application is signed without using the option 'deep'.

        * The 3rd party lib is signed by it's vendor with their Developer ID

          Application certificate.

        * The lib's deployment target is MacOS 10.9 or higher

          (LC_VERSION_MIN_MACOSX).

        * The lib's installation name is fixed under /Library/Frameworks.

          (LC_ID_DYLIB, calling otool -l on the lib, is this correct?).

        * As the lib uses another certificate than the application, the

          application enables the disable-library-validation entitlement.

          This has been checked via codesign -d --entitlements :- on the app.

        * Enabling all hardened runtime related entitlements for test purposes

          does not help.

         

        To be clear again:

        * A signed application without option 'hardened runtime' loads the lib

          successfully.

        * A signed application with option 'hardened runtime' enabled and all

          related entitlements enabled fails loading the lib.

         

        I do not see any relevant error messages so far:

        * If the application is executed from a terminal, it does not produce

          any error output.

        * The system log does not produce related messages (or I do not see them).

        * I do not see any dyld related messages (Where should I find them?).

        * codesign --verify --verbose=4 APP_BUNDLE says 'valid on disk'.

        * spctl --verbose?4 --assess --type execute APP_BUNDLE says 'accepted'.

         

        So, how can I gather more information from the system about why it

        forbids to load the lib?

        Do you have any other ideas for me?

         

        Thanks,

        -Markus

        • Re: Another library load fails with hardened runtime
          eskimo Apple Staff Apple Staff (13,385 points)

          how can I gather more information from the system about why it forbids to load the lib?

          In your app, call dlerror after the failure to what it thinks the problem is.  Then add a log point [1] immediately after the failure.  Then reproduce the problem and look in the system log immediately before your log point.  In many cases the kernel or syspolicyd will log info about why something failed.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

          [1] If you’re already using the system log, use that.  Otherwise it’s fine to use NSLog because this is temporary code for a test.

            • Re: Another library load fails with hardened runtime
              capella_markus Level 1 Level 1 (0 points)

              Ok, I am getting deeper into this ...

               

              New info:

              * dlerror() tells me 'image not found'.

              * I still do not see any related entries within system log.

                Especially syspolicyd keeps calm.

                Please see the attached log.

               

              I have currently 2 directions into which I investigate:

              1. Heterogenous IDE and toolchain setups for different modules

              2. Some dynamic link time resultion problem.

                 Perhaps MacOS searches for dylibs more restrictive with hardened

                 runtime enabled.

               

              1. IDE and toolchain

              Historically, we compile our application and some of it's libs using different

              toolchains.

              * The application itself is recompiled frequently using MacOS 10.14 and

                XCode 11.

              * Some of our wrapper libs are not compiled together with our

                application. These binaries have been compiled using older versions

                of MacOS and XCode (still need to investigate the exact versions).

                For the one wrapper dylib that fails loading the 3rd party lib from

                /Libraries/Frameworks, otool -l shows

                LC_VERSION_MIN_MACOSX Version 10.7, SDK 10.12

                This wrapper lib gets deployed within our bundle.

                Therefore it also gets signed with our Developer ID Application

                certificate.

               

              Finally our bundle and it's dependancies look like this:

               

              * BUNDLE/Contents/MacOS/APPLICATION

                LC_VERSION_MIN_MACOSX Version 10.10, SDK 10.15

                Signed with -o runtime + entitlements, using our certificate

               

              * BUNDLE/Contents/Framework/WRAPPER_DYLIB

                LC_VERSION_MIN_MACOSX Version 10.7, SDK 10.12

                Signed, using our certificate

               

              * /Libraries/Frameworks/FRAMEWORK_NAME.framework/Versions/A/3RD_PARTY_DYLIB

                LC_VERSION_MIN_MACOSX Version 10.9, SDK 10.12

                Signed, using 3rd party certificate

               

              Q: In a chain like this, do all the bundle's internal modules need an

                 LC_VERSION_MIN_MACOSX >= 10.9 or only the lib to be loaded from

                 outside of the bundle?

               

              Q: We need hardened runtime and entitlements only for the application,

                 not for the libraries, is this correct?

               

               

              2. Dynamic link time resultion

               

              The other thing I see is that the wrapper lib contains a field

              LC_LOAD_DYLIB with an incomplete (and therefore relative?) path:

              "FRAMEWORK_NAME.framework/Versions/A/3RD_PARTY_LIB_NAME"

              No @rpath or similar prefix variables, but also no absolute path.

               

              Q: Running with hardened runtime and loading libs from

                 /Libraries/Frameworks, do we need complete and absolute paths in

                 LC_LOAD_DYLIB?

               

              Thanks,

              -Markus