From 3d3c214069595b9b76804893b2eff3c389591dfd Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 3 Oct 2006 01:59:42 +0000 Subject: [PATCH] dyld-45.3.tar.gz --- src/dyld.cpp | 115 +++++++++++----------- unit-tests/test-cases/suid-environ/main.c | 23 ++++- 2 files changed, 81 insertions(+), 57 deletions(-) diff --git a/src/dyld.cpp b/src/dyld.cpp index 718bd33..2f1be41 100644 --- a/src/dyld.cpp +++ b/src/dyld.cpp @@ -397,37 +397,6 @@ static const char** parseColonList(const char* list) 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 @@ static void printEnvironmentVariables(const char* envp[]) 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"); @@ -653,6 +614,48 @@ void processDyldEnvironmentVarible(const char* key, const char* value) } } +// +// 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; + } +} static void checkEnvironmentVariables(const char* envp[], bool ignoreEnviron) { @@ -676,8 +679,7 @@ static void checkEnvironmentVariables(const char* envp[], bool ignoreEnviron) } 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); } } @@ -2001,7 +2003,10 @@ _main(const struct mach_header* mainExecutableMH, int argc, const char* argv[], } uintptr_t result = 0; sMainExecutableMachHeader = mainExecutableMH; - checkEnvironmentVariables(envp, isEmulated); + if ( issetugid() ) + pruneEnvironmentVariables(envp, &apple); + else + checkEnvironmentVariables(envp, isEmulated); if ( sEnv.DYLD_PRINT_OPTS ) printOptions(argv); if ( sEnv.DYLD_PRINT_ENV ) diff --git a/unit-tests/test-cases/suid-environ/main.c b/unit-tests/test-cases/suid-environ/main.c index c0410e1..43a9749 100644 --- a/unit-tests/test-cases/suid-environ/main.c +++ b/unit-tests/test-cases/suid-environ/main.c @@ -30,15 +30,34 @@ // binaries set to run as some other user id never see any DYLD_ environment variables // -int main(int argc, const char* argv[], const char* envp[]) +int main(int argc, const char* argv[], const char* envp[], const char* apple[]) { - for(const char** p = envp; *p != NULL; p++) { + // verify no DYLD_ variables + const char** p; + for(p = envp; *p != NULL; p++) { //fprintf(stderr, "%s\n", *p); if ( strncmp(*p, "DYLD_", 5) == 0 ) { FAIL("suid-environ: found %s", *p); return EXIT_SUCCESS; } } + // verify same as apple parameter + ++p; + if ( apple != p ) { + FAIL("suid-environ: apple parameter not at end of envp"); + return EXIT_SUCCESS; + } + + // verify apple parameter is not NULL and ends in main + if ( *apple == NULL ) { + FAIL("suid-environ: apple parameter is empty"); + return EXIT_SUCCESS; + } + if ( strstr(*apple, "/main") == NULL ) { + FAIL("suid-environ: apple parameter is not path to main"); + return EXIT_SUCCESS; + } + PASS("suid-environ"); return EXIT_SUCCESS; } -- 2.45.2