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]

Re: [patch] Fix for BZ 16381 -- explicit loader invocation "ld.so ./a.out" on a PIE binary calls global ctors twice


On Thu, Jan 16, 2014 at 8:59 AM, Carlos O'Donell <carlos@redhat.com> wrote:

Attached is a second version of the patch, modified to address Carlos'
comments.

This is a fix for PR 16381 -- "ld.so ./a.out" on PIE binary calls global
constructors twice.

The reason for the bug is that a.out was loaded as lt_library when using
"ld.so a.out", but as lt_executable when using "a.out" directly (contrast
the call to _dl_new_object() from dl_main in rtld.c for "normal" invocation
(the kernel has already mapped a.out in) with the call to _dl_map_object()
for the loader-prefixed invocation.

When lt_executable is used, the code in call_init() correctly skips
initialization, since the crt0.o will perform it (again).

The reason this worked for non-PIE binaries is that _dl_map_object_from_fd
re-set l_type to lt_executable when it discovered that it just loaded
ET_EXEC.

This patch simply sets correct type for loading of the executable from
the start.

Tested on Linux / x86_64 with no regressions.

-- 
Paul Pluzhnikov


2014-01-17  Paul Pluzhnikov  <ppluzhnikov@google.com>

        * elf/Makefile: Add tst-pie2
        * elf/tst-pie2.c: New file.
	* elf/dl-load.c (_dl_map_object_from_fd): Assert correct l_type
	for ET_EXEC.
        * elf/rtld.c (map_doit): Load executable as lt_executable.
	(dl_main): Likewise.


diff --git a/NEWS b/NEWS
index da86ee5..93dfff5 100644
--- a/NEWS
+++ b/NEWS
@@ -24,8 +24,8 @@ Version 2.19
   16074, 16077, 16078, 16103, 16112, 16133, 16143, 16144, 16146, 16150,
   16151, 16153, 16167, 16172, 16195, 16214, 16245, 16271, 16274, 16283,
   16289, 16293, 16314, 16316, 16330, 16337, 16338, 16356, 16365, 16366,
-  16369, 16372, 16375, 16379, 16384, 16385, 16386, 16387, 16390, 16394,
-  16400, 16407, 16408, 16414, 16430, 16453.
+  16369, 16372, 16375, 16379, 16381, 16384, 16385, 16386, 16387, 16390,
+  16394, 16400, 16407, 16408, 16414, 16430, 16453.

 * Slovenian translations for glibc messages have been contributed by the
   Translation Project's Slovenian team of translators.
diff --git a/elf/Makefile b/elf/Makefile
index 4c58fc9..055ea38 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -214,8 +214,8 @@ modules-names = testobj1 testobj2 testobj3
testobj4 testobj5 testobj6 \
 		tst-array5dep tst-null-argv-lib
 ifeq (yesyes,$(have-fpie)$(build-shared))
 modules-names += tst-piemod1
-tests += tst-pie1
-tests-pie += tst-pie1
+tests += tst-pie1 tst-pie2
+tests-pie += tst-pie1 tst-pie2
 endif
 modules-execstack-yes = tst-execstack-mod
 extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
@@ -882,6 +882,7 @@ $(objpfx)tst-array5-static.out: tst-array5-static.exp \
 	cmp $@ tst-array5-static.exp > /dev/null

 CFLAGS-tst-pie1.c += $(pie-ccflag)
+CFLAGS-tst-pie2.c += $(pie-ccflag)

 $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so

diff --git a/elf/dl-load.c b/elf/dl-load.c
index ee12f32..6f6b344 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1534,8 +1534,8 @@ cannot enable executable stack as shared object
requires");
   /* Signal that we closed the file.  */
   fd = -1;

-  if (l->l_type == lt_library && type == ET_EXEC)
-    l->l_type = lt_executable;
+  /* If this is ET_EXEC, we should have loaded it as lt_executable.  */
+  assert (type != ET_EXEC || l->l_type == lt_executable);

   l->l_entry += l->l_addr;

diff --git a/elf/rtld.c b/elf/rtld.c
index 6dcbabc..021b72e 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -623,7 +623,8 @@ static void
 map_doit (void *a)
 {
   struct map_args *args = (struct map_args *) a;
-  args->map = _dl_map_object (args->loader, args->str, lt_library, 0,
+  int type = (args->mode == __RTLD_OPENEXEC) ? lt_executable : lt_library;
+  args->map = _dl_map_object (args->loader, args->str, type, 0,
 			      args->mode, LM_ID_BASE);
 }

@@ -1075,7 +1076,7 @@ of this helper program; chances are you did not
intend to run this program.\n\
       else
 	{
 	  HP_TIMING_NOW (start);
-	  _dl_map_object (NULL, rtld_progname, lt_library, 0,
+	  _dl_map_object (NULL, rtld_progname, lt_executable, 0,
 			  __RTLD_OPENEXEC, LM_ID_BASE);
 	  HP_TIMING_NOW (stop);

diff --git a/elf/tst-pie2.c b/elf/tst-pie2.c
new file mode 100644
index 0000000..1da674e
--- /dev/null
+++ b/elf/tst-pie2.c
@@ -0,0 +1,38 @@
+/* Test case for BZ 16381
+
+   Copyright (C) 2014 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 <assert.h>
+
+static int g;
+
+void init_g (void) __attribute__((constructor));
+
+void
+init_g (void)
+{
+  assert (g == 0);
+  g += 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+  return 0;
+}

Attachment: glibc-PR16381-2014017.txt
Description: Text document


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