NixOS / patchelf

A small utility to modify the dynamic linker and RPATH of ELF executables
GNU General Public License v3.0
3.54k stars 486 forks source link

`make check` fails when configured `--with-asan` #273

Open tdp2110 opened 3 years ago

tdp2110 commented 3 years ago

Describe the bug

Tests fail when patchelf is built with AddressSanitizer instrumentation.

Steps To Reproduce

Working on Ubuntu 18.04.5 LTS,

./bootstrap.sh
./configure --with-asan
make
make check

We see many failures not present without asan, eg:

PASS: plain-fail.sh
PASS: plain-run.sh
PASS: shrink-rpath.sh
PASS: set-interpreter-short.sh
PASS: set-interpreter-long.sh
PASS: set-rpath.sh
PASS: no-rpath.sh
PASS: big-dynstr.sh
PASS: set-rpath-library.sh
PASS: soname.sh
PASS: shrink-rpath-with-allowed-prefixes.sh
PASS: force-rpath.sh
PASS: plain-needed.sh
PASS: output-flag.sh
PASS: no-rpath-pie-powerpc.sh
PASS: build-id.sh
PASS: invalid-elf.sh
FAIL: no-rpath-amd64.sh
FAIL: no-rpath-armel.sh
FAIL: no-rpath-armhf.sh
FAIL: no-rpath-hurd-i386.sh
FAIL: no-rpath-i386.sh
FAIL: no-rpath-ia64.sh
FAIL: no-rpath-kfreebsd-amd64.sh
FAIL: no-rpath-kfreebsd-i386.sh
PASS: no-rpath-mips.sh
PASS: no-rpath-mipsel.sh
FAIL: no-rpath-powerpc.sh
FAIL: no-rpath-s390.sh
PASS: no-rpath-sh4.sh
PASS: no-rpath-sparc.sh
============================================================================
Testsuite summary for patchelf 0.12
============================================================================
# TOTAL: 31
# PASS:  21
# SKIP:  0
# XFAIL: 0
# FAIL:  10
# XPASS: 0
# ERROR: 0
============================================================================
See tests/test-suite.log
============================================================================

I didn't look at all the logs, but they seem to be memory corruption issues. Eg, tests/no-rpath-amd64.sh.log shows

=================================================================
==19393==ERROR: AddressSanitizer: heap-use-after-free on address 0x614000000190 at pc 0x558b4ac8da24 bp 0x7ffd0f898130 sp 0x7ffd0f898120
READ of size 4 at 0x614000000190 thread T0
    #0 0x558b4ac8da23 in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, unsigned short>::normalizeNoteSegments() /home/tom/projects/patchelf/src/patchelf.cc:991
    #1 0x558b4accdea3 in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, unsigned short>::rewriteSectionsExecutable() /home/tom/projects/patchelf/src/patchelf.cc:931
    #2 0x558b4accec5a in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, unsigned short>::rewriteSections() /home/tom/projects/patchelf/src/patchelf.cc:1048
    #3 0x558b4ac6456f in patchElf2<ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, long unsigned int, long unsigned int, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, short unsigned int> > /home/tom/projects/patchelf/src/patchelf.cc:1770
    #4 0x558b4ac6456f in patchElf /home/tom/projects/patchelf/src/patchelf.cc:1791
    #5 0x558b4ac6456f in mainWrapped(int, char**) /home/tom/projects/patchelf/src/patchelf.cc:1937
    #6 0x558b4ac5c9ad in main /home/tom/projects/patchelf/src/patchelf.cc:1945
    #7 0x7fb13e3b9bf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
    #8 0x558b4ac5d439 in _start (/home/tom/projects/patchelf/src/patchelf+0x7439)

0x614000000190 is located 336 bytes inside of 448-byte region [0x614000000040,0x614000000200)
freed by thread T0 here:
    #0 0x7fb13ee0b2c0 in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe12c0)
    #1 0x558b4ac72efb in __gnu_cxx::new_allocator<Elf64_Phdr>::deallocate(Elf64_Phdr*, unsigned long) /usr/include/c++/7/ext/new_allocator.h:125
    #2 0x558b4ac72efb in std::allocator_traits<std::allocator<Elf64_Phdr> >::deallocate(std::allocator<Elf64_Phdr>&, Elf64_Phdr*, unsigned long) /usr/include/c++/7/bits/alloc_traits.h:462
    #3 0x558b4ac72efb in std::_Vector_base<Elf64_Phdr, std::allocator<Elf64_Phdr> >::_M_deallocate(Elf64_Phdr*, unsigned long) /usr/include/c++/7/bits/stl_vector.h:180
    #4 0x558b4ac72efb in void std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::_M_realloc_insert<Elf64_Phdr const&>(__gnu_cxx::__normal_iterator<Elf64_Phdr*, std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> > >, Elf64_Phdr const&)
