olga / rpms / glibc

Forked from rpms/glibc 5 years ago
Clone

Blame SOURCES/glibc-rh1452721-2.patch

ce426f
commit TBD
ce426f
Author: Florian Weimer <fweimer@redhat.com>
ce426f
Date:   Fri May 19 17:46:47 2017 +0200
ce426f
ce426f
    rtld: Reject overly long LD_PRELOAD path elements
ce426f
ce426f
Index: b/elf/rtld.c
ce426f
===================================================================
ce426f
--- a/elf/rtld.c
ce426f
+++ b/elf/rtld.c
ce426f
@@ -99,6 +99,22 @@ uintptr_t __pointer_chk_guard_local
ce426f
 strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
ce426f
 #endif
ce426f
 
ce426f
+/* Check that AT_SECURE=0, or that the passed name does not contain
ce426f
+   directories and is not overly long.  Reject empty names
ce426f
+   unconditionally.  */
ce426f
+static bool
ce426f
+dso_name_valid_for_suid (const char *p)
ce426f
+{
ce426f
+  if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
ce426f
+    {
ce426f
+      /* Ignore pathnames with directories for AT_SECURE=1
ce426f
+	 programs, and also skip overlong names.  */
ce426f
+      size_t len = strlen (p);
ce426f
+      if (len >= NAME_MAX || memchr (p, '/', len) != NULL)
ce426f
+	return false;
ce426f
+    }
ce426f
+  return *p != '\0';
ce426f
+}
ce426f
 
ce426f
 /* List of auditing DSOs.  */
ce426f
 static struct audit_list
ce426f
@@ -880,6 +896,44 @@ static const char *preloadlist attribute
ce426f
 /* Nonzero if information about versions has to be printed.  */
ce426f
 static int version_info attribute_relro;
ce426f
 
ce426f
+/* The LD_PRELOAD environment variable gives list of libraries
ce426f
+   separated by white space or colons that are loaded before the
ce426f
+   executable's dependencies and prepended to the global scope list.
ce426f
+   (If the binary is running setuid all elements containing a '/' are
ce426f
+   ignored since it is insecure.)  Return the number of preloads
ce426f
+   performed.  */
ce426f
+unsigned int
ce426f
+handle_ld_preload (const char *preloadlist, struct link_map *main_map)
ce426f
+{
ce426f
+  unsigned int npreloads = 0;
ce426f
+  const char *p = preloadlist;
ce426f
+  char fname[PATH_MAX];
ce426f
+
ce426f
+  while (*p != '\0')
ce426f
+    {
ce426f
+      /* Split preload list at space/colon.  */
ce426f
+      size_t len = strcspn (p, " :");
ce426f
+      if (len > 0 && len < PATH_MAX)
ce426f
+	{
ce426f
+	  memcpy (fname, p, len);
ce426f
+	  fname[len] = '\0';
ce426f
+	}
ce426f
+      else
ce426f
+	fname[0] = '\0';
ce426f
+
ce426f
+      /* Skip over the substring and the following delimiter.  */
ce426f
+      p += len;
ce426f
+      if (*p == ' ' || *p == ':')
ce426f
+	++p;
ce426f
+
ce426f
+      if (dso_name_valid_for_suid (fname))
ce426f
+	npreloads += do_preload (fname, main_map, "LD_PRELOAD");
ce426f
+    }
ce426f
+  return npreloads;
ce426f
+}
ce426f
+
ce426f
+
ce426f
+
ce426f
 static void
ce426f
 dl_main (const ElfW(Phdr) *phdr,
ce426f
 	 ElfW(Word) phnum,
ce426f
@@ -1611,23 +1665,8 @@ ERROR: ld.so: object '%s' cannot be load
ce426f
 
ce426f
   if (__builtin_expect (preloadlist != NULL, 0))
ce426f
     {
ce426f
-      /* The LD_PRELOAD environment variable gives list of libraries
ce426f
-	 separated by white space or colons that are loaded before the
ce426f
-	 executable's dependencies and prepended to the global scope
ce426f
-	 list.  If the binary is running setuid all elements
ce426f
-	 containing a '/' are ignored since it is insecure.  */
ce426f
-      char *list = strdupa (preloadlist);
ce426f
-      char *p;
ce426f
-
ce426f
       HP_TIMING_NOW (start);
ce426f
-
ce426f
-      /* Prevent optimizing strsep.  Speed is not important here.  */
ce426f
-      while ((p = (strsep) (&list, " :")) != NULL)
ce426f
-	if (p[0] != '\0'
ce426f
-	    && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
ce426f
-		|| strchr (p, '/') == NULL))
ce426f
-	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
ce426f
-
ce426f
+      npreloads += handle_ld_preload (preloadlist, main_map);
ce426f
       HP_TIMING_NOW (stop);
ce426f
       HP_TIMING_DIFF (diff, start, stop);
ce426f
       HP_TIMING_ACCUM_NT (load_time, diff);