]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Skip PT_DYNAMIC segment with p_filesz == 0 [BZ #22101]
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 26 Sep 2017 20:49:48 +0000 (13:49 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 26 Sep 2017 20:50:01 +0000 (13:50 -0700)
ELF objects generated with "objcopy --only-keep-debug" have

Type     Offset  VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
DYNAMIC  0x0+e28 0x0+200e40 0x0+200e40 0x0+    0x0+1a0 RW  0x8

with 0 file size. ld.so should skip such PT_DYNAMIC segments.

Without a PT_DYNAMIC segment the loading of the shared object will
fail, and therefore ldd on such objects will also fail instead of
crashing. This provides better diagnostics for tooling that is
attempting to inspect the invalid shared objects which may just
contain debug information.

[BZ #22101]
* elf/Makefile (tests): Add tst-debug1.
($(objpfx)tst-debug1): New.
($(objpfx)tst-debug1.out): Likewise.
($(objpfx)tst-debug1mod1.so): Likewise.
* elf/dl-load.c (_dl_map_object_from_fd): Skip PT_DYNAMIC segment
with p_filesz == 0.
* elf/tst-debug1.c: New file.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
ChangeLog
elf/Makefile
elf/dl-load.c
elf/tst-debug1.c [new file with mode: 0644]

index f8e097e17fa846c35afab502a25ad67f666a617f..d15964db69e5b19ba9f00ab1720aedbad8b85b3a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2017-09-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       [BZ #22101]
+       * elf/Makefile (tests): Add tst-debug1.
+       ($(objpfx)tst-debug1): New.
+       ($(objpfx)tst-debug1.out): Likewise.
+       ($(objpfx)tst-debug1mod1.so): Likewise.
+       * elf/dl-load.c (_dl_map_object_from_fd): Skip PT_DYNAMIC segment
+       with p_filesz == 0.
+       * elf/tst-debug1.c: New file.
+
 2017-09-26  Joseph Myers  <joseph@codesourcery.com>
 
        * sysdeps/sparc/sparc-ifunc.h [!__ASSEMBLER__] (sparc_libm_ifunc):
index 7cf959aabdfafa607688cd72c5b24d6b101f2f97..e21f37e30b67ba3a04945f45d67bf43c383f940b 100644 (file)
@@ -181,7 +181,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
         tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
         tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
         tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
-        tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose
+        tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
+        tst-debug1
 #       reldep9
 tests-internal += loadtest unload unload2 circleload1 \
         neededtest neededtest2 neededtest3 neededtest4 \
@@ -1417,3 +1418,9 @@ tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
                     LD_HWCAP_MASK=0x1
 tst-env-setuid-tunables-ENV = \
        GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096
+
+$(objpfx)tst-debug1: $(libdl)
+$(objpfx)tst-debug1.out: $(objpfx)tst-debug1mod1.so
+
+$(objpfx)tst-debug1mod1.so: $(objpfx)testobj1.so
+       $(OBJCOPY) --only-keep-debug $< $@
index a067760cc64ec79af2dd6040b9e8508004e1a63f..1220183ce29f83668d2044dc25093c08184335fe 100644 (file)
@@ -1052,8 +1052,14 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
             segments are mapped in.  We record the addresses it says
             verbatim, and later correct for the run-time load address.  */
        case PT_DYNAMIC:
-         l->l_ld = (void *) ph->p_vaddr;
-         l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
+         if (ph->p_filesz)
+           {
+             /* Debuginfo only files from "objcopy --only-keep-debug"
+                contain a PT_DYNAMIC segment with p_filesz == 0.  Skip
+                such a segment to avoid a crash later.  */
+             l->l_ld = (void *) ph->p_vaddr;
+             l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
+           }
          break;
 
        case PT_PHDR:
diff --git a/elf/tst-debug1.c b/elf/tst-debug1.c
new file mode 100644 (file)
index 0000000..aa2f488
--- /dev/null
@@ -0,0 +1,34 @@
+/* Unit test for dlopen on ELF object from "objcopy --only-keep-debug".
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  void *h = dlopen ("tst-debug1mod1.so", RTLD_LAZY);
+  if (h != NULL)
+    {
+      puts ("shouldn't load tst-debug1mod1.so");
+      return 1;
+    }
+  return 0;
+}
+
+#include <support/test-driver.c>