/****** 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;
}
示例#2
0
/****** 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;
}