Carlos O'Donell 0e17ea2
Short description: Work ld.so --verify crash on debuginfo files.
Carlos O'Donell 0e17ea2
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Carlos O'Donell 0e17ea2
Origin: PATCH
Carlos O'Donell 0e17ea2
Bug-RHEL: #741105, #767146
Carlos O'Donell 0e17ea2
Upstream status: not-needed
Carlos O'Donell 0e17ea2
Carlos O'Donell 0e17ea2
This change is designed to work around running ld.so on a debuginfo
Carlos O'Donell 0e17ea2
file. This is the wrong fix for this problem and should be dropped.
Carlos O'Donell 0e17ea2
The correct solution is to mark debuginfo files as new types of
Carlos O'Donell 0e17ea2
ELF files.
Carlos O'Donell 0e17ea2
Arjun Shankar 81c303b
diff --git a/elf/dl-load.c b/elf/dl-load.c
Arjun Shankar 81c303b
index 24e2819345995bd9..007121144e71d9cf 100644
Arjun Shankar 81c303b
--- a/elf/dl-load.c
Arjun Shankar 81c303b
+++ b/elf/dl-load.c
Arjun Shankar 81c303b
@@ -880,6 +880,18 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
Arjun Shankar 81c303b
      in this information for the executable in case of an explicit
Arjun Shankar 81c303b
      loader invocation.  */
Siddhesh Poyarekar 6223dbf
   struct r_file_id id;
Siddhesh Poyarekar 6223dbf
+  struct stat64 st;
Arjun Shankar 81c303b
+
Siddhesh Poyarekar 6223dbf
+  if (__glibc_unlikely (!_dl_get_file_id (fd, &id, &st)))
Arjun Shankar 81c303b
+    {
Arjun Shankar 81c303b
+      errstring = N_("cannot stat shared object");
Arjun Shankar 81c303b
+      call_lose_errno:
Arjun Shankar 81c303b
+        errval = errno;
Arjun Shankar 81c303b
+      call_lose:
Arjun Shankar 81c303b
+        lose (errval, fd, name, realname, l, errstring,
Arjun Shankar 81c303b
+              make_consistent ? r : NULL, nsid);
Arjun Shankar 81c303b
+    }
Arjun Shankar 81c303b
+
Arjun Shankar 81c303b
   if (mode & __RTLD_OPENEXEC)
Arjun Shankar 81c303b
     {
Arjun Shankar 81c303b
       assert (nsid == LM_ID_BASE);
Arjun Shankar 81c303b
@@ -887,16 +899,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
Arjun Shankar 81c303b
     }
Arjun Shankar 81c303b
   else
Siddhesh Poyarekar 6223dbf
     {
Arjun Shankar 81c303b
-      if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
Arjun Shankar 81c303b
-	{
Arjun Shankar 81c303b
-	  errstring = N_("cannot stat shared object");
Arjun Shankar 81c303b
-	call_lose_errno:
Arjun Shankar 81c303b
-	  errval = errno;
Arjun Shankar 81c303b
-	call_lose:
Arjun Shankar 81c303b
-	  lose (errval, fd, name, realname, l, errstring,
Arjun Shankar 81c303b
-		make_consistent ? r : NULL, nsid);
Arjun Shankar 81c303b
-	}
Arjun Shankar 81c303b
-
Arjun Shankar 81c303b
       /* Look again to see if the real name matched another already loaded.  */
Arjun Shankar 81c303b
       for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
Arjun Shankar 81c303b
 	if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
Arjun Shankar 81c303b
@@ -1074,6 +1076,16 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
92f446a
 		= N_("ELF load command address/offset not properly aligned");
92f446a
 	      goto call_lose;
92f446a
 	    }
Siddhesh Poyarekar c899b49
+	  if (__glibc_unlikely (ph->p_offset + ph->p_filesz > st.st_size))
92f446a
+	    {
92f446a
+	      /* If the segment requires zeroing of part of its last
92f446a
+		 page, we'll crash when accessing the unmapped page.
92f446a
+		 There's still a possibility of a race, if the shared
92f446a
+		 object is truncated between the fxstat above and the
92f446a
+		 memset below.  */
92f446a
+	      errstring = N_("ELF load command past end of file");
92f446a
+	      goto call_lose;
92f446a
+	    }
92f446a
 
