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] [BZ #18422] elf/tst-audit tests fail without PLT entries


On Sun, May 24, 2015 at 7:06 PM, Carlos O'Donell <carlos@redhat.com> wrote:

> And that is the *real* bug. Please fix that instead of removing -Wl,-z,now.
> It should be a net-zero performance chance since either you are doing
> relocations for the GOT and then the PLT, or the GOT twice?

I did a closer look.  Nothing is wrong, except for that tst-audit2 expects
certain order in ld.so.  With JUMP_SLOT relocation, the GOTPLT entry of
calloc is update to calloc defined in tst-audit2:

(gdb) bt
#0  0xf7fe56bd in elf_machine_rel (reloc=<optimized out>,
    skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>,
    version=<optimized out>, sym=<optimized out>, map=<optimized out>)
    at ../sysdeps/i386/dl-machine.h:329
#1  elf_dynamic_do_Rel (skip_ifunc=<optimized out>, lazy=<optimized out>,
    nrelative=<optimized out>, relsize=<optimized out>,
    reladdr=<optimized out>, map=<optimized out>) at do-rel.h:137
#2  _dl_relocate_object (scope=0xf7ffdab8, reloc_mode=reloc_mode@entry=0,
    consider_profiling=1, consider_profiling@entry=0) at dl-reloc.c:258
#3  0xf7fdc648 in dl_main (phdr=<optimized out>, phnum=<optimized out>,
    user_entry=0xffffcf1c, auxv=0xffffd0a8) at rtld.c:2133
#4  0xf7ff0de7 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0xffffcfb0,
    dl_main=dl_main@entry=0xf7fda6f0 <dl_main>) at ../elf/dl-sysdep.c:249
#5  0xf7fddd05 in _dl_start_final (arg=0xffffcfb0) at rtld.c:308
#6  _dl_start (arg=0xffffcfb0) at rtld.c:414
#7  0xf7fd9a87 in _start ()
   from /export/build/gnu/glibc-32bit/build-i686-linux/elf/ld.so
(gdb)

and then calloc is called:

(gdb) c
Continuing.

Breakpoint 4, calloc (n=n@entry=20, m=4) at tst-audit2.c:18
18 {
(gdb) bt
#0  calloc (n=n@entry=20, m=4) at tst-audit2.c:18
#1  0xf7fe668d in _dl_relocate_object (scope=0xf7ffdab8,
    reloc_mode=reloc_mode@entry=0, consider_profiling=1,
    consider_profiling@entry=0) at dl-reloc.c:272
#2  0xf7fdc648 in dl_main (phdr=<optimized out>, phnum=<optimized out>,
    user_entry=0xffffcf1c, auxv=0xffffd0a8) at rtld.c:2133
#3  0xf7ff0de7 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0xffffcfb0,
    dl_main=dl_main@entry=0xf7fda6f0 <dl_main>) at ../elf/dl-sysdep.c:249
#4  0xf7fddd05 in _dl_start_final (arg=0xffffcfb0) at rtld.c:308
#5  _dl_start (arg=0xffffcfb0) at rtld.c:414
#6  0xf7fd9a87 in _start ()
   from /export/build/gnu/glibc-32bit/build-i686-linux/elf/ld.so
(gdb)

With GLOB_DAT relocation, calloc in ld.so is called first:

(gdb) bt
#0  calloc (nmemb=20, size=4) at dl-minimal.c:102
#1  0xf7fe665d in _dl_relocate_object (scope=0xf7fcfb20, reloc_mode=1,
    consider_profiling=1) at dl-reloc.c:272
#2  0xf7fdc500 in dl_main (phdr=<optimized out>, phnum=<optimized out>,
    user_entry=0xffffcf0c, auxv=0xffffd098) at rtld.c:2074
#3  0xf7ff0db7 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0xffffcfa0,
    dl_main=dl_main@entry=0xf7fda6c0 <dl_main>) at ../elf/dl-sysdep.c:249
#4  0xf7fddcd5 in _dl_start_final (arg=0xffffcfa0) at rtld.c:308
#5  _dl_start (arg=0xffffcfa0) at rtld.c:414
#6  0xf7fd9a57 in _start ()
   from /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so
(gdb)

and then the GOT entry of calloc is updated:

