/****** uti/sanitize_environment() ***************************************** * NAME * sanitize_environment() -- remove sensitive variables from the environment before calling programs * * SYNOPSIS * #include "uti/execvlp.h" * void sanitize_environment(char *env[]) * * FUNCTION * Remove variables from the environment which represent a security * risk when a program is called under a privileged id with an * environment supplied by the user, such as remote * communication daemons. (For instance, if the user can get a * dynamically-linked privileged program run in an ELF environment * with arbitrary LD_LIBRARY_PATH or LD_PRELOAD, all bets are off.) * * SEE ALSO * qrsh_starter *******************************************************************************/ void sanitize_environment (char *env[]) { int i = 0, j; regex_t lc_regex; const char *sharedlib = var_get_sharedlib_path_name (); /* Valid locale -- see var_unsafe. */ const char *lc_pattern = "^[A-Za-z_]+=[A-Za-z][-A-Za-z0-9_,+@.=]*$"; if (!env) return; /* We only need to bother if we're privileged in some way. */ if ((geteuid () != SGE_SUPERUSER_UID) && (getegid () != SGE_SUPERUSER_GID) && (geteuid () == getuid ()) && (getegid () == getgid ())) return; if (regcomp (&lc_regex, lc_pattern, REG_NOSUB | REG_EXTENDED)) exit(1); while (env[i]) { /* In an ELF system, sensitive variables include LD_LIBRARY_PATH, plus variations like LD_LIBRARY_PATH64, and LD_PRELOAD. For safety, we'll zap anything with an LD_ prefix. (We could test the __ELF__ of the system, but this is safer.) Similarly check var_get_sharedlib_path_name as a prefix. */ if ((strncmp (env[i], "LD_", 3) == 0) /* Known in Tru64, but sudo has it generally */ || (strncmp (env[i], "_RLD_", 5) == 0) #ifdef __APPLE__ /* DYLD_{FALLBACK_,}FRAMEWORK_PATH, {FALLBACK_,}DYLD_LIBRARY_PATH seem to be relevant. */ || (strncmp (env[i], "DYLD_", 5) == 0) #elif defined _AIX || (strncmp (env[i], "LDR_", 4) == 0) #elif defined __hpux__ /* _HP_DLDOPTS is loader options; guess a prefix. */ || (strncmp (env[i], "_HP_DLD", 7) == 0) #endif || (strncmp (env[i], sharedlib, strlen (sharedlib)) == 0) || var_unsafe (env[i], lc_regex)) { /* Shuffle env elements down over the unsafe one. */ for (j=i; env[j]; j++) env[j] = env[j+1]; } else { i++; } } regfree (&lc_regex); return; }
/****** sgeobj/var/var_list_set_sharedlib_path() ****************************** * NAME * var_list_set_sharedlib_path -- set shared lib path * * SYNOPSIS * void var_list_set_sharedlib_path(lList **varl); * * FUNCTION * Sets or replaces the shared lib path in the list of variables. * The SGE shared lib path is always set to the beginning of the * resulting shared lib path * (security, see var_get_sharedlib_path_name()) * * INPUTS * lList **varl - list of nment variables * * SEE ALSO * sgeobj/var/var_get_sharedlib_path_name() * sgeobj/var/var_list_set_string() * sgeobj/var/var_list_set_int() * sgeobj/var/var_list_set_sge_u32() ******************************************************************************/ void var_list_set_sharedlib_path(lList **varl) { char *sharedlib_path; char *sge_sharedlib_path; const char *sge_root = sge_get_root_dir(0, NULL, 0, 1); const char *sharedlib_path_name = var_get_sharedlib_path_name(); lListElem *sharedlib_elem = NULL; DENTER(TOP_LAYER, "set_sharedlib_path"); /* this is the SGE sharedlib path */ sge_sharedlib_path = sge_malloc(strlen(sge_root) + strlen("/lib/") + strlen(sge_get_arch()) + 1); sprintf(sge_sharedlib_path, "%s/lib/%s", sge_root, sge_get_arch()); /* if already in environment: extend by SGE sharedlib path, else set */ sharedlib_elem = lGetElemStr(*varl, VA_variable, sharedlib_path_name); if(sharedlib_elem != NULL) { const char *old_value = lGetString(sharedlib_elem, VA_value); if(old_value && strlen(old_value) > 0) { DPRINTF(("sharedlib path %s already set:\n", sharedlib_path_name)); sharedlib_path = sge_malloc(strlen(old_value) + 1 + strlen(sge_sharedlib_path) + 1); strcpy(sharedlib_path, sge_sharedlib_path); strcat(sharedlib_path, ":"); strcat(sharedlib_path, old_value); lSetString(sharedlib_elem, VA_value, sharedlib_path); sge_free(&sharedlib_path); } else { DPRINTF(("overwriting empty sharedlib path %s\n", sharedlib_path_name)); lSetString(sharedlib_elem, VA_value, sge_sharedlib_path); } } else { DPRINTF(("creating new sharedlib path %s\n", sharedlib_path_name)); sharedlib_elem = lAddElemStr(varl, VA_variable, sharedlib_path_name, VA_Type); lSetString(sharedlib_elem, VA_value, sge_sharedlib_path); } sge_free(&sge_sharedlib_path); DEXIT; }