Siddhesh Poyarekar c899b49
 	  struct loadcmd *c = &loadcmds[nloadcmds++];
Carlos O'Donell e61b8f4
 	  c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
Arjun Shankar 81c303b
diff --git a/sysdeps/generic/dl-fileid.h b/sysdeps/generic/dl-fileid.h
Arjun Shankar 81c303b
index 6310d46c2a6efc60..209580b6c0b8524b 100644
Arjun Shankar 81c303b
--- a/sysdeps/generic/dl-fileid.h
Arjun Shankar 81c303b
+++ b/sysdeps/generic/dl-fileid.h
Siddhesh Poyarekar 6223dbf
@@ -29,7 +29,8 @@ struct r_file_id
Siddhesh Poyarekar 6223dbf
    On error, returns false, with errno set.  */
Siddhesh Poyarekar 6223dbf
 static inline bool
Siddhesh Poyarekar 6223dbf
 _dl_get_file_id (int fd __attribute__ ((unused)),
Siddhesh Poyarekar 6223dbf
-		 struct r_file_id *id __attribute__ ((unused)))
Siddhesh Poyarekar 6223dbf
+		 struct r_file_id *id __attribute__ ((unused)),
Siddhesh Poyarekar 6223dbf
+		 struct stat64_t *st __attribute__((unused)))
Siddhesh Poyarekar 6223dbf
 {
Siddhesh Poyarekar 6223dbf
   return true;
Siddhesh Poyarekar 6223dbf
 }
Arjun Shankar 81c303b
diff --git a/sysdeps/posix/dl-fileid.h b/sysdeps/posix/dl-fileid.h
Arjun Shankar 81c303b
index ae88a350788a5999..baa17b90a292a4d9 100644
Arjun Shankar 81c303b
--- a/sysdeps/posix/dl-fileid.h
Arjun Shankar 81c303b
+++ b/sysdeps/posix/dl-fileid.h
Siddhesh Poyarekar 6223dbf
@@ -27,18 +27,16 @@ struct r_file_id
Siddhesh Poyarekar 6223dbf
     ino64_t ino;
Siddhesh Poyarekar 6223dbf
   };
Siddhesh Poyarekar 6223dbf
 
Siddhesh Poyarekar 6223dbf
-/* Sample FD to fill in *ID.  Returns true on success.
Siddhesh Poyarekar 6223dbf
+/* Sample FD to fill in *ID and *ST.  Returns true on success.
Siddhesh Poyarekar 6223dbf
    On error, returns false, with errno set.  */
Siddhesh Poyarekar 6223dbf
 static inline bool
Siddhesh Poyarekar 6223dbf
-_dl_get_file_id (int fd, struct r_file_id *id)
Siddhesh Poyarekar 6223dbf
+_dl_get_file_id (int fd, struct r_file_id *id, struct stat64 *st)
Siddhesh Poyarekar 6223dbf
 {
Siddhesh Poyarekar 6223dbf
-  struct stat64 st;
Siddhesh Poyarekar 6223dbf
-
Siddhesh Poyarekar 6223dbf
-  if (__glibc_unlikely (__fxstat64 (_STAT_VER, fd, &st) < 0))
Siddhesh Poyarekar 6223dbf
+  if (__glibc_unlikely (__fxstat64 (_STAT_VER, fd, st) < 0))
Siddhesh Poyarekar 6223dbf
     return false;
Siddhesh Poyarekar 6223dbf
 
Siddhesh Poyarekar 6223dbf
-  id->dev = st.st_dev;
Siddhesh Poyarekar 6223dbf
-  id->ino = st.st_ino;
Siddhesh Poyarekar 6223dbf
+  id->dev = st->st_dev;
Siddhesh Poyarekar 6223dbf
+  id->ino = st->st_ino;
Siddhesh Poyarekar 6223dbf
   return true;
Siddhesh Poyarekar 6223dbf
 }
Siddhesh Poyarekar 6223dbf