Loading...
src/dyld.cpp dyld-45.3 dyld-44.2
--- dyld/dyld-45.3/src/dyld.cpp
+++ dyld/dyld-44.2/src/dyld.cpp
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -241,6 +241,10 @@
 
 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 ) {
@@ -273,10 +277,6 @@
 		}
 	}
 	
-	// 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,6 +397,37 @@
 	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);
@@ -461,34 +492,42 @@
 void processDyldEnvironmentVarible(const char* key, const char* value)
 {
 	if ( strcmp(key, "DYLD_FRAMEWORK_PATH") == 0 ) {
-		sEnv.DYLD_FRAMEWORK_PATH = parseColonList(value);
+		if ( !disableIfBadUser((char*)value) )
+			sEnv.DYLD_FRAMEWORK_PATH = parseColonList(value);
 	}
 	else if ( strcmp(key, "DYLD_FALLBACK_FRAMEWORK_PATH") == 0 ) {
-		sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = parseColonList(value);
+		if ( !disableIfBadUser((char*)value) )
+			sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = parseColonList(value);
 	}
 	else if ( strcmp(key, "DYLD_LIBRARY_PATH") == 0 ) {
-		sEnv.DYLD_LIBRARY_PATH = parseColonList(value);
+		if ( !disableIfBadUser((char*)value) )
+			sEnv.DYLD_LIBRARY_PATH = parseColonList(value);
 	}
 	else if ( strcmp(key, "DYLD_FALLBACK_LIBRARY_PATH") == 0 ) {
-		sEnv.DYLD_FALLBACK_LIBRARY_PATH = parseColonList(value);
+		if ( !disableIfBadUser((char*)value) )
+			sEnv.DYLD_FALLBACK_LIBRARY_PATH = parseColonList(value);
 	}
 	else if ( (strcmp(key, "DYLD_ROOT_PATH") == 0) || (strcmp(key, "DYLD_PATHS_ROOT") == 0) ) {
-		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 ( !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;
+					}
 				}
 			}
 		}
 	} 
 	else if ( strcmp(key, "DYLD_IMAGE_SUFFIX") == 0 ) {
-		gLinkContext.imageSuffix = value;
+		if ( !disableIfBadUser((char*)value) )
+			gLinkContext.imageSuffix = value;
 	}
 	else if ( strcmp(key, "DYLD_INSERT_LIBRARIES") == 0 ) {
-		sEnv.DYLD_INSERT_LIBRARIES = parseColonList(value);
+		if ( !disableIfBadUser((char*)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");
@@ -611,49 +650,6 @@
 	}
 	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;
 	}
 }
 
@@ -679,27 +675,32 @@
 		}
 		else if ( strncmp(keyEqualsValue, "LD_LIBRARY_PATH=", 16) == 0 ) {
 			const char* path = &keyEqualsValue[16];
-			sEnv.LD_LIBRARY_PATH = parseColonList(path);
-		}
-	}
-		
+			if ( !disableIfBadUser((char*)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 )
-			removePathWithPrefix(paths, "$HOME");
-		else
-			paths_expand_roots(paths, "$HOME", home);
+		if ( home != NULL ) {
+			if ( riskyUser() )
+				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 ) 
-			removePathWithPrefix(paths, "$HOME");
-		else
-			paths_expand_roots(paths, "$HOME", home);
+		if ( home != NULL ) {
+			if ( riskyUser() )
+				removePathWithPrefix(paths, "$HOME");
+			else
+				paths_expand_roots(paths, "$HOME", home);
+		}
 		sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
 	}
 }
@@ -817,20 +818,6 @@
 #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;
 }
 
@@ -1151,7 +1138,7 @@
 		return image;
 	}
 	
-	throw "main executable not a known format";
+	return NULL;
 }
 
 
@@ -1234,18 +1221,8 @@
 	
 	// try other file formats...
 	
-	
-	// 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]);
-	}
+	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]);
 }
 
 
@@ -1631,17 +1608,8 @@
 	
 	// try other file formats...
 	
-	// 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]);
-	}
+	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]);
 }
 
 
@@ -1713,17 +1681,8 @@
 #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
-		target = dyld::findImageByMachHeader(mh);
-	#endif
+		ImageLoader* target = dyld::findImageByMachHeader(mh);
 		if ( target == NULL )
 			throw "image not found for lazy pointer";
 		result = target->doBindLazySymbol(lazyPointer, gLinkContext);
@@ -1960,17 +1919,6 @@
 
 
 //
-// _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.
 //
@@ -1979,16 +1927,8 @@
 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;
-	
-	bool isEmulated = checkEmulation();
 	// Pickup the pointer to the exec path.
 	sExecPath = apple[0];
-	if (isEmulated) {
-		// under Rosetta 
-		sExecPath = strdup(apple[0] + strlen(apple[0]) + 1);
-	}
 	if ( sExecPath[0] != '/' ) {
 		// have relative path, use cwd to make absolute
 		char cwdbuff[MAXPATHLEN];
@@ -2003,10 +1943,8 @@
 	}
 	uintptr_t result = 0;
 	sMainExecutableMachHeader = mainExecutableMH;
-	if ( issetugid() )
-		pruneEnvironmentVariables(envp, &apple);
-	else
-		checkEnvironmentVariables(envp, isEmulated);
+	bool isEmulated = checkEmulation();
+	checkEnvironmentVariables(envp, isEmulated);
 	if ( sEnv.DYLD_PRINT_OPTS ) 
 		printOptions(argv);
 	if ( sEnv.DYLD_PRINT_ENV )