Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 31 Aug 2000 00:20:09 +0000 (00:20 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 31 Aug 2000 00:20:09 +0000 (00:20 +0000)
* elf/dl-load.c (fillin_rpath): Only check for trusted directories
when adding new entries.

ChangeLog
elf/dl-load.c

index b9dc89d..bffcc60 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2000-08-30  Ulrich Drepper  <drepper@redhat.com>
 
+       * elf/dl-load.c (fillin_rpath): Only check for trusted directories
+       when adding new entries.
+
        * elf/dl-load.c (fillin_rpath): Make local copy of where string
        since the object being loaded can be unloaded.
 
index ad29386..21c3274 100644 (file)
@@ -126,6 +126,8 @@ static const size_t system_dirs_len[] =
 {
   SYSTEM_DIRS_LEN
 };
+#define nsystem_dirs_len \
+  (sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
 
 
 /* Local version of `strdup' function.  */
@@ -362,32 +364,6 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
       if (len > 0 && cp[len - 1] != '/')
        cp[len++] = '/';
 
-      /* Make sure we don't use untrusted directories if we run SUID.  */
-      if (check_trusted)
-       {
-         const char *trun = system_dirs;
-         size_t idx;
-
-         /* All trusted directories must be complete names.  */
-         if (cp[0] != '/')
-           continue;
-
-         for (idx = 0;
-              idx < sizeof (system_dirs_len) / sizeof (system_dirs_len[0]);
-              ++idx)
-           {
-             if (len == system_dirs_len[idx] && memcmp (trun, cp, len) == 0)
-               /* Found it.  */
-               break;
-
-             trun += system_dirs_len[idx] + 1;
-           }
-
-         if (idx == sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
-           /* It's no trusted directory, skip it.  */
-           continue;
-       }
-
       /* See if this directory is already known.  */
       for (dirp = all_dirs; dirp != NULL; dirp = dirp->next)
        if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)
@@ -408,7 +384,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
        {
          size_t cnt;
          enum r_dir_status init_val;
-         size_t where_len = strlen (where) + 1;
+         size_t where_len = where ? strlen (where) + 1 : 0;
 
          /* It's a new directory.  Create an entry and add it.  */
          dirp = (struct r_search_path_elem *)
@@ -424,17 +400,51 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
          if (len > max_dirnamelen)
            max_dirnamelen = len;
 
-         /* We have to make sure all the relative directories are never
-            ignored.  The current directory might change and all our
-            saved information would be void.  */
-         init_val = cp[0] != '/' ? existing : unknown;
+         /* Make sure we don't use untrusted directories if we run SUID.  */
+         if (__builtin_expect (check_trusted, 0))
+           {
+             const char *trun = system_dirs;
+             size_t idx;
+
+             /* By default we don't trust anything.  */
+             init_val = nonexisting;
+
+             /* All trusted directories must be complete names.  */
+             if (cp[0] == '/')
+               {
+                 for (idx = 0; idx < nsystem_dirs_len; ++idx)
+                   {
+                     if (len == system_dirs_len[idx]
+                         && memcmp (trun, cp, len) == 0)
+                       /* Found it.  */
+                       break;
+
+                     trun += system_dirs_len[idx] + 1;
+                   }
+
+                 if (idx < nsystem_dirs_len)
+                   /* It's a trusted directory so allow checking for it.  */
+                   init_val = unknown;
+               }
+           }
+         else
+           /* We don't have to check for trusted directories and can
+              accept everything.  We have to make sure all the
+              relative directories are never ignored.  The current
+              directory might change and all our saved information
+              would be void.  */
+           init_val = cp[0] != '/' ? existing : unknown;
+
          for (cnt = 0; cnt < ncapstr; ++cnt)
            dirp->status[cnt] = init_val;
 
          dirp->what = what;
-         dirp->where = memcpy ((char *) dirp + sizeof (*dirp)
-                               + ncapstr * sizeof (enum r_dir_status),
-                               where, where_len);
+         if (__builtin_expect (where != NULL, 1))
+           dirp->where = memcpy ((char *) dirp + sizeof (*dirp)
+                                 + ncapstr * sizeof (enum r_dir_status),
+                                 where, where_len);
+         else
+           dirp->where = NULL;
 
          dirp->next = all_dirs;
          all_dirs = dirp;
@@ -531,8 +541,7 @@ _dl_init_paths (const char *llp)
 
   /* First set up the rest of the default search directory entries.  */
   aelem = rtld_search_dirs = (struct r_search_path_elem **)
-    malloc ((sizeof (system_dirs_len) / sizeof (system_dirs_len[0]) + 1)
-            * sizeof (struct r_search_path_elem *));
+    malloc ((nsystem_dirs_len + 1) * sizeof (struct r_search_path_elem *));
   if (rtld_search_dirs == NULL)
     _dl_signal_error (ENOMEM, NULL, N_("cannot create search path array"));
 
@@ -570,13 +579,11 @@ _dl_init_paths (const char *llp)
        for (cnt = 0; cnt < ncapstr; ++cnt)
          pelem->status[cnt] = unknown;
 
-      pelem->next = (++idx == (sizeof (system_dirs_len)
-                              / sizeof (system_dirs_len[0]))
-                    ? NULL : (pelem + round_size));
+      pelem->next = (++idx == nsystem_dirs_len ? NULL : (pelem + round_size));
 
       pelem += round_size;
     }
-  while (idx < sizeof (system_dirs_len) / sizeof (system_dirs_len[0]));
+  while (idx < nsystem_dirs_len);
 
   max_dirnamelen = SYSTEM_DIRS_MAX_LEN;
   *aelem = NULL;
@@ -1506,8 +1513,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
                      dirp += system_dirs_len[cnt] + 1;
                      ++cnt;
                    }
-                 while (cnt < (sizeof (system_dirs_len)
-                               / sizeof (system_dirs_len[0])));
+                 while (cnt < nsystem_dirs_len);
                }
 
              if (cached)