[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

r5277 - in glibc-package/trunk/debian: . patches patches/any



Author: aurel32
Date: 2012-06-03 18:11:47 +0000 (Sun, 03 Jun 2012)
New Revision: 5277

Added:
   glibc-package/trunk/debian/patches/any/cvs-ld.so-rpath-origin.diff
Modified:
   glibc-package/trunk/debian/changelog
   glibc-package/trunk/debian/patches/series
Log:
  * Add patches/any/cvs-ld.so-rpath-origin.diff to fix an insecure handling
    of privileged programs' RPATHs with $ORIGIN (CVE-2011-1658).  Closes:
    #672119.



Modified: glibc-package/trunk/debian/changelog
===================================================================
--- glibc-package/trunk/debian/changelog	2012-06-03 17:57:45 UTC (rev 5276)
+++ glibc-package/trunk/debian/changelog	2012-06-03 18:11:47 UTC (rev 5277)
@@ -59,6 +59,9 @@
   * Set libc*-dev "Multi-Arch: same". Add conflicts betwwen libc*-dev
     packages. Move a.out.h and ieee754.h to the arch qualified path.
     Thanks to Thibaut Girka for the help.  Closes: #666760.
+  * Add patches/any/cvs-ld.so-rpath-origin.diff to fix an insecure handling
+    of privileged programs' RPATHs with $ORIGIN (CVE-2011-1658).  Closes:
+    #672119.
 
  -- Clint Adams <clint@debian.org>  Fri, 04 May 2012 23:39:00 -0400
 

Added: glibc-package/trunk/debian/patches/any/cvs-ld.so-rpath-origin.diff
===================================================================
--- glibc-package/trunk/debian/patches/any/cvs-ld.so-rpath-origin.diff	                        (rev 0)
+++ glibc-package/trunk/debian/patches/any/cvs-ld.so-rpath-origin.diff	2012-06-03 18:11:47 UTC (rev 5277)
@@ -0,0 +1,296 @@
+2011-05-11  Ulrich Drepper  <drepper@gmail.com>
+
+	[BZ #12393]
+	* elf/dl-load.c (is_trusted_path): Remove unnecessary test.
+	(is_trusted_path_normalize): Skip initial colon.  Append slash
+	to empty buffer.  Duplicate is_trusted_path code but allow
+	constructed patch to be prefix.
+	(is_dst): Allow $ORIGIN followed by /.
+	(_dl_dst_substitute): Correct clearing of check_for_trusted.
+	Correct testing of result of is_trusted_path_normalize
+	(decompose_rpath): Fix warning.
+
+2011-05-07  Petr Baudis  <pasky@suse.cz>
+	    Ulrich Drepper  <drepper@gmail.com>
+
+	[BZ #12393]
+	* elf/dl-load.c (fillin_rpath): Move trusted path check...
+	(is_trusted_path): ...to here.
+	(is_norm_trusted_path): Add wrapper for /../ and /./ normalization.
+	(_dl_dst_substitute): Verify expanded $ORIGIN path elements
+	using is_norm_trusted_path() in setuid scripts.
+
+2011-03-14  Andreas Schwab  <schwab@redhat.com>
+
+	* elf/dl-load.c (_dl_dst_substitute): When skipping the first
+	rpath element also skip the following colon.
+	(expand_dynamic_string_token): Add is_path parameter and pass
+	down to DL_DST_REQUIRED and _dl_dst_substitute.
+	(decompose_rpath): Call expand_dynamic_string_token with
+	non-zero is_path.  Ignore empty rpaths.
+	(_dl_map_object_from_fd): Call expand_dynamic_string_token
+	with zero is_path.
+
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -168,6 +168,87 @@
+ }
+ 
+ 
++static bool
++is_trusted_path (const char *path, size_t len)
++{
++  const char *trun = system_dirs;
++
++  for (size_t idx = 0; idx < nsystem_dirs_len; ++idx)
++    {
++      if (len == system_dirs_len[idx] && memcmp (trun, path, len) == 0)
++	/* Found it.  */
++	return true;
++
++      trun += system_dirs_len[idx] + 1;
++    }
++
++  return false;
++}
++
++
++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] == '/')
++	{
++	  if (path[1] == '.')
++	    {
++	      if (path[2] == '.' && (path[3] == '/' || path[3] == '\0'))
++		{
++		  while (wnp > npath && *--wnp != '/')
++		    ;
++		  path += 3;
++		  continue;
++		}
++	      else if (path[2] == '/' || path[2] == '\0')
++		{
++		  path += 2;
++		  continue;
++		}
++	    }
++
++	  if (wnp > npath && wnp[-1] == '/')
++	    {
++	      ++path;
++	      continue;
++	    }
++	}
++
++      *wnp++ = *path++;
++    }
++
++  if (wnp == npath || wnp[-1] != '/')
++    *wnp++ = '/';
++
++  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;
++}
++
++
+ static size_t
+ is_dst (const char *start, const char *name, const char *str,
+ 	int is_path, int secure)
+@@ -200,7 +281,8 @@
+     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;
+ 
+@@ -240,13 +322,14 @@
+ 		    int is_path)
+ {
+   const char *const start = name;
+-  char *last_elem, *wp;
+ 
+   /* Now fill the result path.  While copying over the string we keep
+      track of the start of the last path element.  When we come accross
+      a DST we copy over the value or (if the value is not available)
+      leave the entire path element out.  */
+-  last_elem = wp = result;
++  char *wp = result;
++  char *last_elem = result;
++  bool check_for_trusted = false;
+ 
+   do
+     {
+@@ -265,6 +348,9 @@
+ 	      else
+ #endif
+ 		repl = l->l_origin;
++
++	      check_for_trusted = (INTUSE(__libc_enable_secure)
++				   && l->l_type == lt_executable);
+ 	    }
+ 	  else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
+ 	    repl = GLRO(dl_platform);
+@@ -284,6 +370,10 @@
+ 	      name += len;
+ 	      while (*name != '\0' && (!is_path || *name != ':'))
+ 		++name;
++	      /* Also skip following colon if this is the first rpath
++		 element, but keep an empty element at the end.  */
++	      if (wp == result && is_path && *name == ':' && name[1] != '\0')
++		++name;
+ 	    }
+ 	  else
+ 	    /* No DST we recognize.  */
+@@ -293,11 +383,28 @@
+ 	{
+ 	  *wp++ = *name++;
+ 	  if (is_path && *name == ':')
+-	    last_elem = wp;
++	    {
++	      /* 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))
++		wp = last_elem;
++	      else
++		last_elem = wp;
++
++	      check_for_trusted = false;
++	    }
+ 	}
+     }
+   while (*name != '\0');
+ 
++  /* 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))
++    wp = last_elem;
++
+   *wp = '\0';
+ 
+   return result;
+@@ -310,7 +417,7 @@
+    belonging to the map is loaded.  In this case the path element
+    containing $ORIGIN is left out.  */
+ static char *
+-expand_dynamic_string_token (struct link_map *l, const char *s)
++expand_dynamic_string_token (struct link_map *l, const char *s, int is_path)
+ {
+   /* We make two runs over the string.  First we determine how large the
+      resulting string is and then we copy it over.  Since this is no
+@@ -321,7 +428,7 @@
+   char *result;
+ 
+   /* Determine the number of DST elements.  */
+-  cnt = DL_DST_COUNT (s, 1);
++  cnt = DL_DST_COUNT (s, is_path);
+ 
+   /* If we do not have to replace anything simply copy the string.  */
+   if (__builtin_expect (cnt, 0) == 0)
+@@ -335,7 +442,7 @@
+   if (result == NULL)
+     return NULL;
+ 
+-  return _dl_dst_substitute (l, s, result, 1);
++  return _dl_dst_substitute (l, s, result, is_path);
+ }
+ 
+ 
+@@ -407,33 +514,8 @@
+ 	cp[len++] = '/';
+ 
+       /* 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;
+-	  int unsecure = 1;
+-
+-	  /* 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.  */
+-		      unsecure = 0;
+-		      break;
+-		    }
+-
+-		  trun += system_dirs_len[idx] + 1;
+-		}
+-	    }
+-
+-	  if (unsecure)
+-	    /* Simply drop this directory.  */
+-	    continue;
+-	}
++      if (__builtin_expect (check_trusted, 0) && !is_trusted_path (cp, len))
++	continue;
+ 
+       /* See if this directory is already known.  */
+       for (dirp = GL(dl_all_dirs); dirp != NULL; dirp = dirp->next)
+@@ -551,13 +633,21 @@
+ 
+   /* Make a writable copy.  At the same time expand possible dynamic
+      string tokens.  */
+-  copy = expand_dynamic_string_token (l, rpath);
++  copy = expand_dynamic_string_token (l, rpath, 1);
+   if (copy == NULL)
+     {
+       errstring = N_("cannot create RUNPATH/RPATH copy");
+       goto signal_error;
+     }
+ 
++  /* Ignore empty rpaths.  */
++  if (*copy == 0)
++    {
++      free (copy);
++      sps->dirs = (struct r_search_path_elem **) -1;
++      return false;
++    }
++
+   /* Count the number of necessary elements in the result array.  */
+   nelems = 0;
+   for (cp = copy; *cp != '\0'; ++cp)
+@@ -2400,7 +2490,7 @@
+     {
+       /* The path may contain dynamic string tokens.  */
+       realname = (loader
+-		  ? expand_dynamic_string_token (loader, name)
++		  ? expand_dynamic_string_token (loader, name, 0)
+ 		  : local_strdup (name));
+       if (realname == NULL)
+ 	fd = -1;

Modified: glibc-package/trunk/debian/patches/series
===================================================================
--- glibc-package/trunk/debian/patches/series	2012-06-03 17:57:45 UTC (rev 5276)
+++ glibc-package/trunk/debian/patches/series	2012-06-03 18:11:47 UTC (rev 5277)
@@ -359,3 +359,4 @@
 any/cvs-regex.diff
 any/cvs-getpwuid-nsswitch.diff
 any/local-sunrpc-dos.diff
+any/cvs-ld.so-rpath-origin.diff


Reply to: