Loading...
--- dyld/dyld-44.2/src/dyld.cpp
+++ dyld/dyld-46.9/src/dyld.cpp
@@ -1,6 +1,6 @@
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
*
- * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
@@ -241,10 +241,6 @@
void removeImage(ImageLoader* image)
{
- // flush find-by-address cache
- if ( sLastImageByAddressCache == image )
- sLastImageByAddressCache = NULL;
-
// if in termination list, pull it out and run terminator
for (std::vector<ImageLoader*>::iterator it=sImageFilesNeedingTermination.begin(); it != sImageFilesNeedingTermination.end(); it++) {
if ( *it == image ) {
@@ -277,6 +273,10 @@
}
}
+ // flush find-by-address cache
+ if ( sLastImageByAddressCache == image )
+ sLastImageByAddressCache = NULL;
+
// if in announcement list, pull it out
for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
if ( *it == image ) {
@@ -397,37 +397,6 @@
return (const char**)result;
}
-/*
- * Library path searching is not done for setuid programs
- * which are not run by the real user. Futher the
- * evironment varaible for the library path is cleared so
- * that if this program executes a non-set uid program this
- * part of the evironment will not be passed along so that
- * that program also will not have it's libraries searched
- * for.
- */
- static bool riskyUser()
- {
- static bool checked = false;
- static bool risky = false;
- if ( !checked ) {
- risky = ( getuid() != 0 && (getuid() != geteuid() || getgid() != getegid()) );
- checked = true;
- }
- return risky;
- }
-
-
-static bool disableIfBadUser(char* rhs)
-{
- bool didDisable = false;
- if ( riskyUser() ) {
- *rhs ='\0';
- didDisable = true;
- }
- return didDisable;
-}
-
static void paths_expand_roots(const char **paths, const char *key, const char *val)
{
// assert(val != NULL);
@@ -492,42 +461,34 @@
void processDyldEnvironmentVarible(const char* key, const char* value)
{
if ( strcmp(key, "DYLD_FRAMEWORK_PATH") == 0 ) {
- if ( !disableIfBadUser((char*)value) )
- sEnv.DYLD_FRAMEWORK_PATH = parseColonList(value);
+ sEnv.DYLD_FRAMEWORK_PATH = parseColonList(value);
}
else if ( strcmp(key, "DYLD_FALLBACK_FRAMEWORK_PATH") == 0 ) {
- if ( !disableIfBadUser((char*)value) )
- sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = parseColonList(value);
+ sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = parseColonList(value);
}
else if ( strcmp(key, "DYLD_LIBRARY_PATH") == 0 ) {
- if ( !disableIfBadUser((char*)value) )
- sEnv.DYLD_LIBRARY_PATH = parseColonList(value);
+ sEnv.DYLD_LIBRARY_PATH = parseColonList(value);
}
else if ( strcmp(key, "DYLD_FALLBACK_LIBRARY_PATH") == 0 ) {
- if ( !disableIfBadUser((char*)value) )
- sEnv.DYLD_FALLBACK_LIBRARY_PATH = parseColonList(value);
+ sEnv.DYLD_FALLBACK_LIBRARY_PATH = parseColonList(value);
}
else if ( (strcmp(key, "DYLD_ROOT_PATH") == 0) || (strcmp(key, "DYLD_PATHS_ROOT") == 0) ) {
- if ( !disableIfBadUser((char*)value) ) {
- if ( strcmp(value, "/") != 0 ) {
- sEnv.DYLD_ROOT_PATH = parseColonList(value);
- for (int i=0; sEnv.DYLD_ROOT_PATH[i] != NULL; ++i) {
- if ( sEnv.DYLD_ROOT_PATH[i][0] != '/' ) {
- fprintf(stderr, "dyld: warning DYLD_ROOT_PATH not used because it contains a non-absolute path\n");
- sEnv.DYLD_ROOT_PATH = NULL;
- break;
- }
+ if ( strcmp(value, "/") != 0 ) {
+ sEnv.DYLD_ROOT_PATH = parseColonList(value);
+ for (int i=0; sEnv.DYLD_ROOT_PATH[i] != NULL; ++i) {
+ if ( sEnv.DYLD_ROOT_PATH[i][0] != '/' ) {
+ fprintf(stderr, "dyld: warning DYLD_ROOT_PATH not used because it contains a non-absolute path\n");
+ sEnv.DYLD_ROOT_PATH = NULL;
+ break;
}
}
}
}
else if ( strcmp(key, "DYLD_IMAGE_SUFFIX") == 0 ) {
- if ( !disableIfBadUser((char*)value) )
- gLinkContext.imageSuffix = value;
+ gLinkContext.imageSuffix = value;
}
else if ( strcmp(key, "DYLD_INSERT_LIBRARIES") == 0 ) {
- if ( !disableIfBadUser((char*)value) )
- sEnv.DYLD_INSERT_LIBRARIES = parseColonList(value);
+ sEnv.DYLD_INSERT_LIBRARIES = parseColonList(value);
}
else if ( strcmp(key, "DYLD_DEBUG_TRACE") == 0 ) {
fprintf(stderr, "dyld: warning DYLD_DEBUG_TRACE not supported\n");
@@ -650,6 +611,49 @@
}
else {
fprintf(stderr, "dyld: warning, unknown environment variable: %s\n", key);
+ }
+}
+
+//
+// For security, setuid programs ignore DYLD_* environment variables.
+// Additionally, the DYLD_* enviroment variables are removed
+// from the environment, so that any child processes don't see them.
+//
+static void pruneEnvironmentVariables(const char* envp[], const char*** applep)
+{
+ // delete all DYLD_* and LD_LIBRARY_PATH environment variables
+ int removedCount = 0;
+ const char** d = envp;
+ for(const char** s = envp; *s != NULL; s++) {
+ if ( (strncmp(*s, "DYLD_", 5) != 0) && (strncmp(*s, "LD_LIBRARY_PATH=", 16) != 0) ) {
+ *d++ = *s;
+ }
+ else {
+ ++removedCount;
+ }
+ }
+ *d++ = NULL;
+
+ // slide apple parameters
+ if ( removedCount > 0 ) {
+ *applep = d;
+ do {
+ *d = d[removedCount];
+ } while ( *d++ != NULL );
+ }
+
+ // setup DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
+ if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
+ const char** paths = sFrameworkFallbackPaths;
+ removePathWithPrefix(paths, "$HOME");
+ sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths;
+ }
+
+ // default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
+ if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
+ const char** paths = sLibraryFallbackPaths;
+ removePathWithPrefix(paths, "$HOME");
+ sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
}
}
@@ -675,32 +679,27 @@
}
else if ( strncmp(keyEqualsValue, "LD_LIBRARY_PATH=", 16) == 0 ) {
const char* path = &keyEqualsValue[16];
- if ( !disableIfBadUser((char*)path) )
- sEnv.LD_LIBRARY_PATH = parseColonList(path);
- }
- }
-
+ sEnv.LD_LIBRARY_PATH = parseColonList(path);
+ }
+ }
+
// default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
const char** paths = sFrameworkFallbackPaths;
- if ( home != NULL ) {
- if ( riskyUser() )
- removePathWithPrefix(paths, "$HOME");
- else
- paths_expand_roots(paths, "$HOME", home);
- }
+ if ( home == NULL )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths;
}
// default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
const char** paths = sLibraryFallbackPaths;
- if ( home != NULL ) {
- if ( riskyUser() )
- removePathWithPrefix(paths, "$HOME");
- else
- paths_expand_roots(paths, "$HOME", home);
- }
+ if ( home == NULL )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
}
}
@@ -818,6 +817,20 @@
#if FIND_STATS
++cacheNotMacho;
#endif
+ return NULL;
+}
+
+ImageLoader* findImageContainingAddressThreadSafe(const void* addr)
+{
+ // do exhastive search
+ // todo: consider maintaining a list sorted by address ranges and do a binary search on that
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
+ ImageLoader* anImage = sAllImages[i];
+ if ( anImage->containsAddress(addr) ) {
+ return anImage;
+ }
+ }
return NULL;
}
@@ -1041,6 +1054,15 @@
return true;
}
break;
+#ifdef CPU_TYPE_X86_64
+ case CPU_TYPE_X86_64:
+ if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_X86_64_ALL ) {
+ *offset = OSSwapBigToHostInt32(archs[i].offset);
+ *len = OSSwapBigToHostInt32(archs[i].size);
+ return true;
+ }
+ break;
+#endif
}
}
}
@@ -1120,6 +1142,12 @@
if ( mh->cpusubtype == CPU_SUBTYPE_I386_ALL )
return true;
break;
+#ifdef CPU_TYPE_X86_64
+ case CPU_TYPE_X86_64:
+ if ( mh->cpusubtype == CPU_SUBTYPE_X86_64_ALL )
+ return true;
+ break;
+#endif
}
}
}
@@ -1138,7 +1166,7 @@
return image;
}
- return NULL;
+ throw "main executable not a known format";
}
@@ -1221,8 +1249,18 @@
// try other file formats...
- throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
- firstPage[0], firstPage[1], firstPage[2], firstPage[3], firstPage[4], firstPage[5], firstPage[6],firstPage[7]);
+
+ // throw error about what was found
+ switch (*(uint32_t*)firstPage) {
+ case MH_MAGIC:
+ case MH_CIGAM:
+ case MH_MAGIC_64:
+ case MH_CIGAM_64:
+ throw "mach-o, but wrong architecture";
+ default:
+ throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
+ firstPage[0], firstPage[1], firstPage[2], firstPage[3], firstPage[4], firstPage[5], firstPage[6],firstPage[7]);
+ }
}
@@ -1608,8 +1646,17 @@
// try other file formats...
- throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
- mem[0], mem[1], mem[2], mem[3], mem[4], mem[5], mem[6],mem[7]);
+ // throw error about what was found
+ switch (*(uint32_t*)mem) {
+ case MH_MAGIC:
+ case MH_CIGAM:
+ case MH_MAGIC_64:
+ case MH_CIGAM_64:
+ throw "mach-o, but wrong architecture";
+ default:
+ throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
+ mem[0], mem[1], mem[2], mem[3], mem[4], mem[5], mem[6],mem[7]);
+ }
}
@@ -1662,7 +1709,7 @@
#if __ppc__ || __ppc64__
__asm__ ("trap");
-#elif __i386__
+#elif __i386__ || __x86_64__
__asm__ ("int3");
#else
#error unknown architecture
@@ -1681,8 +1728,17 @@
#endif
// lookup and bind lazy pointer and get target address
try {
+ ImageLoader* target;
+ #if __i386__
+ // fast stubs pass NULL for mh and image is instead found via the location of stub (aka lazyPointer)
+ if ( mh == NULL )
+ target = dyld::findImageContainingAddressThreadSafe(lazyPointer);
+ else
+ target = dyld::findImageByMachHeader(mh);
+ #else
// note, target should always be mach-o, because only mach-o lazy handler wired up to this
- ImageLoader* target = dyld::findImageByMachHeader(mh);
+ target = dyld::findImageByMachHeader(mh);
+ #endif
if ( target == NULL )
throw "image not found for lazy pointer";
result = target->doBindLazySymbol(lazyPointer, gLinkContext);
@@ -1865,21 +1921,16 @@
gLinkContext.apple = apple;
}
-static bool checkEmulation()
-{
-#if __i386__
+static bool isRosetta()
+{
int mib[] = { CTL_KERN, KERN_CLASSIC, getpid() };
int is_classic = 0;
size_t len = sizeof(int);
int ret = sysctl(mib, 3, &is_classic, &len, NULL, 0);
if ((ret != -1) && is_classic) {
- // When a 32-bit ppc program is run under emulation on an Intel processor,
- // we want any i386 dylibs (e.g. the emulator) to not load in the shared region
- // because the shared region is being used by ppc dylibs
- gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
+ // we're running under Rosetta
return true;
}
-#endif
return false;
}
@@ -1919,6 +1970,17 @@
//
+// _pthread_keys is partitioned in a lower part that dyld will use; libSystem
+// will use the upper part. We set __pthread_tsd_first to 1 as the start of
+// the lower part. Libc will take #1 and c++ exceptions will take #2. There
+// is one free key=3 left.
+//
+extern "C" {
+ extern int __pthread_tsd_first;
+}
+
+
+//
// Entry point for dyld. The kernel loads dyld and jumps to __dyld_start which
// sets up some registers and call this function.
//
@@ -1927,8 +1989,23 @@
uintptr_t
_main(const struct mach_header* mainExecutableMH, int argc, const char* argv[], const char* envp[], const char* apple[])
{
+ // set pthread keys to dyld range
+ __pthread_tsd_first = 1;
+
// Pickup the pointer to the exec path.
sExecPath = apple[0];
+ bool ignoreEnvironmentVariables = false;
+#if __i386__
+ if ( isRosetta() ) {
+ // under Rosetta (x86 side)
+ // When a 32-bit ppc program is run under emulation on an Intel processor,
+ // we want any i386 dylibs (e.g. any used by Rosetta) to not load in the shared region
+ // because the shared region is being used by ppc dylibs
+ gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
+ sExecPath = strdup(apple[0] + strlen(apple[0]) + 1);
+ ignoreEnvironmentVariables = true;
+ }
+#endif
if ( sExecPath[0] != '/' ) {
// have relative path, use cwd to make absolute
char cwdbuff[MAXPATHLEN];
@@ -1943,8 +2020,10 @@
}
uintptr_t result = 0;
sMainExecutableMachHeader = mainExecutableMH;
- bool isEmulated = checkEmulation();
- checkEnvironmentVariables(envp, isEmulated);
+ if ( issetugid() )
+ pruneEnvironmentVariables(envp, &apple);
+ else
+ checkEnvironmentVariables(envp, ignoreEnvironmentVariables);
if ( sEnv.DYLD_PRINT_OPTS )
printOptions(argv);
if ( sEnv.DYLD_PRINT_ENV )
@@ -2002,8 +2081,9 @@
fprintf(stderr, "dyld: launch failed\n");
}
+
// Link in any inserted libraries.
- // Do this after link main executable so any extra libraries pulled in by inserted libraries are at end of flat namespace
+ // Do this after linking main executable so any extra libraries pulled in by inserted libraries are at end of flat namespace
if ( insertLibrariesCount > 0 ) {
for (int i=0; i < insertLibrariesCount; ++i) {
try {