(gdb) bt
#0  0xf7fe568d in elf_machine_rel (reloc=<optimized out>,
    skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>,
    version=<optimized out>, sym=<optimized out>, map=<optimized out>)
    at ../sysdeps/i386/dl-machine.h:329
#1  elf_dynamic_do_Rel (skip_ifunc=<optimized out>, lazy=<optimized out>,
    nrelative=<optimized out>, relsize=<optimized out>,
    reladdr=<optimized out>, map=<optimized out>) at do-rel.h:137
#2  _dl_relocate_object (scope=0xf7ffdab8, reloc_mode=reloc_mode@entry=0,
    consider_profiling=1, consider_profiling@entry=0) at dl-reloc.c:258
#3  0xf7fdc618 in dl_main (phdr=<optimized out>, phnum=<optimized out>,
    user_entry=0xffffcf0c, auxv=0xffffd098) at rtld.c:2133
#4  0xf7ff0db7 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0xffffcfa0,
    dl_main=dl_main@entry=0xf7fda6c0 <dl_main>) at ../elf/dl-sysdep.c:249
#5  0xf7fddcd5 in _dl_start_final (arg=0xffffcfa0) at rtld.c:308
#6  _dl_start (arg=0xffffcfa0) at rtld.c:414
#7  0xf7fd9a57 in _start ()
   from /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so
(gdb)

After, calloc isn't called and magic in tst-audit2 isn't updated.  Both
orders are correct.  Here is a patch to make sure that calloc in tst-audit2.c is
called at least once from ld.so.

> I think it is important we continue to build ld.so with -Wl,-z,now, both
> for the optimizations, and for consistency among our security tooling.
>
> I'm happy to hear input from others.
>
> Have you checked to see how your patch to remove the PLT impacts analysis
> tooling like Asan and Valgrind?
>

No, i didn't test them nor I expect any problems.



-- 
H.J.
From 31d9cfee87edf3acf95640db262b950e3b0514f3 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 25 May 2015 11:30:57 -0700
Subject: [PATCH] Make sure that calloc is called at least once
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

PLT relocations aren't required when -z now used.  Linker on master with:

commit 25070364b0ce33eed46aa5d78ebebbec6accec7e
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sat May 16 07:00:21 2015 -0700

    Don't generate PLT relocations for now binding

    There is no need for PLT relocations with -z now. We can use GOT
    relocations, which take less space, instead and replace 16-byte .plt
    entres with 8-byte .plt.got entries.

    bfd/

      * elf32-i386.c (elf_i386_check_relocs): Create .plt.got section
      for now binding.
      (elf_i386_allocate_dynrelocs): Use .plt.got section for now
      binding.
      * elf64-x86-64.c (elf_x86_64_check_relocs): Create .plt.got
      section for now binding.
      (elf_x86_64_allocate_dynrelocs): Use .plt.got section for now
      binding.

won't generate PLT relocations with -z now.  elf/tst-audit2.c expect
certain order of execution in ld.so. ÂWith PLT relocations, the GOTPLT
entry of calloc is update to calloc defined in tst-audit2:

(gdb) bt
  skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>,
  version=<optimized out>, sym=<optimized out>, map=<optimized out>)
  at ../sysdeps/i386/dl-machine.h:329
out>,
  nrelative=<optimized out>, relsize=<optimized out>,
  reladdr=<optimized out>, map=<optimized out>) at do-rel.h:137
reloc_mode=reloc_mode@entry=0,
  consider_profiling=1, consider_profiling@entry=0) at dl-reloc.c:258
  user_entry=0xffffcf1c, auxv=0xffffd0a8) at rtld.c:2133
  start_argptr=start_argptr@entry=0xffffcfb0,
  dl_main=dl_main@entry=0xf7fda6f0 <dl_main>) at
../elf/dl-sysdep.c:249
 Âfrom /export/build/gnu/glibc-32bit/build-i686-linux/elf/ld.so
(gdb)

and then calloc is called:

(gdb) c
Continuing.

Breakpoint 4, calloc (n=n@entry=20, m=4) at tst-audit2.c:18
18 {
(gdb) bt
  reloc_mode=reloc_mode@entry=0, consider_profiling=1,
  consider_profiling@entry=0) at dl-reloc.c:272
  user_entry=0xffffcf1c, auxv=0xffffd0a8) at rtld.c:2133
  start_argptr=start_argptr@entry=0xffffcfb0,
  dl_main=dl_main@entry=0xf7fda6f0 <dl_main>) at
