[Bug libelf/23528] New: When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp -w, AddressSanitizer chatch a double-free crashes.

2018-08-15 Thread wcventure at 126 dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=23528

Bug ID: 23528
   Summary: When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp
-w, AddressSanitizer chatch a double-free crashes.
   Product: elfutils
   Version: unspecified
Status: UNCONFIRMED
  Severity: normal
  Priority: P2
 Component: libelf
  Assignee: unassigned at sourceware dot org
  Reporter: wcventure at 126 dot com
CC: elfutils-devel at sourceware dot org
  Target Milestone: ---

Created attachment 11185
  --> https://sourceware.org/bugzilla/attachment.cgi?id=11185&action=edit
When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp -w, AddressSanitizer
chatch a double-free crashes.

When executing ./eu-nm @@ or ./eu-readelf -aAdehIlnrsSVcp -w @@,
AddressSanitizer chatch a double-free crashes.

The AddressSanitizer's output shows as follow:
==30316==ERROR: AddressSanitizer: attempting double-free on 0x6040de50 in
thread T0:
#0 0x7e5282ca in __interceptor_free
(/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
#1 0x7de26c83 in elf_end /mnt/d/Project/elfutils/libelf/elf_end.c:171
#2 0x7e1b23f6 in free_file
/mnt/d/Project/elfutils/libdwfl/dwfl_module.c:57
#3 0x7e1b23f6 in __libdwfl_module_free
/mnt/d/Project/elfutils/libdwfl/dwfl_module.c:113
#4 0x7e1b06bc in dwfl_end /mnt/d/Project/elfutils/libdwfl/dwfl_end.c:54
#5 0x409883 in show_symbols /mnt/d/Project/elfutils/src/nm.c:1494
#6 0x40cf4c in handle_elf /mnt/d/Project/elfutils/src/nm.c:1578
#7 0x4035dc in process_file /mnt/d/Project/elfutils/src/nm.c:374
#8 0x4035dc in main /mnt/d/Project/elfutils/src/nm.c:249
#9 0x7d4c082f in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#10 0x4043c8 in _start (/mnt/d/Project/elfutils/build/bin/eu-nm+0x4043c8)

0x6040de50 is located 0 bytes inside of 36-byte region
[0x6040de50,0x6040de74)
freed by thread T0 here:
#0 0x7e5282ca in __interceptor_free
(/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
#1 0x7dea3dcf in __libelf_reset_rawdata
/mnt/d/Project/elfutils/libelf/elf_compress.c:325

previously allocated by thread T0 here:
#0 0x7e528602 in malloc
(/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7dea31dd in __libelf_decompress
/mnt/d/Project/elfutils/libelf/elf_compress.c:223
#2 0x7deaa490  (/mnt/d/Project/elfutils/build/lib/libelf.so.1+0x9a490)

SUMMARY: AddressSanitizer: double-free ??:0 __interceptor_free
==30316==ABORTING
[Inferior 1 (process 30316) exited with code 01]

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[Bug libelf/23528] When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp -w, AddressSanitizer catch a double-free crashe.

2018-08-15 Thread wcventure at 126 dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=23528

wcventure  changed:

   What|Removed |Added

Summary|When executing ./eu-nm or   |When executing ./eu-nm or
   |./eu-readelf|./eu-readelf
   |-aAdehIlnrsSVcp -w, |-aAdehIlnrsSVcp -w,
   |AddressSanitizer chatch a   |AddressSanitizer catch a
   |double-free crashes.|double-free crashe.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[Bug libelf/23528] When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp -w, AddressSanitizer catch a double-free crash.

2018-08-15 Thread wcventure at 126 dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=23528

wcventure  changed:

   What|Removed |Added

Summary|When executing ./eu-nm or   |When executing ./eu-nm or
   |./eu-readelf|./eu-readelf
   |-aAdehIlnrsSVcp -w, |-aAdehIlnrsSVcp -w,
   |AddressSanitizer catch a|AddressSanitizer catch a
   |double-free crashe. |double-free crash.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[Bug backends/23529] New: heap-buffer-overflow in eu-readelf

2018-08-15 Thread wcventure at 126 dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=23529

Bug ID: 23529
   Summary: heap-buffer-overflow in eu-readelf
   Product: elfutils
   Version: unspecified
Status: UNCONFIRMED
  Severity: normal
  Priority: P2
 Component: backends
  Assignee: unassigned at sourceware dot org
  Reporter: wcventure at 126 dot com
CC: elfutils-devel at sourceware dot org
  Target Milestone: ---

Created attachment 11186
  --> https://sourceware.org/bugzilla/attachment.cgi?id=11186&action=edit
crash-seed-buffer-over-flow

when executing "./eu-readelf -aAdehIlnrsSVcp -w @@", AddressSanitizer catch a
heap-buffer-overflow carsh.

==29317==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x6060c536 at pc 0x7f5bdaf2bfb0 bp 0x7669ef70 sp 0x7669ef60
READ of size 1 at 0x6060c536 thread T0
#0 0x7f5bdaf2bfaf in __libdw_get_uleb128_unchecked
/mnt/d/Project/elfutils/libdw/memory-access.h:97
#1 0x7f5bdaf2bfaf in dwarf_getabbrevattr_data
/mnt/d/Project/elfutils/libdw/dwarf_getabbrevattr.c:60
#2 0x42f8c2 in print_debug_abbrev_section
/mnt/d/Project/elfutils/src/readelf.c:5045
#3 0x45313f in print_debug /mnt/d/Project/elfutils/src/readelf.c:11143
#4 0x45b07b in process_elf_file /mnt/d/Project/elfutils/src/readelf.c:996
#5 0x462344 in process_dwflmod /mnt/d/Project/elfutils/src/readelf.c:760
#6 0x7f5bdafcc410 in dwfl_getmodules
/mnt/d/Project/elfutils/libdwfl/dwfl_getmodules.c:86
#7 0x40f013 in process_file /mnt/d/Project/elfutils/src/readelf.c:868
#8 0x405614 in main /mnt/d/Project/elfutils/src/readelf.c:350
#9 0x7f5bda65082f in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#10 0x406118 in _start
(/mnt/d/Project/elfutils/build/bin/eu-readelf+0x406118)

0x6060c536 is located 0 bytes to the right of 54-byte region
[0x6060c500,0x6060c536)
allocated by thread T0 here:
#0 0x7f5bdb328602 in malloc
(/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7f5bdac62680 in convert_data
/mnt/d/Project/elfutils/libelf/elf_getdata.c:164
#2 0x7f5bdac62680 in __libelf_set_data_list_rdlock
/mnt/d/Project/elfutils/libelf/elf_getdata.c:431

SUMMARY: AddressSanitizer: heap-buffer-overflow
/mnt/d/Project/elfutils/libdw/memory-access.h:97 __libdw_get_uleb128_unchecked
Shadow bytes around the buggy address:
  0x0c0c7fff9850: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa
  0x0c0c7fff9860: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
  0x0c0c7fff9870: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
  0x0c0c7fff9880: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa
  0x0c0c7fff9890: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
=>0x0c0c7fff98a0: 00 00 00 00 00 00[06]fa fa fa fa fa fd fd fd fd
  0x0c0c7fff98b0: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa
  0x0c0c7fff98c0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
  0x0c0c7fff98d0: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
  0x0c0c7fff98e0: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa
  0x0c0c7fff98f0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:   00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:   fa
  Heap right redzone:  fb
  Freed heap region:   fd
  Stack left redzone:  f1
  Stack mid redzone:   f2
  Stack right redzone: f3
  Stack partial redzone:   f4
  Stack after return:  f5
  Stack use after scope:   f8
  Global redzone:  f9
  Global init order:   f6
  Poisoned by user:f7
  Container overflow:  fc
  Array cookie:ac
  Intra object redzone:bb
  ASan internal:   fe
==29317==ABORTING

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[Bug libelf/23528] When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp -w, AddressSanitizer catch a double-free crash.

2018-08-15 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=23528

--- Comment #1 from Mark Wielaard  ---
Replicated under valgrind:

$ valgrind -q eu-readelf -S Double-free-libelf

==13892== Invalid free() / delete / delete[] / realloc()
==13892==at 0x48369EB: free (vg_replace_malloc.c:530)
==13892==by 0x4899094: elf_end (elf_end.c:171)
==13892==by 0x4868619: free_file (dwfl_module.c:57)
==13892==by 0x4868787: __libdwfl_module_free (dwfl_module.c:113)
==13892==by 0x4868370: dwfl_end (dwfl_end.c:54)
==13892==by 0x114617: process_file (readelf.c:873)
==13892==by 0x111C13: main (readelf.c:350)
==13892==  Address 0x51138b0 is 0 bytes inside a block of size 36 free'd
==13892==at 0x48369EB: free (vg_replace_malloc.c:530)
==13892==by 0x48A5C46: __libelf_reset_rawdata (elf_compress.c:325)
==13892==by 0x48A5D80: elf_compress (elf_compress.c:514)
==13892==by 0x4869F00: relocate_section (relocate.c:507)
==13892==by 0x486A567: __libdwfl_relocate (relocate.c:752)
==13892==by 0x486EB5B: dwfl_module_getelf (dwfl_module_getelf.c:52)
==13892==by 0x11E764: process_elf_file (readelf.c:901)
==13892==by 0x11E764: process_dwflmod (readelf.c:760)
==13892==by 0x486C450: dwfl_getmodules (dwfl_getmodules.c:86)
==13892==by 0x1143BF: process_file (readelf.c:868)
==13892==by 0x111C13: main (readelf.c:350)
==13892==  Block was alloc'd at
==13892==at 0x48357BF: malloc (vg_replace_malloc.c:299)
==13892==by 0x48A59E7: __libelf_decompress (elf_compress.c:223)
==13892==by 0x48A60D4: elf_compress_gnu (elf_compress_gnu.c:178)
==13892==by 0x4869F68: relocate_section (relocate.c:504)
==13892==by 0x486A567: __libdwfl_relocate (relocate.c:752)
==13892==by 0x486EB5B: dwfl_module_getelf (dwfl_module_getelf.c:52)
==13892==by 0x11E764: process_elf_file (readelf.c:901)
==13892==by 0x11E764: process_dwflmod (readelf.c:760)
==13892==by 0x486C450: dwfl_getmodules (dwfl_getmodules.c:86)
==13892==by 0x1143BF: process_file (readelf.c:868)
==13892==by 0x111C13: main (readelf.c:350)

The issue is this section:

[10] .zdebug_abbrev   PROGBITS  00011d 2b  0 NGTC   0   0 
1

Note how it claims to be both gnu style compressed (starts with .zdebug) and
gabi compressed (has SHF_COMPRESSED flag C).

Then the code in relocate.c tries to decompress the section data twice:

  if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
elf_compress_gnu (tscn, 0, 0);

  if ((tshdr->sh_flags & SHF_COMPRESSED) != 0)
if (elf_compress (tscn, 0, 0) < 0)
  return DWFL_E_LIBELF;

So it tries to decompress twice. The second call sees that the data is already
decompressed and assumes it was done implicitly by some call to elf_strptr, and
so just uses the decompressed data to setup the decompressed section data
again, throwing away the buffer that elf_compress_gnu has already setup.
elf_end then tries to free this data buffer again.

The most direct fix is to just make relocate.c not decompress twice in
different ways:

diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
index 9afcdebe..81750cd3 100644
--- a/libdwfl/relocate.c
+++ b/libdwfl/relocate.c
@@ -238,8 +238,7 @@ resolve_symbol (Dwfl_Module *referer, struct
reloc_symtab_cache *symtab,
  /* If the section is already decompressed, that isn't an error.  */
  if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
elf_compress_gnu (scn, 0, 0);
-
- if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ else if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
if (elf_compress (scn, 0, 0) < 0)
  return DWFL_E_LIBELF;

@@ -502,8 +501,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const
GElf_Ehdr *ehdr,

   if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
 elf_compress_gnu (tscn, 0, 0);
-
-  if ((tshdr->sh_flags & SHF_COMPRESSED) != 0)
+  else if ((tshdr->sh_flags & SHF_COMPRESSED) != 0)
 if (elf_compress (tscn, 0, 0) < 0)
   return DWFL_E_LIBELF;

@@ -523,8 +521,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const
GElf_Ehdr *ehdr,

   if (strncmp (sname, ".zdebug", strlen ("zdebug")) == 0)
 elf_compress_gnu (scn, 0, 0);
-
-  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+  else if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
 if (elf_compress (scn, 0, 0) < 0)
   return DWFL_E_LIBELF;


But we can probably fix it in elf_compress[_gnu] by better checks or just by
refusing to elf_compress_gnu if the section already has the SHF_COMPRESSED flag
set.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[Bug libelf/23528] When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp -w, AddressSanitizer catch a double-free crash.

2018-08-15 Thread fche at redhat dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=23528

Frank Ch. Eigler  changed:

   What|Removed |Added

 CC||fche at redhat dot com

--- Comment #2 from Frank Ch. Eigler  ---
FWIW, is there some technical reason why an .zdebug section couldn't possibly
ALSO be SHT_COMPRESSED ?  i.e., compressed twice for some reason by the
generator?

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[Bug backends/23529] heap-buffer-overflow in eu-readelf

2018-08-15 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=23529

Mark Wielaard  changed:

   What|Removed |Added

 CC||mark at klomp dot org

--- Comment #1 from Mark Wielaard  ---
Replicated with valgrind:

valgrind -q eu-readelf --debug-dump=abbrev Buffer-over-readelf

==21205== Invalid read of size 1
==21205==at 0x4855B45: __libdw_get_uleb128_unchecked (memory-access.h:97)
==21205==by 0x4855B45: dwarf_getabbrevattr_data (dwarf_getabbrevattr.c:60)
==21205==by 0x116573: print_debug_abbrev_section (readelf.c:5045)
==21205==by 0x11E090: print_debug (readelf.c:11143)
==21205==by 0x11FEA9: process_elf_file (readelf.c:996)
==21205==by 0x11FEA9: process_dwflmod (readelf.c:760)
==21205==by 0x486C460: dwfl_getmodules (dwfl_getmodules.c:86)
==21205==by 0x1143BF: process_file (readelf.c:868)
==21205==by 0x111C13: main (readelf.c:350)
==21205==  Address 0x5115416 is 0 bytes after a block of size 54 alloc'd
==21205==at 0x48357BF: malloc (vg_replace_malloc.c:299)
==21205==by 0x489E287: convert_data (elf_getdata.c:164)
==21205==by 0x489E287: __libelf_set_data_list_rdlock (elf_getdata.c:431)
==21205==by 0x489E387: __elf_getdata_rdlock (elf_getdata.c:538)
==21205==by 0x484DF80: check_section (dwarf_begin_elf.c:167)
==21205==by 0x484E4E2: global_read (dwarf_begin_elf.c:310)
==21205==by 0x484E4E2: dwarf_begin_elf (dwarf_begin_elf.c:434)
==21205==by 0x486E767: load_dw (dwfl_module_getdwarf.c:1340)
==21205==by 0x486E98B: find_dw (dwfl_module_getdwarf.c:1390)
==21205==by 0x486E98B: dwfl_module_getdwarf (dwfl_module_getdwarf.c:1445)
==21205==by 0x11DB1A: print_debug (readelf.c:10874)
==21205==by 0x11FEA9: process_elf_file (readelf.c:996)
==21205==by 0x11FEA9: process_dwflmod (readelf.c:760)
==21205==by 0x486C460: dwfl_getmodules (dwfl_getmodules.c:86)
==21205==by 0x1143BF: process_file (readelf.c:868)
==21205==by 0x111C13: main (readelf.c:350)

The issue is that __libdw_getabbrev (used by dwarf_getabbrev, dwarf_offabbrev)
uses a different "end of attributes" condition than dwarf_getabbrevattr[_data]:

  while (attrname != 0 && attrform != 0);

vs

  /* If both values are zero the index is out of range.  */
  if (name == 0 && form == 0)

Since the spec says: "The series of attribute specifications ends with an entry
containing 0 for the name and 0 for the form." the second form is correct. And
the check in __libdw_getabbrev should be:

while (attrname != 0 || attrform != 0);

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[Bug libelf/23528] When executing ./eu-nm or ./eu-readelf -aAdehIlnrsSVcp -w, AddressSanitizer catch a double-free crash.

2018-08-15 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=23528

Mark Wielaard  changed:

   What|Removed |Added

 CC||mark at klomp dot org

--- Comment #3 from Mark Wielaard  ---
(In reply to Frank Ch. Eigler from comment #2)
> FWIW, is there some technical reason why an .zdebug section couldn't
> possibly ALSO be SHT_COMPRESSED ?  i.e., compressed twice for some reason by
> the generator?

In theory you could gabi compress a section that is GNU compressed. But in
practice eu-elfcompress won't let you do that (it will first decompress the
.zdebug_xxx section, rename it to .debug_xxx and then gabi compress it). It
would also be somewhat pointless since they use the same zlib compression
scheme. So unless you use ELF_CHF_FORCE it wouldn't actually work since the
result would likely be bigger.

The other way around however (GNU compress an already gabi compressed section)
would be problematic. There is no good way to know whether the data is
corrupted or already (de)compressed since the GNU compression has no meta-data
(like Elf[32|64]_Chdr or a section flag) associated only the implicit section
naming, but from just the name you cannot know whether or not the section data
has already be (de)compressed.

So I think the correct fix is as follows:

diff --git a/libelf/elf_compress_gnu.c b/libelf/elf_compress_gnu.c
index c35dc395..dfa7c571 100644
--- a/libelf/elf_compress_gnu.c
+++ b/libelf/elf_compress_gnu.c
@@ -80,7 +80,9 @@ elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int
flags)
   sh_addralign = shdr->sh_addralign;
 }

-  if ((sh_flags & SHF_ALLOC) != 0)
+  /* Allocated sections, or sections that are already compressed
+ cannot (also) be GNU compressed.  */
+  if ((sh_flags & SHF_ALLOC) != 0 || (sh_flags & SHF_COMPRESSED))
 {
   __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
   return -1;

That way you could still (theoretically) gabi compress a gnu compressed
section. But you wouldn't be able to gnu (de)compress a section that is already
gabi compressed (unless you first [gabi] decompress it).

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[PATCH] libelf/elf_end.c: check data_list.data.d.d_buf before free it

2018-08-15 Thread Robert Yang
The one which actually saves the data is data_list.data.d.d_buf, so check it
before free rawdata_base.

This can fix a segmentation fault when prelink libqb_1.0.3:
prelink: /usr/lib/libqb.so.0.18.2: Symbol section index outside of section 
numbers

The segmentation fault happens when prelink call elf_end().

Signed-off-by: Robert Yang 
---
 libelf/elf_end.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libelf/elf_end.c b/libelf/elf_end.c
index 160f0b8..5388e80 100644
--- a/libelf/elf_end.c
+++ b/libelf/elf_end.c
@@ -165,9 +165,10 @@ elf_end (Elf *elf)
 
/* The section data is allocated if we couldn't mmap
   the file.  Or if we had to decompress.  */
-   if (elf->map_address == NULL
+   if ((elf->map_address == NULL
|| scn->rawdata_base == scn->zdata_base
|| (scn->flags & ELF_F_MALLOCED) != 0)
+   && (scn->data_list.data.d.d_buf != NULL))
  free (scn->rawdata_base);
 
/* Free the list of data buffers for the section.
-- 
2.7.4