Re: bin-x86_64/diet segfaults in findtlsdata()

[email protected] Mon, 6 Aug 2018 15:05:46 +0200 (CEST)
Newsgroups gmane.linux.lib.dietlibc
Message-ID <[email protected]>
> On August 6, 2018 at 2:28 PM [email protected] wrote:
> 
> 
> 
> > On August 6, 2018 at 1:54 PM [email protected] wrote:
> > 
> > 
> > Hi,
> > 
> > I'm getting a new segfault while building the current dietlibc cvs:
> > 
> > ...
> > make: Entering directory '/tmp/dietlibc-cvs'
> > bin-x86_64/diet gcc -D__dietlibc__ -g -O0 -march=native -Wall -fno-stack-protector -std=gnu99 -W -Wall -Wextra -Wchar-subscripts -Wmissing-prototypes -Wmissing-declarations -Wno-switch -Wno-unused -Wredundant-decls -Wshadow -o bin-x86_64/elftrunc contrib/elftrunc.c
> > make: *** [Makefile:346: bin-x86_64/elftrunc] Segmentation fault
> > 
> > 
> > After a bit of gdbugging here is the segfault context:
> > 
> > inside the function findtlsdata(long* auxvec) in lib/stackgap-common.h:
> > 
> > ...
> > static void findtlsdata(long* auxvec) {
> > #if (__WORDSIZE == 64)
> > Elf64_Phdr* x=0;
> > #else
> > Elf32_Phdr* x=0;
> > #endif
> > size_t i,n=0;
> > while (*auxvec) {
> > if (auxvec[0]==3) { /* AT_PHDR */
> > x=(void*)auxvec[1];
> > if (n) break;
> > } else if (auxvec[0]==5) { /* AT_PHNUM */
> > n=auxvec[1];
> > if (x) break;
> > }
> > auxvec+=2;
> > } /* if we don't find the entry, the kernel let us down */
> > if (!x || !n) return; /* a kernel this old does not support thread local storage anyway */
> > for (i=0; i<n; ++i)
> > if (x[i].p_type==PT_TLS) {
> > __tdataptr=(void*)x[i].p_vaddr;
> > __tdatasize=x[i].p_filesz;
> > __tmemsize=x[i].p_memsz;
> > if (__tmemsize&15)
> > __tmemsize=(__tmemsize+15)&~15;
> > break;
> > }
> > /* if there is no PT_TLS section, there is no thread-local data, and
> > * we just leave the __t* variables zero */
> > }
> > ...
> > 
> > it searches the auxvec table for the PHDR address and the PHNUM and it actually finds something:
> > here is a memory dump of the auxvec in gdb:
> > 
> > (gdb) x/40ug auxvec
> > 0x7fffffffe1e8: 33 140737354125312
> > 0x7fffffffe1f8: 16 3219913727
> > 0x7fffffffe208: 6 4096
> > 0x7fffffffe218: 17 100
> > 0x7fffffffe228: 3 4194368
> > 0x7fffffffe238: 4 56
> > 0x7fffffffe248: 5 6
> > 0x7fffffffe258: 7 0
> > 0x7fffffffe268: 8 0
> > 0x7fffffffe278: 9 4198400
> > 0x7fffffffe288: 11 1000
> > 0x7fffffffe298: 12 1000
> > 0x7fffffffe2a8: 13 999
> > 0x7fffffffe2b8: 14 999
> > 0x7fffffffe2c8: 23 0
> > 0x7fffffffe2d8: 25 140737488347945
> > 0x7fffffffe2e8: 26 0
> > 0x7fffffffe2f8: 31 140737488351118
> > 0x7fffffffe308: 15 140737488347961
> > 0x7fffffffe318: 0 0
> > (gdb) x/40xg auxvec
> > 0x7fffffffe1e8: 0x0000000000000021 0x00007ffff7ffd000
> > 0x7fffffffe1f8: 0x0000000000000010 0x00000000bfebfbff
> > 0x7fffffffe208: 0x0000000000000006 0x0000000000001000
> > 0x7fffffffe218: 0x0000000000000011 0x0000000000000064
> > 0x7fffffffe228: 0x0000000000000003 0x0000000000400040
> > 0x7fffffffe238: 0x0000000000000004 0x0000000000000038
> > 0x7fffffffe248: 0x0000000000000005 0x0000000000000006
> > 0x7fffffffe258: 0x0000000000000007 0x0000000000000000
> > 0x7fffffffe268: 0x0000000000000008 0x0000000000000000
> > 0x7fffffffe278: 0x0000000000000009 0x0000000000401000
> > 0x7fffffffe288: 0x000000000000000b 0x00000000000003e8
> > 0x7fffffffe298: 0x000000000000000c 0x00000000000003e8
> > 0x7fffffffe2a8: 0x000000000000000d 0x00000000000003e7
> > 0x7fffffffe2b8: 0x000000000000000e 0x00000000000003e7
> > 0x7fffffffe2c8: 0x0000000000000017 0x0000000000000000
> > 0x7fffffffe2d8: 0x0000000000000019 0x00007fffffffe329
> > 0x7fffffffe2e8: 0x000000000000001a 0x0000000000000000
> > 0x7fffffffe2f8: 0x000000000000001f 0x00007fffffffef8e
> > 0x7fffffffe308: 0x000000000000000f 0x00007fffffffe339
> > 0x7fffffffe318: 0x0000000000000000 0x0000000000000000
> > (gdb)
> > 
> > The pointer 'x' gets the value 0x400040 and the program segfaults as soon as 'x'
> > is dereferenced in:
> > 
> > if (x[i].p_type==PT_TLS) {
> > 
> > with i==0.
> > 
> > Can someone recognize something stange in this ? Is the address 0x400040 'plausible'
> > or is it obviously wrong.
> > 
> > I'm compiling natively with gcc 8.2 on linux 4.17.11.
> > 
> > giorgio
> 
> 
> I suspect this is a bug in recent versions of binutils (2.30 ~ 2.31),
> see:
> 
>   https://sourceware.org/bugzilla/show_bug.cgi?id=23428
> 
> and
> 
>   http://www.openwall.com/lists/musl/2018/07/18/5
> 
> giorgio

Hi,

I've just compiled the same dietlibc sources with the 'ld' linker from the current
binutils git repo, branch 'binutils-2_31-branch' (commit id
29d5746fed0c1e9a77371311e6555b0abd5b56b2), and the segfault disappeared.

giorgio