- fsignatures_t siginfo;
- siginfo.fs_file_start=offsetInFatFile; // start of mach-o slice in fat file
- siginfo.fs_blob_start=(void*)(codeSigCmd->dataoff); // start of CD in mach-o file
- siginfo.fs_blob_size=codeSigCmd->datasize; // size of CD
- int result = fcntl(fd, F_ADDFILESIGS, &siginfo);
- if ( result == -1 )
- dyld::log("dyld: F_ADDFILESIGS failed for %s with errno=%d\n", this->getPath(), errno);
- //dyld::log("dyld: registered code signature for %s\n", this->getPath());
+ // if dylib being loaded has no code signature load command
+ if ( codeSigCmd == NULL ) {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ bool codeSigningEnforced = context.codeSigningEnforced;
+ if ( context.mainExecutableCodeSigned && !codeSigningEnforced ) {
+ static bool codeSignEnforcementDynamicallyEnabled = false;
+ if ( !codeSignEnforcementDynamicallyEnabled ) {
+ uint32_t flags;
+ if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) {
+ if ( flags & CS_ENFORCEMENT ) {
+ codeSignEnforcementDynamicallyEnabled = true;
+ }
+ }
+ }
+ codeSigningEnforced = codeSignEnforcementDynamicallyEnabled;
+ }
+ // if we require dylibs to be code signed
+ if ( codeSigningEnforced ) {
+ // if there is a non-load command based code signature, use it
+ off_t offset = (off_t)offsetInFatFile;
+ if ( fcntl(fd, F_FINDSIGS, &offset, sizeof(offset)) != -1 )
+ return;
+ // otherwise gracefully return from dlopen()
+ dyld::throwf("required code signature missing for '%s'\n", this->getPath());
+ }
+#endif
+ //Since we don't have a range for the signature we have to assume full coverage
+ fCoveredCodeLength = UINT64_MAX;
+ }
+ else {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ // <rdar://problem/13622786> ignore code signatures in binaries built with pre-10.9 tools
+ if ( this->sdkVersion() < DYLD_MACOSX_VERSION_10_9 ) {
+ return;
+ }
+#endif
+ fsignatures_t siginfo;
+ siginfo.fs_file_start=offsetInFatFile; // start of mach-o slice in fat file
+ siginfo.fs_blob_start=(void*)(long)(codeSigCmd->dataoff); // start of CD in mach-o file
+ siginfo.fs_blob_size=codeSigCmd->datasize; // size of CD
+ int result = fcntl(fd, F_ADDFILESIGS_RETURN, &siginfo);
+
+#if TARGET_IPHONE_SIMULATOR
+ // rdar://problem/18759224> check range covered by the code directory after loading
+ // Attempt to fallback only if we are in the simulator
+
+ if ( result == -1 ) {
+ result = fcntl(fd, F_ADDFILESIGS, &siginfo);
+ siginfo.fs_file_start = codeSigCmd->dataoff;
+ }
+#endif
+
+ if ( result == -1 ) {
+ if ( (errno == EPERM) || (errno == EBADEXEC) )
+ dyld::throwf("code signature invalid for '%s'\n", this->getPath());
+ if ( context.verboseCodeSignatures )
+ dyld::log("dyld: Failed registering code signature for %s, errno=%d\n", this->getPath(), errno);
+ siginfo.fs_file_start = UINT64_MAX;
+ } else if ( context.verboseCodeSignatures ) {
+ dyld::log("dyld: Registered code signature for %s\n", this->getPath());
+ }
+ fCoveredCodeLength = siginfo.fs_file_start;
+ }