From 5b9b19d9ee5040cad920e8e31e4c2100fcf8d25f Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 25 Sep 2017 17:16:52 -0700
Subject: [PATCH] Skip PT_DYNAMIC segment with p_filesz == 0 [BZ #22101]

ELF object generated with "objcopy --only-keep-debug" has

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.

	[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.
---
 elf/Makefile     |  9 ++++++++-
 elf/dl-load.c    | 10 ++++++++--
 elf/tst-debug1.c | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 elf/tst-debug1.c

diff --git a/elf/Makefile b/elf/Makefile
index 7cf959aabd..e21f37e30b 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -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 $< $@
diff --git a/elf/dl-load.c b/elf/dl-load.c
index a067760cc6..d43bb2dd5e 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -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 file from "objcopy --only-keep-debug"
+		 contains PT_DYNAMIC segment with p_filesz == 0.  Skip
+		 such segment to avoid 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
index 0000000000..aa2f4886bf
--- /dev/null
+++ b/elf/tst-debug1.c
@@ -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>
-- 
2.13.5
