Loading...
dyld3/ClosureFileSystemPhysical.cpp dyld-733.8 dyld-852
--- dyld/dyld-733.8/dyld3/ClosureFileSystemPhysical.cpp
+++ dyld/dyld-852/dyld3/ClosureFileSystemPhysical.cpp
@@ -23,13 +23,12 @@
 
 #include "ClosureFileSystemPhysical.h"
 
+#include <TargetConditionals.h>
+
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
-#if BUILDING_UPDATE_DYLD_CACHE_BUILDER
-  #include <rootless.h>
-#endif
 #include <sys/errno.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -38,6 +37,9 @@
   #include <sandbox.h>
   #include <sandbox/private.h>
 #endif
+#include <TargetConditionals.h>
+#include "MachOFile.h"
+#include "MachOAnalyzer.h"
 
 using dyld3::closure::FileSystemPhysical;
 
@@ -45,7 +47,7 @@
     __block bool success = false;
     // first pass: open file and ask kernel for canonical path
     forEachPath(possiblePath, ^(const char* aPath, unsigned prefixLen, bool& stop) {
-        int fd = ::open(aPath, O_RDONLY, 0);
+        int fd = dyld3::open(aPath, O_RDONLY, 0);
         if ( fd != -1 ) {
             char tempPath[MAXPATHLEN];
             success = (fcntl(fd, F_GETPATH, tempPath) == 0);
@@ -110,6 +112,8 @@
     }
     if ( _rootPath != nullptr ) {
         strlcpy(altPath, _rootPath, PATH_MAX);
+        if ( path[0] != '/' )
+            strlcat(altPath, "/", PATH_MAX);
         strlcat(altPath, path, PATH_MAX);
         handler(altPath, (unsigned)strlen(_rootPath), stop);
         if ( stop )
@@ -144,9 +148,8 @@
     // open file
     __block int fd;
     __block struct stat statBuf;
-    __block bool sipProtected = false;
     forEachPath(path, ^(const char* aPath, unsigned prefixLen, bool& stop) {
-        fd = ::open(aPath, O_RDONLY, 0);
+        fd = dyld3::open(aPath, O_RDONLY, 0);
         if ( fd == -1 ) {
             int openErrno = errno;
             if ( (openErrno == EPERM) && sandboxBlockedOpen(path) )
@@ -183,9 +186,6 @@
                     }
                     else
                         strcpy(realerPath, realPathWithin);
-    #if BUILDING_UPDATE_DYLD_CACHE_BUILDER
-                    sipProtected = (rootless_check_trusted_fd(fd) == 0);
-    #endif
                     stop = true;
                 }
                 else {
@@ -217,7 +217,7 @@
     info.fileContentLen = statBuf.st_size;
     info.sliceOffset = 0;
     info.sliceLen = statBuf.st_size;
-    info.isSipProtected = sipProtected;
+    info.isOSBinary = false;
     info.inode = statBuf.st_ino;
     info.mtime = statBuf.st_mtime;
     info.path  = path;
@@ -240,6 +240,27 @@
     }
     info.fileContent = wholeFile;
 
+    // if this is an arm64e mach-o or a fat file with an arm64e slice we need to record if it is an OS binary
+#if TARGET_OS_OSX && __arm64e__
+    const MachOAnalyzer* ma = (MachOAnalyzer*)wholeFile;
+    if ( ma->hasMachOMagic() ) {
+        if ( (ma->cputype == CPU_TYPE_ARM64) && ((ma->cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) ) {
+            if ( ma->isOSBinary(fd, 0, info.fileContentLen) )
+                info.isOSBinary = true;
+        }
+    }
+    else if ( const FatFile* fat = FatFile::isFatFile(wholeFile) ) {
+        Diagnostics diag;
+        fat->forEachSlice(diag, info.fileContentLen, ^(uint32_t sliceCpuType, uint32_t sliceCpuSubType, const void* sliceStart, uint64_t sliceSize, bool& stop) {
+            if ( (sliceCpuType == CPU_TYPE_ARM64) && ((sliceCpuSubType & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) ) {
+                uint64_t sliceOffset = (uint8_t*)sliceStart-(uint8_t*)wholeFile;
+                const MachOAnalyzer* sliceMA = (MachOAnalyzer*)((uint8_t*)wholeFile + sliceOffset);
+                if ( sliceMA->isOSBinary(fd, sliceOffset, sliceSize) )
+                    info.isOSBinary = true;
+            }
+        });
+    }
+#endif
     // Set unmap as the unload method.
     info.unload = [](const LoadedFileInfo& info) {
         ::munmap((void*)info.fileContent, (size_t)info.fileContentLen);
@@ -257,11 +278,11 @@
 void FileSystemPhysical::unloadPartialFile(LoadedFileInfo& info, uint64_t keepStartOffset, uint64_t keepLength) const {
     // Unmap from 0..keepStartOffset and (keepStartOffset+keepLength)..info.fileContentLen
     if (keepStartOffset)
-        ::munmap((void*)info.fileContent, (size_t)keepStartOffset);
+        ::munmap((void*)info.fileContent, (size_t)trunc_page(keepStartOffset));
     if ((keepStartOffset + keepLength) != info.fileContentLen) {
-        // Round up to page alignment
-        keepLength = (keepLength + PAGE_SIZE - 1) & (-PAGE_SIZE);
-        ::munmap((void*)((char*)info.fileContent + keepStartOffset + keepLength), (size_t)(info.fileContentLen - (keepStartOffset + keepLength)));
+        uintptr_t start = round_page((uintptr_t)info.fileContent + keepStartOffset + keepLength);
+        uintptr_t end = (uintptr_t)info.fileContent + info.fileContentLen;
+        ::munmap((void*)start, end - start);
     }
     info.fileContent = (const void*)((char*)info.fileContent + keepStartOffset);
     info.fileContentLen = keepLength;
@@ -272,7 +293,7 @@
     __block bool result = false;
     forEachPath(path, ^(const char* aPath, unsigned prefixLen, bool& stop) {
         struct stat statBuf;
-        if ( ::stat(aPath, &statBuf) == 0 ) {
+        if ( dyld3::stat(aPath, &statBuf) == 0 ) {
             if (inode)
                 *inode = statBuf.st_ino;
             if (mtime)