summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBreno Rodrigues Guimaraes <brenorg@gmail.com>2023-03-17 18:15:46 -0300
committerBreno Rodrigues Guimaraes <brenorg@gmail.com>2023-03-17 19:06:57 -0300
commit8b32fae32d8bfc0770bb4948254db50b6ebbc39e (patch)
tree422a54f2e936dd3bb9ef9985751e5c846da56a7f
parent75e4daaf29f10d2b31be4991507bfa0673b4e9e4 (diff)
downloadpatchelf-8b32fae32d8bfc0770bb4948254db50b6ebbc39e.tar.gz
Check for other references to the RPATH string
-rw-r--r--src/patchelf.cc29
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);