/usr/include/c++/7/bits/vector.tcc:448
    #5 0x558b4ac8d665 in std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::push_back(Elf64_Phdr const&) /usr/include/c++/7/bits/stl_vector.h:948
    #6 0x558b4ac8d665 in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, unsigned short>::normalizeNoteSegments() /home/tom/projects/patchelf/src/patchelf.cc:1025
    #7 0x558b4accdea3 in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, unsigned short>::rewriteSectionsExecutable() /home/tom/projects/patchelf/src/patchelf.cc:931
    #8 0x558b4accec5a in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, unsigned short>::rewriteSections() /home/tom/projects/patchelf/src/patchelf.cc:1048
    #9 0x558b4ac6456f in patchElf2<ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, long unsigned int, long unsigned int, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, short unsigned int> > /home/tom/projects/patchelf/src/patchelf.cc:1770
    #10 0x558b4ac6456f in patchElf /home/tom/projects/patchelf/src/patchelf.cc:1791
    #11 0x558b4ac6456f in mainWrapped(int, char**) /home/tom/projects/patchelf/src/patchelf.cc:1937
    #12 0x558b4ac5c9ad in main /home/tom/projects/patchelf/src/patchelf.cc:1945
    #13 0x7fb13e3b9bf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)

previously allocated by thread T0 here:
    #0 0x7fb13ee0a448 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0448)
    #1 0x558b4ac72ce5 in __gnu_cxx::new_allocator<Elf64_Phdr>::allocate(unsigned long, void const*) /usr/include/c++/7/ext/new_allocator.h:111
    #2 0x558b4ac72ce5 in std::allocator_traits<std::allocator<Elf64_Phdr> >::allocate(std::allocator<Elf64_Phdr>&, unsigned long) /usr/include/c++/7/bits/alloc_traits.h:436
    #3 0x558b4ac72ce5 in std::_Vector_base<Elf64_Phdr, std::allocator<Elf64_Phdr> >::_M_allocate(unsigned long) /usr/include/c++/7/bits/stl_vector.h:172
    #4 0x558b4ac72ce5 in void std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::_M_realloc_insert<Elf64_Phdr const&>(__gnu_cxx::__normal_iterator<Elf64_Phdr*, std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> > >, Elf64_Phdr const&)
/usr/include/c++/7/bits/vector.tcc:406
    #5 0x558b4ac74f67 in std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::push_back(Elf64_Phdr const&) /usr/include/c++/7/bits/stl_vector.h:948
    #6 0x558b4ac74f67 in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, unsigned short>::ElfFile(std::shared_ptr<std::vector<unsigned char, std::allocator<unsigned char> > >)
 /home/tom/projects/patchelf/src/patchelf.cc:417
    #7 0x558b4ac63533 in patchElf /home/tom/projects/patchelf/src/patchelf.cc:1791
    #8 0x558b4ac63533 in mainWrapped(int, char**) /home/tom/projects/patchelf/src/patchelf.cc:1937
    #9 0x558b4ac5c9ad in main /home/tom/projects/patchelf/src/patchelf.cc:1945
    #10 0x7fb13e3b9bf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)

Expected behavior

ASAN-instrumented tests should be clean and pass without error.

patchelf --version output

patchelf 0.12

Additional context

I was working on the approach outlined here to rework readFile to not have a fixed capacity. I used a more standard approach of reading a file to a string (without pre-reservation of a std::vector), but tests failed unless I reserved some extra scratch space on the vector. This got me suspicious of possible memory-corruption shenanigans in this source, so I built with address sanitizer (fortunately supported by configure!) and hit all this stuff.

If I get a little time, I may try to address these issues myself.

Thanks for your efforts on this library!

Mic92 commented 3 years ago

I think it would be best if we do build with asan and ubsan by default in non-release builds

Mic92 commented 1 year ago

Can you still reproduce these issues on master? I can't.