summary refs log tree commit diff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-05-11 00:15:38 -0400
committerUlrich Drepper <drepper@gmail.com>2011-05-11 00:15:38 -0400
commit22836f52e3e4740e450f9b93a2f1e31a90b168a6 (patch)
treef13227901f9fd1bd52d3e3d8c86b4cfe60787754 /elf/dl-load.c
parent7b3b0b2a63f7e980adb630550c0dc9639ec09d7f (diff)
downloadglibc-22836f52e3e4740e450f9b93a2f1e31a90b168a6.tar.gz
glibc-22836f52e3e4740e450f9b93a2f1e31a90b168a6.tar.xz
glibc-22836f52e3e4740e450f9b93a2f1e31a90b168a6.zip
Fix up testing for valid $ORIGIN use
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index f2773d5686..18a83d2754 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -171,10 +171,6 @@ local_strdup (const char *s)
 static bool
 is_trusted_path (const char *path, size_t len)
 {
-  /* All trusted directories must be complete names.  */
-  if (path[0] != '/')
-    return false;
-
   const char *trun = system_dirs;
 
   for (size_t idx = 0; idx < nsystem_dirs_len; ++idx)
@@ -193,9 +189,17 @@ is_trusted_path (const char *path, size_t len)
 static bool
 is_trusted_path_normalize (const char *path, size_t len)
 {
+  if (len == 0)
+    return false;
+
+  if (*path == ':')
+    {
+      ++path;
+      --len;
+    }
+
   char *npath = (char *) alloca (len + 2);
   char *wnp = npath;
-
   while (*path != '\0')
     {
       if (path[0] == '/')
@@ -225,11 +229,23 @@ is_trusted_path_normalize (const char *path, size_t len)
 
       *wnp++ = *path++;
     }
-  if (wnp > npath && wnp[-1] != '/')
+
+  if (wnp == npath || wnp[-1] != '/')
     *wnp++ = '/';
-  *wnp = '\0';
 
-  return is_trusted_path (npath, wnp - npath);
+  const char *trun = system_dirs;
+
+  for (size_t idx = 0; idx < nsystem_dirs_len; ++idx)
+    {
+      if (wnp - npath >= system_dirs_len[idx]
+	  && memcmp (trun, npath, system_dirs_len[idx]) == 0)
+	/* Found it.  */
+	return true;
+
+      trun += system_dirs_len[idx] + 1;
+    }
+
+  return false;
 }
 
 
@@ -265,7 +281,8 @@ is_dst (const char *start, const char *name, const char *str,
     return 0;
 
   if (__builtin_expect (secure, 0)
-      && ((name[len] != '\0' && (!is_path || name[len] != ':'))
+      && ((name[len] != '\0' && name[len] != '/'
+	   && (!is_path || name[len] != ':'))
 	  || (name != start + 1 && (!is_path || name[-2] != ':'))))
     return 0;
 
@@ -371,13 +388,12 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
 		 normalized path must be rooted in one of the trusted
 		 directories.  */
 	      if (__builtin_expect (check_for_trusted, false)
-		  && is_trusted_path_normalize (last_elem, wp - last_elem))
-		{
-		  wp = last_elem;
-		  check_for_trusted = false;
-		}
+		  && !is_trusted_path_normalize (last_elem, wp - last_elem))
+		wp = last_elem;
 	      else
 		last_elem = wp;
+
+	      check_for_trusted = false;
 	    }
 	}
     }
@@ -386,7 +402,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
   /* In SUID/SGID programs, after $ORIGIN expansion the normalized
      path must be rooted in one of the trusted directories.  */
   if (__builtin_expect (check_for_trusted, false)
-      && is_trusted_path_normalize (last_elem, wp - last_elem))
+      && !is_trusted_path_normalize (last_elem, wp - last_elem))
     wp = last_elem;
 
   *wp = '\0';
@@ -628,7 +644,7 @@ decompose_rpath (struct r_search_path_struct *sps,
   if (*copy == 0)
     {
       free (copy);
-      sps->dirs = (char *) -1;
+      sps->dirs = (struct r_search_path_elem **) -1;
       return false;
     }