This is followup to 665d6a5916.
Fixes <https://bugs.gnu.org/27489>.
* gnu/packages/base.scm (glibc-2.25-patched, glibc-2.24, glibc-2.23)
(glibc-2.22): Add glibc-vectorized-strcspn-guards.patch to patches.
Move a comment where it belongs.
* gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch: Swap with ...
* gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch: ... this.
* gnu/packages/patches/glibc-vectorized-strcspn-guards.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.  Fix formatting.
		
	
			
		
			
				
	
	
		
			124 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 6d0ba622891bed9d8394eef1935add53003b12e8 Mon Sep 17 00:00:00 2001
 | 
						|
From: Florian Weimer <fweimer@redhat.com>
 | 
						|
Date: Mon, 19 Jun 2017 22:31:04 +0200
 | 
						|
Subject: [PATCH] ld.so: Reject overly long LD_PRELOAD path elements
 | 
						|
 | 
						|
patch from:
 | 
						|
https://sourceware.org/git/?p=glibc.git;a=patch;h=6d0ba622891bed9d8394eef1935add53003b12e8
 | 
						|
 | 
						|
---
 | 
						|
 ChangeLog  |  7 ++++++
 | 
						|
 elf/rtld.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
 | 
						|
 2 files changed, 73 insertions(+), 16 deletions(-)
 | 
						|
 | 
						|
diff --git a/elf/rtld.c b/elf/rtld.c
 | 
						|
index 2269dbe..86ae20c 100644
 | 
						|
--- a/elf/rtld.c
 | 
						|
+++ b/elf/rtld.c
 | 
						|
@@ -99,6 +99,35 @@ uintptr_t __pointer_chk_guard_local
 | 
						|
 strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
 | 
						|
 #endif
 | 
						|
 
 | 
						|
+/* Length limits for names and paths, to protect the dynamic linker,
 | 
						|
+   particularly when __libc_enable_secure is active.  */
 | 
						|
+#ifdef NAME_MAX
 | 
						|
+# define SECURE_NAME_LIMIT NAME_MAX
 | 
						|
+#else
 | 
						|
+# define SECURE_NAME_LIMIT 255
 | 
						|
+#endif
 | 
						|
+#ifdef PATH_MAX
 | 
						|
+# define SECURE_PATH_LIMIT PATH_MAX
 | 
						|
+#else
 | 
						|
+# define SECURE_PATH_LIMIT 1024
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+/* Check that AT_SECURE=0, or that the passed name does not contain
 | 
						|
+   directories and is not overly long.  Reject empty names
 | 
						|
+   unconditionally.  */
 | 
						|
+static bool
 | 
						|
+dso_name_valid_for_suid (const char *p)
 | 
						|
+{
 | 
						|
+  if (__glibc_unlikely (__libc_enable_secure))
 | 
						|
+    {
 | 
						|
+      /* Ignore pathnames with directories for AT_SECURE=1
 | 
						|
+	 programs, and also skip overlong names.  */
 | 
						|
+      size_t len = strlen (p);
 | 
						|
+      if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
 | 
						|
+	return false;
 | 
						|
+    }
 | 
						|
+  return *p != '\0';
 | 
						|
+}
 | 
						|
 
 | 
						|
 /* List of auditing DSOs.  */
 | 
						|
 static struct audit_list
 | 
						|
@@ -718,6 +747,42 @@ static const char *preloadlist attribute_relro;
 | 
						|
 /* Nonzero if information about versions has to be printed.  */
 | 
						|
 static int version_info attribute_relro;
 | 
						|
 
 | 
						|
+/* The LD_PRELOAD environment variable gives list of libraries
 | 
						|
+   separated by white space or colons that are loaded before the
 | 
						|
+   executable's dependencies and prepended to the global scope list.
 | 
						|
+   (If the binary is running setuid all elements containing a '/' are
 | 
						|
+   ignored since it is insecure.)  Return the number of preloads
 | 
						|
+   performed.  */
 | 
						|
+unsigned int
 | 
						|
+handle_ld_preload (const char *preloadlist, struct link_map *main_map)
 | 
						|
+{
 | 
						|
+  unsigned int npreloads = 0;
 | 
						|
+  const char *p = preloadlist;
 | 
						|
+  char fname[SECURE_PATH_LIMIT];
 | 
						|
+
 | 
						|
+  while (*p != '\0')
 | 
						|
+    {
 | 
						|
+      /* Split preload list at space/colon.  */
 | 
						|
+      size_t len = strcspn (p, " :");
 | 
						|
+      if (len > 0 && len < sizeof (fname))
 | 
						|
+	{
 | 
						|
+	  memcpy (fname, p, len);
 | 
						|
+	  fname[len] = '\0';
 | 
						|
+	}
 | 
						|
+      else
 | 
						|
+	fname[0] = '\0';
 | 
						|
+
 | 
						|
+      /* Skip over the substring and the following delimiter.  */
 | 
						|
+      p += len;
 | 
						|
+      if (*p != '\0')
 | 
						|
+	++p;
 | 
						|
+
 | 
						|
+      if (dso_name_valid_for_suid (fname))
 | 
						|
+	npreloads += do_preload (fname, main_map, "LD_PRELOAD");
 | 
						|
+    }
 | 
						|
+  return npreloads;
 | 
						|
+}
 | 
						|
+
 | 
						|
 static void
 | 
						|
 dl_main (const ElfW(Phdr) *phdr,
 | 
						|
 	 ElfW(Word) phnum,
 | 
						|
@@ -1464,23 +1529,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 | 
						|
 
 | 
						|
   if (__glibc_unlikely (preloadlist != NULL))
 | 
						|
     {
 | 
						|
-      /* The LD_PRELOAD environment variable gives list of libraries
 | 
						|
-	 separated by white space or colons that are loaded before the
 | 
						|
-	 executable's dependencies and prepended to the global scope
 | 
						|
-	 list.  If the binary is running setuid all elements
 | 
						|
-	 containing a '/' are ignored since it is insecure.  */
 | 
						|
-      char *list = strdupa (preloadlist);
 | 
						|
-      char *p;
 | 
						|
-
 | 
						|
       HP_TIMING_NOW (start);
 | 
						|
-
 | 
						|
-      /* Prevent optimizing strsep.  Speed is not important here.  */
 | 
						|
-      while ((p = (strsep) (&list, " :")) != NULL)
 | 
						|
-	if (p[0] != '\0'
 | 
						|
-	    && (__builtin_expect (! __libc_enable_secure, 1)
 | 
						|
-		|| strchr (p, '/') == NULL))
 | 
						|
-	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
 | 
						|
-
 | 
						|
+      npreloads += handle_ld_preload (preloadlist, main_map);
 | 
						|
       HP_TIMING_NOW (stop);
 | 
						|
       HP_TIMING_DIFF (diff, start, stop);
 | 
						|
       HP_TIMING_ACCUM_NT (load_time, diff);
 | 
						|
-- 
 | 
						|
2.9.3
 | 
						|
 |