This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug dynamic-link/14612] New: Bogus input causes ld --verify to segfault
- From: "law at redhat dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: Mon, 24 Sep 2012 18:33:02 +0000
- Subject: [Bug dynamic-link/14612] New: Bogus input causes ld --verify to segfault
- Auto-submitted: auto-generated
http://sourceware.org/bugzilla/show_bug.cgi?id=14612
Bug #: 14612
Summary: Bogus input causes ld --verify to segfault
Product: glibc
Version: 2.17
Status: NEW
Severity: normal
Priority: P2
Component: dynamic-link
AssignedTo: unassigned@sourceware.org
ReportedBy: law@redhat.com
Classification: Unclassified
Given an i686 executable with the following program headers:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08050034 0x00000000 0x000c0 0x000c0 R E 0
INTERP 0x0000f4 0x00000000 0x00000000 0x00011 0x00000 R 0
[Requesting program interpreter: /usr/lib/ld.so.1]
LOAD 0x000000 0x08050000 0x00000000 0x0d0b8 0x0d0b8 R E 0x10000
LOAD 0x00d0b8 0x0806d0b8 0x00000000 0x01d97 0x0259c RWE 0x10000
DYNAMIC 0x00d214 0x0806d214 0x00000000 0x000f8 0x00000 RWE 0
NOTE 0x00ee4f 0x00000000 0x00000000 0x000c8 0x00000 0
Running ld.so --verify on that executable will cause a segafult in strcmp as we
pass a NULL pointer as one of the arguments.
If we look at the PT_INTERP code we have:
case PT_INTERP:
/* This "interpreter segment" was used by the program loader to
find the program interpreter, which is this program itself, the
dynamic linker. We note what name finds us, so that a future
dlopen call or DT_NEEDED entry, for something that wants to link
against the dynamic linker as a shared library, will know that
the shared object is already loaded. */
_dl_rtld_libname.name = ((const char *) main_map->l_addr
+ ph->p_vaddr);
/* _dl_rtld_libname.next = NULL; Already zero. */
GL(dl_rtld_map).l_libname = &_dl_rtld_libname;
[ ... ]
has_interp = true;
main_map->l_addr and ph->p_vaddr will both be zero. Thus _dl_rtld_libname.name
will be zero. _dl_rtld_libname gets copied into GL(dl_rtld_map).l_libname.
Then slightly later we have this:
/* If the current libname is different from the SONAME, add the
latter as well. */
if (GL(dl_rtld_map).l_info[DT_SONAME] != NULL
&& strcmp (GL(dl_rtld_map).l_libname->name,
(const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+ GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val) != 0)
Note now we pass GL(dl_rtld_map).l_libname->name to strcmp. That value is NULL
resulting in the segfault.
So the question in my mind is how far do we go to avoid faulting on bogus
input? It's easy enough to check for NULL, but a bogus PT_INTERP could cause a
fault by pointing to any unmapped memory region.
Assuming we can settle that question, we also need to avoid setting
"has_interp" to true when the PT_INTERP is bogus. Otherwise we'll think we got
a valid interpreter and won't flag the executable/DSO has bogus in this code:
if (__builtin_expect (mode, normal) == verify)
{
/* We were called just to verify that this is a dynamic
executable using us as the program interpreter. Exit with an
error if we were not able to load the binary or no interpreter
is specified (i.e., this is no dynamically linked binary. */
if (main_map->l_ld == NULL)
_exit (1);
/* We allow here some platform specific code. */
#ifdef DISTINGUISH_LIB_VERSIONS
DISTINGUISH_LIB_VERSIONS;
#endif
_exit (has_interp ? 0 : 2);
}
--
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.