diff --git a/.gitignore b/.gitignore index 921b9f85..c3f60a5d 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ Makefile .direnv/ .vscode/ .idea/ +result diff --git a/src/patchelf.cc b/src/patchelf.cc index 668a5e49..e824cbf9 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -1150,6 +1150,7 @@ void ElfFile::modifySoname(sonameMode op, const std::string & } changed = true; + this->rewriteSections(); } template @@ -1158,6 +1159,7 @@ void ElfFile::setInterpreter(const std::string & newInterpret std::string & section = replaceSection(".interp", newInterpreter.size() + 1); setSubstr(section, 0, newInterpreter + '\0'); changed = true; + this->rewriteSections(); } @@ -1234,6 +1236,7 @@ void ElfFile::removeRPath(Elf_Shdr & shdrDynamic) { } } memset(last, 0, sizeof(Elf_Dyn) * (dyn - last)); + this->rewriteSections(); } template @@ -1380,6 +1383,7 @@ void ElfFile::modifyRPath(RPathOp op, newDyn.d_un.d_val = shdrDynStr.sh_size; setSubstr(newDynamic, 0, std::string((char *) &newDyn, sizeof(Elf_Dyn))); } + this->rewriteSections(); } @@ -1409,6 +1413,8 @@ void ElfFile::removeNeeded(const std::set & libs } memset(last, 0, sizeof(Elf_Dyn) * (dyn - last)); + + this->rewriteSections(); } template @@ -1532,6 +1538,8 @@ void ElfFile::replaceNeeded(const std::maprewriteSections(); } template @@ -1582,6 +1590,8 @@ void ElfFile::addNeeded(const std::set & libs) } changed = true; + + this->rewriteSections(); } template @@ -1638,6 +1648,7 @@ void ElfFile::noDefaultLib() setSubstr(newDynamic, 0, std::string((char *) &newDyn, sizeof(Elf_Dyn))); } + this->rewriteSections(); changed = true; } @@ -1667,6 +1678,7 @@ void ElfFile::clearSymbolVersions(const std::set } } changed = true; + this->rewriteSections(); } static bool printInterpreter = false; @@ -1726,7 +1738,6 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con elfFile.noDefaultLib(); if (elfFile.isChanged()){ - elfFile.rewriteSections(); writeFile(fileName, elfFile.fileContents); } else if (alwaysWrite) { debug("not modified, but alwaysWrite=true\n"); diff --git a/tests/Makefile.am b/tests/Makefile.am index 404f159d..b280e62d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -39,7 +39,8 @@ src_TESTS = \ basic-flags.sh \ set-empty-rpath.sh \ phdr-corruption.sh \ - replace-needed.sh + replace-needed.sh \ + replace-add-needed.sh build_TESTS = \ $(no_rpath_arch_TESTS) diff --git a/tests/replace-add-needed.sh b/tests/replace-add-needed.sh new file mode 100755 index 00000000..ab0d3532 --- /dev/null +++ b/tests/replace-add-needed.sh @@ -0,0 +1,38 @@ +#! /bin/sh -e +SCRATCH=scratch/$(basename $0 .sh) +PATCHELF=$(readlink -f "../src/patchelf") + +rm -rf ${SCRATCH} +mkdir -p ${SCRATCH} + +cp simple ${SCRATCH}/ +cp libfoo.so ${SCRATCH}/ +cp libbar.so ${SCRATCH}/ + +cd ${SCRATCH} + +libcldd=$(ldd ./simple | awk '/ => / { print $3 }' | grep -E "(libc.so|ld-musl)") + +# We have to set the soname on these libraries +${PATCHELF} --set-soname libbar.so ./libbar.so + +# Add a libbar.so so we can rewrite it later +${PATCHELF} --add-needed libbar.so ./simple + +# Make the NEEDED in libfoo the same as simple +# This is a current "bug" in musl +# https://www.openwall.com/lists/musl/2021/12/21/1 +${PATCHELF} --replace-needed libbar.so $(readlink -f ./libbar.so) ./libfoo.so + +${PATCHELF} --replace-needed libc.so.6 ${libcldd} \ + --replace-needed libbar.so $(readlink -f ./libbar.so) \ + --add-needed $(readlink -f ./libfoo.so) \ + ./simple + +exitCode=0 +./simple || exitCode=$? + +if test "$exitCode" != 0; then + ldd ./simple + exit 1 +fi \ No newline at end of file