Introduce SIP_DISABLED compile option for ape-m1.c

Systems that don't use SIP can now build APE Loader with this flag to
get a performance speedup.
This commit is contained in:
Justine Tunney 2023-11-13 22:04:05 -08:00
parent 0283f2772c
commit 1c2e7c1333
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
2 changed files with 35 additions and 18 deletions

View file

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

View file

@ -32,8 +32,11 @@ __funline void *__repstosb(void *di, char al, size_t cx) {
: "0"(di), "1"(cx), "a"(al)); : "0"(di), "1"(cx), "a"(al));
return di; return di;
#else #else
volatile char *volatile d = di; char *d = di;
while (cx--) *d++ = al; while (cx--) {
*d++ = al;
asm volatile("" ::: "memory");
}
return (void *)d; return (void *)d;
#endif #endif
} }
@ -45,9 +48,12 @@ __funline void *__repmovsb(void *di, const void *si, size_t cx) {
: "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si)); : "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si));
return di; return di;
#else #else
volatile char *volatile d = di; char *d = di;
volatile const char *volatile s = si; const char *s = si;
while (cx--) *d++ = *s++; while (cx--) {
*d++ = *s++;
asm volatile("" ::: "memory");
}
return (void *)d; return (void *)d;
#endif #endif
} }
@ -56,6 +62,7 @@ __funline void *__mempcpy(void *d, const void *s, size_t n) {
size_t i; size_t i;
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
((char *)d)[i] = ((const char *)s)[i]; ((char *)d)[i] = ((const char *)s)[i];
asm volatile("" ::: "memory");
} }
return (char *)d + n; return (char *)d + n;
} }