Skip to content

Commit c04c8ce

Browse files
author
Rodger Combs
committed
modifyRPath: when possible, avoid growing the dynamic section
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.
1 parent 7dc867a commit c04c8ce

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

src/patchelf.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
11501150
string. */
11511151
std::vector<std::string> neededLibs;
11521152
Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
1153-
Elf_Dyn * dynRPath = 0, * dynRunPath = 0;
1153+
Elf_Dyn * dynRPath = 0, * dynRunPath = 0, * dynReplaceable = 0;
11541154
char * rpath = 0;
11551155
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
11561156
if (rdi(dyn->d_tag) == DT_RPATH) {
@@ -1165,6 +1165,12 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
11651165
}
11661166
else if (rdi(dyn->d_tag) == DT_NEEDED)
11671167
neededLibs.push_back(std::string(strTab + rdi(dyn->d_un.d_val)));
1168+
/* Try to replace an IGNORE rather than growing and moving the section, if possible */
1169+
else if (rdi(dyn->d_tag) == DT_IGNORE)
1170+
dynReplaceable = dyn;
1171+
/* If we don't find an IGNORE, RELCOUNT/RELACOUNT are redundant and optional, so we can replace those */
1172+
else if (!dynReplaceable && (rdi(dyn->d_tag) == DT_RELCOUNT || rdi(dyn->d_tag) == DT_RELACOUNT))
1173+
dynReplaceable = dyn;
11681174
}
11691175

11701176
if (op == rpPrint) {
@@ -1290,7 +1296,11 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
12901296
if (dynRunPath) dynRunPath->d_un.d_val = shdrDynStr.sh_size;
12911297
if (dynRPath) dynRPath->d_un.d_val = shdrDynStr.sh_size;
12921298
}
1293-
1299+
/* Convert an unused or redundant entry to a DT_RPATH or DT_RUNPATH */
1300+
else if (dynReplaceable) {
1301+
dynReplaceable->d_un.d_val = shdrDynStr.sh_size;
1302+
dynReplaceable->d_tag = forceRPath ? DT_RPATH : DT_RUNPATH;
1303+
}
12941304
else {
12951305
/* There is no DT_RUNPATH entry in the .dynamic section, so we
12961306
have to grow the .dynamic section. */

0 commit comments

Comments
 (0)