diff options
author | Breno Rodrigues Guimaraes <brenorg@gmail.com> | 2023-03-17 18:15:46 -0300 |
---|---|---|
committer | Breno Rodrigues Guimaraes <brenorg@gmail.com> | 2023-03-17 19:06:57 -0300 |
commit | 8b32fae32d8bfc0770bb4948254db50b6ebbc39e (patch) | |
tree | 422a54f2e936dd3bb9ef9985751e5c846da56a7f | |
parent | 75e4daaf29f10d2b31be4991507bfa0673b4e9e4 (diff) | |
download | patchelf-8b32fae32d8bfc0770bb4948254db50b6ebbc39e.tar.gz |
Check for other references to the RPATH string
-rw-r--r-- | src/patchelf.cc | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc index f2f9043..ee00918 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -1538,7 +1538,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, /* !!! We assume that the virtual address in the DT_STRTAB entry of the dynamic section corresponds to the .dynstr section. */ - auto shdrDynStr = findSectionHeader(".dynstr"); + auto& shdrDynStr = findSectionHeader(".dynstr"); char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset); @@ -1621,24 +1621,39 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, } changed = true; - /* Zero out the previous rpath to prevent retained dependencies in - Nix. */ + bool rpathStrShared = false; size_t rpathSize = 0; if (rpath) { - rpathSize = strlen(rpath); + std::string_view rpathView {rpath}; + rpathSize = rpathView.size(); + + size_t rpathStrReferences = 0; + forAllStringReferences(shdrDynStr, [&] (auto refIdx) { + if (rpathView.end() == std::string_view(strTab + rdi(refIdx)).end()) + rpathStrReferences++; + }); + assert(rpathStrReferences >= 1); + debug("Number of rpath references: %lu\n", rpathStrReferences); + rpathStrShared = rpathStrReferences > 1; + } + + /* Zero out the previous rpath to prevent retained dependencies in + Nix. */ + if (rpath && !rpathStrShared) { + debug("Tainting old rpath with Xs\n"); memset(rpath, 'X', rpathSize); } debug("new rpath is '%s'\n", newRPath.c_str()); - if (newRPath.size() <= rpathSize) { + if (!rpathStrShared && newRPath.size() <= rpathSize) { if (rpath) memcpy(rpath, newRPath.c_str(), newRPath.size() + 1); return; } /* Grow the .dynstr section to make room for the new RPATH. */ - debug("rpath is too long, resizing...\n"); + debug("rpath is too long or shared, resizing...\n"); std::string & newDynStr = replaceSection(".dynstr", rdi(shdrDynStr.sh_size) + newRPath.size() + 1); @@ -2295,7 +2310,7 @@ void ElfFile<ElfFileParamNames>::modifyExecstack(ExecstackMode op) template<ElfFileParams> template<class StrIdxCallback> -void ElfFile<ElfFileParamNames>::forAllStringReferences(Elf_Shdr& strTabHdr, StrIdxCallback&& fn) +void ElfFile<ElfFileParamNames>::forAllStringReferences(const Elf_Shdr& strTabHdr, StrIdxCallback&& fn) { for (auto& sym : tryGetSectionSpan<Elf_Sym>(".dynsym")) fn(sym.st_name); |