@@ -629,7 +629,6 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
629
629
630
630
/* load from file */
631
631
if (p [i ].p_filesz ) {
632
- long map1 , map2 ;
633
632
int prot1 , prot2 ;
634
633
unsigned long wipe ;
635
634
prot1 = prot ;
@@ -653,22 +652,33 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
653
652
addr = (void * )(dynbase + (p [i ].p_vaddr & - pagesz ));
654
653
size = (p [i ].p_vaddr & (pagesz - 1 )) + p [i ].p_filesz ;
655
654
if (prot1 & PROT_EXEC ) {
655
+ #ifdef SIP_DISABLED
656
656
// if sip is disabled then we can load the executable segments
657
- // of the binary into memory without needing to copy anything!
657
+ // off the binary into memory without needing to copy anything
658
+ // which provides considerably better performance for building
658
659
rc = sys_mmap (addr , size , prot1 , flags , fd , p [i ].p_offset & - pagesz );
659
660
if (rc < 0 ) {
660
- if (rc != - EPERM ) Pexit (exe , rc , "mmap(exec)" );
661
- // apple arm64 won't allow PROT_EXEC mapping any unsigned file
662
- // however we are allowed to copy it into an anonymous mapping
663
- map1 = sys_mmap (0 , size , PROT_READ , MAP_PRIVATE , fd ,
664
- p [i ].p_offset & - pagesz );
665
- if (map1 < 0 ) Pexit (exe , map1 , "mmap(exec) workaround input" );
666
- map2 = sys_mmap (addr , size , (prot1 = PROT_READ | PROT_WRITE ),
667
- MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS , -1 , 0 );
668
- if (map2 < 0 ) Pexit (exe , map2 , "mmap(exec) workaround output" );
669
- memcpy ((void * )map2 , (void * )map1 , size );
670
- munmap ((void * )map1 , size );
661
+ if (rc == - EPERM ) {
662
+ Pexit (exe , rc ,
663
+ "map(exec) failed because SIP (System Integrity Protection) "
664
+ "is enabled, but APE Loader was compiled with SIP_DISABLED" );
665
+ } else {
666
+ Pexit (exe , rc , "map(exec) failed" );
667
+ }
671
668
}
669
+ #else
670
+ // the issue is that if sip is enabled then, attempting to map
671
+ // it with exec permission will cause xnu to phone home a hash
672
+ // of the entire file to apple intelligence as a one time cost
673
+ // which is literally minutes for executables holding big data
674
+ // since there's no public apple api for detecting sip we read
675
+ // as the default strategy which is slow but it works for both
676
+ rc = sys_mmap (addr , size , (prot1 = PROT_READ | PROT_WRITE ),
677
+ MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS , -1 , 0 );
678
+ if (rc < 0 ) Pexit (exe , rc , "prog mmap anon" );
679
+ rc = pread (fd , addr , p [i ].p_filesz , p [i ].p_offset & - pagesz );
680
+ if (rc != p [i ].p_filesz ) Pexit (exe , - errno , "prog pread" );
681
+ #endif
672
682
} else {
673
683
rc = sys_mmap (addr , size , prot1 , flags , fd , p [i ].p_offset & - pagesz );
674
684
if (rc < 0 ) Pexit (exe , rc , "prog mmap" );
0 commit comments