From 8b32fae32d8bfc0770bb4948254db50b6ebbc39e Mon Sep 17 00:00:00 2001 From: Breno Rodrigues Guimaraes Date: Fri, 17 Mar 2023 18:15:46 -0300 Subject: Check for other references to the RPATH string --- src/patchelf.cc | 29 ++++++++++++++++++++++------- 1 file 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::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::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::modifyExecstack(ExecstackMode op) template template -void ElfFile::forAllStringReferences(Elf_Shdr& strTabHdr, StrIdxCallback&& fn) +void ElfFile::forAllStringReferences(const Elf_Shdr& strTabHdr, StrIdxCallback&& fn) { for (auto& sym : tryGetSectionSpan(".dynsym")) fn(sym.st_name); -- cgit v1.2.1