../elf/dl-sysdep.c:249
 Âfrom /export/build/gnu/glibc-32bit/build-i686-linux/elf/ld.so
(gdb)

With GOT relocation, calloc in ld.so is called first:

(gdb) bt
  consider_profiling=1) at dl-reloc.c:272
  user_entry=0xffffcf0c, auxv=0xffffd098) at rtld.c:2074
  start_argptr=start_argptr@entry=0xffffcfa0,
  dl_main=dl_main@entry=0xf7fda6c0 <dl_main>) at
../elf/dl-sysdep.c:249
 Âfrom /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so
(gdb)

and then the GOT entry of calloc is updated:

(gdb) bt
  skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>,
  version=<optimized out>, sym=<optimized out>, map=<optimized out>)
  at ../sysdeps/i386/dl-machine.h:329
out>,
  nrelative=<optimized out>, relsize=<optimized out>,
  reladdr=<optimized out>, map=<optimized out>) at do-rel.h:137
reloc_mode=reloc_mode@entry=0,
  consider_profiling=1, consider_profiling@entry=0) at dl-reloc.c:258
  user_entry=0xffffcf0c, auxv=0xffffd098) at rtld.c:2133
  start_argptr=start_argptr@entry=0xffffcfa0,
  dl_main=dl_main@entry=0xf7fda6c0 <dl_main>) at
../elf/dl-sysdep.c:249
 Âfrom /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so
(gdb)

After that, since calloc isn't called from ld.so nor any other modules,
magic in tst-audit2 isn't updated. ÂBoth orders are correct.  This patch
makes sure that calloc in tst-audit2.c is called at least once from ld.so.

	[BZ #18422]
	* Makefile ($(objpfx)tst-audit2): Depend on $(libdl).
	($(objpfx)tst-audit2.out): Also depend on
	$(objpfx)tst-auditmod9b.so.
	* elf/tst-audit2.c: Include <dlfcn.h>.
	(calloc_called): New.
	(calloc): Allow to be called more than once.
	(do_test): dllopen/dlclose $ORIGIN/tst-auditmod9b.so.
---
 elf/Makefile     |  3 ++-
 elf/tst-audit2.c | 23 ++++++++++++++++++-----
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/elf/Makefile b/elf/Makefile
index b06e0a7..dedf3c7 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1034,7 +1034,8 @@ $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
 $(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
 tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
 
-$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so
+$(objpfx)tst-audit2: $(libdl)
+$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so $(objpfx)tst-auditmod9b.so
 # Prevent GCC-5 from translating a malloc/memset pair into calloc
 CFLAGS-tst-audit2.c += -fno-builtin
 tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
diff --git a/elf/tst-audit2.c b/elf/tst-audit2.c
index acad1b0..44c74d4 100644
--- a/elf/tst-audit2.c
+++ b/elf/tst-audit2.c
@@ -3,10 +3,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <dlfcn.h>
 
 #define MAGIC1 0xabcdef72
 #define MAGIC2 0xd8675309
 static __thread unsigned int magic[] = { MAGIC1, MAGIC2 };
+static __thread int calloc_called;
 
 #undef calloc
 
@@ -16,13 +18,19 @@ static __thread unsigned int magic[] = { MAGIC1, MAGIC2 };
 void *
 calloc (size_t n, size_t m)
 {
-  if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
+  if (!calloc_called)
     {
-      printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC1, MAGIC2);
-      abort ();
+      /* Allow our calloc to be called more than once.  */
+      calloc_called = 1;
+      if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
+	{
+	  printf ("{%x, %x} != {%x, %x}\n",
+		  magic[0], magic[1], MAGIC1, MAGIC2);
+	  abort ();
+	}
+      magic[0] = MAGIC2;
+      magic[1] = MAGIC1;
     }
-  magic[0] = MAGIC2;
-  magic[1] = MAGIC1;
 
   n *= m;
   void *ptr = malloc (n);
@@ -34,6 +42,11 @@ calloc (size_t n, size_t m)
 static int
 do_test (void)
 {
+  /* Make sure that our calloc is called from the dynamic linker at least
+     once.  */
+  void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
+  if (h != NULL)
+    dlclose (h);
   if (magic[1] != MAGIC1 || magic[0] != MAGIC2)
     {
       printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC2, MAGIC1);
-- 
2.1.0


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