Bug 13818 - Bogus LD_PROFILE will cause application to segfault
Summary: Bogus LD_PROFILE will cause application to segfault
Status: RESOLVED DUPLICATE of bug 14831
Alias: None
Product: glibc
Classification: Unclassified
Component: dynamic-link (show other bugs)
Version: 2.15
: P2 normal
Target Milestone: 2.18
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2012-03-07 19:06 UTC by law
Modified: 2014-06-26 14:02 UTC (History)
4 users (show)

See Also:
Last reconfirmed:
fweimer: security-

Potential fix (1.04 KB, text/plain)
2012-03-07 19:06 UTC, law

Note You need to log in before you can comment on or make changes to this bug.
Description law 2012-03-07 19:06:06 UTC
Created attachment 6265 [details]
Potential fix

LD_PROFILE=BLAH /usr/bin/gdb

Results in a segfault in the dynamic linker on my Fedora 16 system.

172       /* This is the address in the array where we store the result of previous
173          relocations.  */
174       struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
175       DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
177       DL_FIXUP_VALUE_TYPE value = *resultp;

The l_reloc_result field is NULL, which causes resultp to point to a near-NULL address and segfault at line 177.

We are processing an R_X86_64_IRELATIVE relocation for libm.

Looking at dl-reloc.c we have:
264     #include "dynamic-link.h"
266         ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
268     #ifndef PROF
269         if (__builtin_expect (consider_profiling, 0))
270           {
271             /* Allocate the array which will contain the already found
272                relocations.  If the shared object lacks a PLT (for example
273                if it only contains lead function) the l_info[DT_PLTRELSZ]
274                will be NULL.  */
275             if (l->l_info[DT_PLTRELSZ] == NULL)
276               {
277                 errstring = N_("%s: no PLTREL found in object %s\n");
278               fatal:
279                 _dl_fatal_printf (errstring,
280                                   rtld_progname ?: "<program name unknown>",
281                                   l->l_name);
282               }
284             l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
285 l->l_info[DT_PLTRELSZ]->d_un.d_val);

Note that we call ELF_DYNAMIC_RELOCATE on line 266 prior to setting up l_reloc_result on line 284.
Comment 1 Carlos O'Donell 2012-03-22 12:33:46 UTC
FAOD can you reproduce this on trunk?

I'm marking this as milestone=2.16 so we look to get this resolved for the next release.
Comment 2 Paul Pluzhnikov 2012-03-22 15:27:26 UTC
I've reproduced this using current git trunk:

commit 48e44791e4d4d755bf7a7dd083d87584dc4779e4
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Thu Mar 22 12:55:19 2012 +0000

Core was generated by `./elf/ld-linux-x86-64.so.2 --library-path .:nptl:math:dlfcn /usr/bin/gdb'.
Program terminated with signal 11, Segmentation fault.
#0  _dl_profile_fixup (l=0x7ffc433d5830, reloc_arg=2, retaddr=140721433520857, regs=0x7fff37c34cd0, framesizep=0x7fff37c35028) at ../elf/dl-runtime.c:176
176	  DL_FIXUP_VALUE_TYPE value = *resultp;
(gdb) bt
#0  _dl_profile_fixup (l=0x7ffc433d5830, reloc_arg=2, 
    retaddr=140721433520857, regs=0x7fff37c34cd0, 
    framesizep=0x7fff37c35028) at ../elf/dl-runtime.c:176
#1  0x00007ffc433ea6c8 in _dl_runtime_profile ()
    at ../sysdeps/x86_64/dl-trampoline.h:48
#2  0x00007ffc430eaad9 in __ieee754_exp ()
    at ../sysdeps/x86_64/fpu/multiarch/e_exp.c:15
#3  0x00007ffc433e1681 in elf_machine_lazy_rel (
    skip_ifunc=<optimized out>, reloc=0x7ffc430e0300, 
    l_addr=140721433456640, map=0x7ffc433d5830)
    at ../sysdeps/x86_64/dl-machine.h:495
#4  elf_dynamic_do_Rela (skip_ifunc=<optimized out>, 
    lazy=<optimized out>, nrelative=<optimized out>, 
    relsize=<optimized out>, reladdr=<optimized out>, 
    map=0x7ffc433d5830) at do-rel.h:85
#5  _dl_relocate_object (scope=0x7ffc433d5b88, 
    reloc_mode=<optimized out>, consider_profiling=1)
    at dl-reloc.c:264
#6  0x00007ffc433d9360 in dl_main (phdr=<optimized out>, 
    phnum=1114560256, user_entry=<optimized out>, 
    auxv=0x7ffc435f9701) at rtld.c:2283
#7  0x00007ffc433eabbc in _dl_sysdep_start (
    start_argptr=<optimized out>, dl_main=0x7ffc433d7b70 <dl_main>)
    at ../elf/dl-sysdep.c:243
#8  0x00007ffc433dad9e in _dl_start_final (arg=0x7fff37c35400)
    at rtld.c:336
#9  _dl_start (arg=0x7fff37c35400) at rtld.c:562
#10 0x00007ffc433d7588 in _start () from ./elf/ld-linux-x86-64.so.2

(gdb) p resultp
$1 = (Elf64_Addr *) 0x40

(gdb) p reloc_result
$2 = (struct reloc_result *) 0x40
Comment 3 Andreas Jaeger 2012-04-06 20:33:03 UTC
Jeff, adding this patch to the openSUSE glibc 2.15 (which contains quite some patches), running the testsuite I get a failure in elf/tst-audit2.out

> cat elf/tst-audit2.out
version: 1
objopen: 0, 
objopen: 0, /build/osc-branches/my-factory-packages/glibc/building/elf/ld-linux-x86-64.so.2
activity: add
objsearch: libc.so.6, LA_SET_ORIG
objsearch: /build/osc-branches/my-factory-packages/glibc/building/libc.so.6, LA_SER_LIBPATH
objopen: 0, /build/osc-branches/my-factory-packages/glibc/building/libc.so.6
activity: consistent
symbind64: symname=__libc_start_main, st_value=0x7f39e38c7320, ndx=2065, flags=0
pltenter: symname=__libc_start_main, st_value=0x7f39e38c7320, ndx=2065, flags=0
symbind64: symname=printf, st_value=0x7f39e38f4a60, ndx=594, flags=0
pltenter: symname=printf, st_value=0x7f39e38f4a60, ndx=594, flags=0
symbind64: symname=free, st_value=0x7f39e3923470, ndx=2177, flags=0
pltenter: symname=free, st_value=0x7f39e3923470, ndx=2177, flags=0
pltenter: symname=free, st_value=0x7f39e3923470, ndx=2177, flags=0
{abcdef72, d8675309} != {d8675309, abcdef72}

But adding the patch to git head, I see no problem with the testsuite. Does it pass the testsuite on Fedora? I'm confused why your patch should have an effect on the openSUSE glibc which mainly contains backports from git plus your patches from Fedora for cycle detection.

Don't spend time to investigate my failure, just please double check that the testsuite passes for you.
Comment 4 law 2012-04-10 05:00:06 UTC
It passes in the f17/rawhide trees where I've got it installed.  I didn't bother backporting to the older f16 based tree.
Comment 5 Alexander Monakov 2013-05-27 09:26:11 UTC
This was independently discovered, filed and fixed as an LD_AUDIT bug 14831.

*** This bug has been marked as a duplicate of bug 14831 ***