Skip to content

Commit 81473a1

Browse files
author
Maximilian Bosch
committed
Add -add-rpath-and-shrink operation
The core issue is that `--shrink-rpath` doesn't free up space filled with `X` by `--add-rpath`, so using a combination of `--add-rpath` & `--shrink-rpath` on a virtual env will blow up shared libraries and cause them to segfault when loaded by Python at some point.
1 parent a0f5433 commit 81473a1

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

src/patchelf.cc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1477,8 +1477,13 @@ std::string ElfFile<ElfFileParamNames>::shrinkRPath(char* rpath, std::vector<std
14771477
std::vector<bool> neededLibFound(neededLibs.size(), false);
14781478

14791479
std::string newRPath = "";
1480+
std::set<std::string> componentsConsidered;
14801481

14811482
for (auto & dirName : splitColonDelimitedString(rpath)) {
1483+
if (componentsConsidered.find(dirName) != componentsConsidered.end()) {
1484+
continue;
1485+
}
1486+
componentsConsidered.insert(dirName);
14821487

14831488
/* Non-absolute entries are allowed (e.g., the special
14841489
"$ORIGIN" hack). */
@@ -1617,6 +1622,14 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
16171622
break;
16181623
}
16191624
case rpSet: { break; } /* new rpath was provied as input to this function */
1625+
case rpShrinkAndAdd: {
1626+
auto temp = std::string(rpath ? rpath : "");
1627+
appendRPath(temp, newRPath);
1628+
newRPath = temp;
1629+
char * newRPathCStr = const_cast<char *>(newRPath.c_str());
1630+
newRPath = shrinkRPath(newRPathCStr, neededLibs, allowedRpathPrefixes);
1631+
break;
1632+
}
16201633
}
16211634

16221635
if (!forceRPath && dynRPath && !dynRunPath) { /* convert DT_RPATH to DT_RUNPATH */
@@ -2419,7 +2432,9 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
24192432
else if (setExecstack)
24202433
elfFile.modifyExecstack(ElfFile::ExecstackMode::set);
24212434

2422-
if (shrinkRPath)
2435+
if (shrinkRPath && addRPath)
2436+
elfFile.modifyRPath(elfFile.rpShrinkAndAdd, allowedRpathPrefixes, newRPath);
2437+
else if (shrinkRPath)
24232438
elfFile.modifyRPath(elfFile.rpShrink, allowedRpathPrefixes, "");
24242439
else if (removeRPath)
24252440
elfFile.modifyRPath(elfFile.rpRemove, {}, "");
@@ -2567,6 +2582,12 @@ static int mainWrapped(int argc, char * * argv)
25672582
if (++i == argc) error("missing argument");
25682583
allowedRpathPrefixes = splitColonDelimitedString(argv[i]);
25692584
}
2585+
else if (arg == "--add-rpath-and-shrink") {
2586+
if (++i == argc) error("missing argument");
2587+
addRPath = true;
2588+
newRPath = resolveArgument(argv[i]);
2589+
shrinkRPath = true;
2590+
}
25702591
else if (arg == "--set-rpath") {
25712592
if (++i == argc) error("missing argument");
25722593
setRPath = true;

src/patchelf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class ElfFile
149149

150150
void setInterpreter(const std::string & newInterpreter);
151151

152-
typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove } RPathOp;
152+
typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove, rpShrinkAndAdd } RPathOp;
153153

154154
void modifyRPath(RPathOp op, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath);
155155
std::string shrinkRPath(char* rpath, std::vector<std::string> &neededLibs, const std::vector<std::string> & allowedRpathPrefixes);

0 commit comments

Comments
 (0)