From a89d508130a7c34539e8754b729f68c7658c9a19 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Tue, 22 Sep 2020 01:22:42 +0100 Subject: [PATCH] Handle libraries with more than one .shstrtab section --- src/patchelf.cc | 12 +++++++++--- tests/Makefile.am | 10 +++++++--- tests/too-many-strtab.c | 3 +++ tests/too-many-strtab.sh | 21 +++++++++++++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 tests/too-many-strtab.c create mode 100755 tests/too-many-strtab.sh diff --git a/src/patchelf.cc b/src/patchelf.cc index 0af9f0a5..80ada220 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -495,7 +495,7 @@ void ElfFile::sortShdrs() info[getSectionName(shdrs[i])] = getSectionName(shdrs[rdi(shdrs[i].sh_info)]); /* Idem for the index of the .shstrtab section in the ELF header. */ - SectionName shstrtabName = getSectionName(shdrs[rdi(hdr->e_shstrndx)]); + Elf_Shdr shstrtab = shdrs[rdi(hdr->e_shstrndx)]; /* Sort the sections by offset. */ CompShdr comp; @@ -515,8 +515,14 @@ void ElfFile::sortShdrs() wri(shdrs[i].sh_info, findSection3(info[getSectionName(shdrs[i])])); - /* And the .shstrtab index. */ - wri(hdr->e_shstrndx, findSection3(shstrtabName)); + /* And the .shstrtab index. Note: the match here is done by checking the offset as searching + * by name can yield incorrect results in case there are multiple sections with the same + * name as the one initially pointed by hdr->e_shstrndx */ + for (unsigned int i = 1; i < rdi(hdr->e_shnum); ++i) { + if (shdrs[i].sh_offset == shstrtab.sh_offset) { + wri(hdr->e_shstrndx, i); + } + } } diff --git a/tests/Makefile.am b/tests/Makefile.am index dbb7580e..47947a1b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ LIBS = -check_PROGRAMS = simple main main-scoped big-dynstr no-rpath +check_PROGRAMS = simple main too-many-strtab main-scoped big-dynstr no-rpath no_rpath_arch_TESTS = \ no-rpath-amd64.sh \ @@ -25,7 +25,8 @@ src_TESTS = \ force-rpath.sh \ plain-needed.sh \ output-flag.sh \ - build-id.sh + build-id.sh \ + too-many-strtab.sh build_TESTS = \ $(no_rpath_arch_TESTS) @@ -77,7 +78,7 @@ big_dynstr_LDFLAGS = $(LDFLAGS_local) # - without libtool, only archives (static libraries) can be built by automake # - with libtool, it is difficult to control options # - with libtool, it is not possible to compile convenience *dynamic* libraries :-( -check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so libbuildid.so +check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so libbuildid.so libtoomanystrtab.so libbuildid_so_SOURCES = simple.c libbuildid_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-build-id @@ -101,6 +102,9 @@ libbar_scoped_so_LDFLAGS = $(LDFLAGS_sharedlib) libsimple_so_SOURCES = simple.c libsimple_so_LDFLAGS = $(LDFLAGS_sharedlib) +libtoomanystrtab_so_SOURCES = too-many-strtab.c +libtoomanystrtab_so_LDFLAGS = $(LDFLAGS_sharedlib) + no_rpath_SOURCES = no-rpath.c # no -fpic for no-rpath.o no_rpath_CFLAGS = diff --git a/tests/too-many-strtab.c b/tests/too-many-strtab.c new file mode 100644 index 00000000..0f513168 --- /dev/null +++ b/tests/too-many-strtab.c @@ -0,0 +1,3 @@ +const int __attribute__((section (".shstrtab"))) lel = 42; + +int main(){return 0;} diff --git a/tests/too-many-strtab.sh b/tests/too-many-strtab.sh new file mode 100755 index 00000000..3ef158f7 --- /dev/null +++ b/tests/too-many-strtab.sh @@ -0,0 +1,21 @@ +#! /bin/sh -e +SCRATCH=scratch/$(basename $0 .sh) + +rm -rf ${SCRATCH} +mkdir -p ${SCRATCH} + +cp libtoomanystrtab.so ${SCRATCH}/ + +# Set a RUNPATH on the library +../src/patchelf --set-rpath '$ORIGIN' ${SCRATCH}/libtoomanystrtab.so + +# Check that patchelf is able to patch it again without crashing. Previously, +# it will wrongly identify the lib as a static object because there was no +# .dynamic section +exitCode=0 +(../src/patchelf --set-rpath '$ORIGIN' ${SCRATCH}/libtoomanystrtab.so) || exitCode=$? +if test "$exitCode" != 0; then + echo "bad exit code!" + exit 1 +fi +