This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

avoid crashing after mapping past EOF of invalid shared object


This first came up when trying to ld.so --verify the split debuginfo
file of a dynamic library.  The .so.debug file contains the same PHDRs,
with the same PT_LOAD offsets and sizes, even though the .debug file
does not contain those sections.

We try to mmap the sections anyway, and the kernel happily returns
success in the attempts to mmap past EOF.  However, when we attempt to
access those pages, e.g. to zero out the trailing portion, we get a bus
error.

Although the crash is harmless in this case (but perhaps not so much if
a running process attempts to dlopen() a shared object truncated: we'd
better return an error than crash), this is a problem of input
validation: we shouldn't attempt to map a page that isn't present, and
reject the file as ill-formed instead.

There's still room for âexploitingâ this situation by truncating the
pseudo shared object between stat()ing it and mapping it in.  However,
I'm not convinced this would be any more of an issue than the crash we'd
get by accessing a page of code or data if a perfectly valid shared
object is truncated after it is loaded.

So the patch has two goals: offer a nicer error for corrupted shared
objects, and document that the truncation in the window between stat and
mmap is not an exploitable crash.

Can anyone think of any reason not to reject shared objects with PT_LOAD
segments past their EOF?  Alternately, can anyone suggest some other
(cheap) way to test whether the last mmap()ed page won't crash upon
zeroing out its end, rather than trying and crashing?

for  ChangeLog
2012-02-03  Alexandre Oliva  <aoliva@redhat.com>

	* elf/dl-load.c (_dl_map_object_from_fd): Avoid attempting to map
	past the end of the shared object.

Index: elf/dl-load.c
===================================================================
--- elf/dl-load.c.orig	2012-02-03 14:27:29.785848352 -0200
+++ elf/dl-load.c	2012-02-03 14:27:33.434800747 -0200
@@ -1129,6 +1129,16 @@ _dl_map_object_from_fd (const char *name
 		= N_("ELF load command address/offset not properly aligned");
 	      goto call_lose;
 	    }
+	  if (__builtin_expect ((ph->p_offset + ph->p_filesz > st.st_size), 0))
+	    {
+	      /* If the segment requires zeroing of part of its last
+		 page, we'll crash when accessing the unmapped page.
+		 There's still a possibility of a race, if the shared
+		 object is truncated between the fxstat above and the
+		 memset below.  */
+	      errstring = N_("ELF load command past end of file");
+	      goto call_lose;
+	    }
 
 	  c = &loadcmds[nloadcmds++];
 	  c->mapstart = ph->p_vaddr & ~(GLRO(dl_pagesize) - 1);

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]