Skip to content

Commit

Permalink
modifyRPath: when possible, avoid growing the dynamic section
Browse files Browse the repository at this point in the history
Growing the section can require changing its position, which results in crashes
if the code relies on a symbol within it (e.g. _DYNAMIC). Instead, we can
usually find an entry that isn't actually required and replace it.
  • Loading branch information
Rodger Combs authored and rcombs committed Jun 16, 2020
1 parent c3ffe62 commit 5daa357
Showing 1 changed file with 12 additions and 2 deletions.
14 changes: 12 additions & 2 deletions src/patchelf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
string. */
std::vector<std::string> neededLibs;
Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
Elf_Dyn * dynRPath = 0, * dynRunPath = 0;
Elf_Dyn * dynRPath = 0, * dynRunPath = 0, * dynReplaceable = 0;
char * rpath = 0;
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
if (rdi(dyn->d_tag) == DT_RPATH) {
Expand All @@ -1157,6 +1157,12 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
}
else if (rdi(dyn->d_tag) == DT_NEEDED)
neededLibs.push_back(std::string(strTab + rdi(dyn->d_un.d_val)));
/* Try to replace an IGNORE rather than growing and moving the section, if possible */
else if (rdi(dyn->d_tag) == DT_IGNORE)
dynReplaceable = dyn;
/* If we don't find an IGNORE, RELCOUNT/RELACOUNT are redundant and optional, so we can replace those */
else if (!dynReplaceable && (rdi(dyn->d_tag) == DT_RELCOUNT || rdi(dyn->d_tag) == DT_RELACOUNT))
dynReplaceable = dyn;
}

if (op == rpPrint) {
Expand Down Expand Up @@ -1283,7 +1289,11 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
if (dynRunPath) dynRunPath->d_un.d_val = shdrDynStr.sh_size;
if (dynRPath) dynRPath->d_un.d_val = shdrDynStr.sh_size;
}

/* Convert an unused or redundant entry to a DT_RPATH or DT_RUNPATH */
else if (dynReplaceable) {
dynReplaceable->d_un.d_val = shdrDynStr.sh_size;
dynReplaceable->d_tag = forceRPath ? DT_RPATH : DT_RUNPATH;
}
else {
/* There is no DT_RUNPATH entry in the .dynamic section, so we
have to grow the .dynamic section. */
Expand Down

0 comments on commit 5daa357

Please sign in to comment.