This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug dynamic-link/20105] New: bad version variable in elf_dynamic_do_Rel() elf/do-rel.h (2.23) causes coredump in dl-machine.h elf_machine_rela()
- From: "jason.vas.dias at gmail dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Mon, 16 May 2016 16:20:19 +0000
- Subject: [Bug dynamic-link/20105] New: bad version variable in elf_dynamic_do_Rel() elf/do-rel.h (2.23) causes coredump in dl-machine.h elf_machine_rela()
- Auto-submitted: auto-generated
https://sourceware.org/bugzilla/show_bug.cgi?id=20105
Bug ID: 20105
Summary: bad version variable in elf_dynamic_do_Rel()
elf/do-rel.h (2.23) causes coredump in dl-machine.h
elf_machine_rela()
Product: glibc
Version: 2.23
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: dynamic-link
Assignee: unassigned at sourceware dot org
Reporter: jason.vas.dias at gmail dot com
Target Milestone: ---
Having built the latest publicly available git tag of the glibc GIT:
git://sourceware.org/git/glibc.git
( latest tag as of writing (2016-05-18) is 'glibc-2.23' )
on a Linux (LFS 7.9+) x86_64 (4-core 4th. gen Intel i7) machine,
both for -m64 (/usr/lib64) and -m32 (/usr/lib32),
running linux kernel 4.5.0, with binutils-2.26.20160125 ,
I generally experienced no problems for a month or so,
but now I tried to run some freeware (OpenOffice-4.1.2)
and it is having problems dynamically loading its copy
of 'libfwk.so*' with dlopen() - glibc suffers a core dump
during dlopen() because it gets an incorrect address for the
'version' variable in do-rel.h :
elf/do-rel.h line 121:
const ElfW(Half) *const version =
(const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
Now, during the load initiated by the command:
$ LD_LIBRARY_PATH=${OOO_HOME} ${OOO_HOME}/soffice.bin
this core dump occurs:
$ echo 'run
info reg
disass/sr
' > /tmp/gdb.cmds
$ LD_LIBRARY_PATH=${OOO_HOME} gdb \
-x /tmp/gdb.cmds--args \
${OOO_HOME}/soffice.bin -writer
... # ( here is selected output showing core dump info :
[New Thread 0x7fffeba9b700 (LWP 8471)]
[New Thread 0x7fffe6d1c700 (LWP 8472)]
[New Thread 0x7fffe651b700 (LWP 8473)]
Thread 1 "soffice.bin" received signal SIGSEGV, Segmentation fault.
0x00007ffff7de5812 in elf_machine_rela (skip_ifunc=0,
reloc_addr_arg=0x7fffea23a460, version=0x48, sym=0x7fffe9f31a98,
reloc=0x7fffe9f45fb0, map=0x61b660) at ../sysdeps/x86_64/dl-machine.h:301
301 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
...
# important registers:
r8 0x48 72
rip 0x00007ffff7de5812
# Dissassmbly of coredump point :
301 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
0x00007ffff7de5789 <+1113>: 41 0f b6 46 04 movzbl 0x4(%r14),%eax
0x00007ffff7de578e <+1118>: c0 e8 04 shr $0x4,%al
0x00007ffff7de5791 <+1121>: 0f 84 a9 03 00 00 je 0x7ffff7de5b40
<_dl_relocate_object+2064>
0x00007ffff7de5797 <+1127>: 4d 3b b4 24 f8 03 00 00 cmp 0x3f8(%r12),%r14
0x00007ffff7de579f <+1135>: 0f 84 ab 06 00 00 je 0x7ffff7de5e50
<_dl_relocate_object+2848>
0x00007ffff7de57a5 <+1141>: 49 83 fd 07 cmp $0x7,%r13
0x00007ffff7de57a9 <+1145>: 0f 84 b1 03 00 00 je 0x7ffff7de5b60
<_dl_relocate_object+2096>
0x00007ffff7de57af <+1151>: 49 83 fd 10 cmp $0x10,%r13
0x00007ffff7de57b3 <+1155>: 0f 84 a7 03 00 00 je 0x7ffff7de5b60
<_dl_relocate_object+2096>
0x00007ffff7de57b9 <+1161>: 49 8d 45 ef lea -0x11(%r13),%rax
0x00007ffff7de57bd <+1165>: 48 83 f8 01 cmp $0x1,%rax
0x00007ffff7de57c1 <+1169>: 41 0f 96 c1 setbe %r9b
0x00007ffff7de57c5 <+1173>: 49 83 fd 24 cmp $0x24,%r13
0x00007ffff7de57c9 <+1177>: 0f 94 c0 sete %al
0x00007ffff7de57cc <+1180>: 41 09 c1 or %eax,%r9d
0x00007ffff7de57cf <+1183>: 41 0f b6 c1 movzbl %r9b,%eax
0x00007ffff7de57d3 <+1187>: 49 83 fd 05 cmp $0x5,%r13
0x00007ffff7de57d7 <+1191>: 0f 84 92 03 00 00 je 0x7ffff7de5b6f
<_dl_relocate_object+2111>
0x00007ffff7de57dd <+1197>: 45 31 c9 xor %r9d,%r9d
0x00007ffff7de57e0 <+1200>: 49 83 fd 06 cmp $0x6,%r13
0x00007ffff7de57e4 <+1204>: 41 0f 94 c1 sete %r9b
0x00007ffff7de57e8 <+1208>: 41 c1 e1 02 shl $0x2,%r9d
do-rel.h:
137 elf_machine_rel (map, r, &symtab[ELFW(R_SYM)
(r->r_info)],
0x00007ffff7de57ec <+1212>: 81 e2 ff 7f 00 00 and $0x7fff,%edx
../sysdeps/x86_64/dl-machine.h:
301 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
0x00007ffff7de57f2 <+1218>: 41 09 c1 or %eax,%r9d
0x00007ffff7de57f5 <+1221>: 4d 89 b4 24 f8 03 00 00 mov %r14,0x3f8(%r12)
do-rel.h:
137 elf_machine_rel (map, r, &symtab[ELFW(R_SYM)
(r->r_info)],
0x00007ffff7de57fd <+1229>: 48 8d 14 52 lea (%rdx,%rdx,2),%rdx
../sysdeps/x86_64/dl-machine.h:
301 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
0x00007ffff7de5801 <+1233>: 45 89 8c 24 00 04 00 00 mov %r9d,0x400(%r12)
do-rel.h:
137 elf_machine_rel (map, r, &symtab[ELFW(R_SYM)
(r->r_info)],
0x00007ffff7de5809 <+1241>: 4c 8d 04 d6 lea (%rsi,%rdx,8),%r8
../sysdeps/x86_64/dl-machine.h:
301 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
0x00007ffff7de580d <+1245>: 4d 85 c0 test %r8,%r8
0x00007ffff7de5810 <+1248>: 74 0f je 0x7ffff7de5821
<_dl_relocate_object+1265>
=> 0x00007ffff7de5812 <+1250>: 41 8b 40 08 mov 0x8(%r8),%eax
# info scope 0x00007ffff7de5812 showing variable in %r8 (whose address has
# value 0x48) :
Symbol v is multi-location:
Range 0x7ffff7de57fd-0x7ffff7de584e: the constant 0
Range 0x7ffff7de584e-0x7ffff7de5852: a variable in $r8
, length 8.
'v' is the value of the version value parameter set in do-rel.h , as
shown in the pre-processed dl-reloc.c output :
# 283 "../sysdeps/x86_64/dl-machine.h"
*reloc_addr = map->l_addr + reloc->r_addend;
}
else
if (__builtin_expect ((r_type == 38), 0))
*(Elf64_Addr *) reloc_addr = (Elf64_Addr) map->l_addr + reloc->r_addend;
else
if (__builtin_expect ((r_type == 0), 0))
return;
else
{
const Elf64_Sym *const refsym = sym;
struct link_map *sym_map = ((((unsigned char) ((*&sym)->st_info)) >> 4)
!= 0 ? ((__builtin_expect ((*&sym) == l->l_lookup_cache.sym, 0) && ((((r_type)
== 7 || (r_type) == 16 || (r_type) == 17 || (r_type) == 18 || (r_type) == 36) *
1) | (((r_type) == 5) * 2) | (((r_type) == 6) * 4)) ==
l->l_lookup_cache.type_class) ? (++_rtld_global._dl_num_cache_relocations,
(*&sym) = l->l_lookup_cache.ret, l->l_lookup_cache.value) : ({ lookup_t _lr;
int _tc = ((((r_type) == 7 || (r_type) == 16 || (r_type) == 17 || (r_type) ==
18 || (r_type) == 36) * 1) | (((r_type) == 5) * 2) | (((r_type) == 6) * 4));
l->l_lookup_cache.type_class = _tc; l->l_lookup_cache.sym = (*&sym); const
struct r_found_version *v =
# 301 "../sysdeps/x86_64/dl-machine.h" 3 4
# 301 "../sysdeps/x86_64/dl-machine.h"
; if ((version) !=
# 301 "../sysdeps/x86_64/dl-machine.h" 3 4
((void *)0)
# 301 "../sysdeps/x86_64/dl-machine.h"
&& (version)->hash != 0) v = (version);
Now 'version' is the parameter to the elf_machine_rela call made by
do-rel.h:
#ifdef RTLD_BOOTSTRAP
/* The dynamic linker always uses versioning. */
assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
#else
if (map->l_info[VERSYMIDX (DT_VERSYM)])
#endif
{
const ElfW(Half) *const version =
(const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
for (; r < end; ++r)
{
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
{
if (r2 == NULL)
r2 = r;
end2 = r;
continue;
}
#endif
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx],
(void *) (l_addr + r->r_offset), skip_ifunc);
}
So the expression &map->l_versions[ndx] has value 0x48 but is dereferenced
as a pointer by elf_machine_rela() .
Please can we modify the expression above so that is
it something like :
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
is_sane_version_pointer(&map->l_versions[ndx])
? (void *) &map->l_versions[ndx] : ((void*)0UL)
, (void *) (l_addr + r->r_offset), skip_ifunc);
What should 'is_sane_version_pointer(p,map)' test for ?
(p >= (&map)->l_versions[0]) perhaps?
This problem does not occur when running the same freeware binaries in a RHEL7
(glibc 2.17) binary distribution system - I believe glibc-2.23 would
eventually complain about library version mismatches when those same
binaries are loaded, but coredumps before getting to that point .
It would be nice if glibc could help debug the problem rather than
coredump in this case - I'll try implementing the above patch with :
#define is_sane_version_pointer(p,map) \
( ((map)->l_version != (void*)0)
&& ((p) >= &((map)->l_version[0])
)
re-building, and see what happens.
--
You are receiving this mail because:
You are on the CC list for the bug.