aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-03-11 04:25:17 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-03-11 04:25:17 -0500
commiteabd8746e14fd1250b6d8afc3db5f106de6aee78 (patch)
tree5d5080ac2b595b10c549dfae30bf80f70dd8667e /src
parent7b1a46ce3419795dedf86ea2b96b2c2e7b8f2d2e (diff)
Patch RPATH to absolute paths when applying cap_sys_admin
glibc's ld.so ignores $ORIGIN in RPATH for capability binaries (AT_SECURE mode), causing "cannot open shared object" errors. Now patchelf rewrites RPATH to absolute paths before setcap runs, both in the settings dialog and the auto-apply at mount time. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src')
-rw-r--r--src/src/organizercore.cpp25
-rw-r--r--src/src/settingsdialogproton.cpp14
2 files changed, 29 insertions, 10 deletions
diff --git a/src/src/organizercore.cpp b/src/src/organizercore.cpp
index b42c3ed..c6bd678 100644
--- a/src/src/organizercore.cpp
+++ b/src/src/organizercore.cpp
@@ -684,13 +684,24 @@ void OrganizerCore::prepareVFS()
std::fprintf(stderr,
"[VFS] passthrough enabled but binary lacks cap_sys_admin "
"— requesting via pkexec...\n");
- QProcess setcap;
- setcap.setProgram("pkexec");
- setcap.setArguments({"setcap", "cap_sys_admin+ep", binary});
- setcap.start();
- setcap.waitForFinished(60000);
- if (setcap.exitCode() != 0) {
+ // When cap_sys_admin is set on a binary, glibc's ld.so enters
+ // AT_SECURE mode and ignores $ORIGIN in RPATH. Patch RPATH to
+ // absolute paths before applying the capability.
+ const QFileInfo fi(binary);
+ const QString binDir = fi.absolutePath();
+ const QString absRpath = binDir + "/lib:" + binDir + "/python/lib";
+
+ QProcess patchelf;
+ patchelf.setProgram("pkexec");
+ patchelf.setArguments({"bash", "-c",
+ QString("patchelf --force-rpath --set-rpath '%1' '%2' && "
+ "setcap cap_sys_admin+ep '%2'")
+ .arg(absRpath, binary)});
+ patchelf.start();
+ patchelf.waitForFinished(60000);
+
+ if (patchelf.exitCode() != 0) {
std::fprintf(stderr,
"[VFS] failed to set cap_sys_admin — disabling passthrough\n");
passthrough = false;
@@ -699,7 +710,7 @@ void OrganizerCore::prepareVFS()
// have it until next exec. Disable passthrough for this session —
// it will work automatically on next launch.
std::fprintf(stderr,
- "[VFS] cap_sys_admin applied to binary — passthrough "
+ "[VFS] cap_sys_admin + absolute RPATH applied — passthrough "
"will activate on next launch\n");
passthrough = false;
}
diff --git a/src/src/settingsdialogproton.cpp b/src/src/settingsdialogproton.cpp
index 36838c4..4bab341 100644
--- a/src/src/settingsdialogproton.cpp
+++ b/src/src/settingsdialogproton.cpp
@@ -71,11 +71,19 @@ ProtonSettingsTab::ProtonSettingsTab(Settings& s, SettingsDialog& d)
ui->passthroughStatusLabel->setText(
tr("Granting FUSE passthrough capability... (sudo prompt)"));
- // Use pkexec (graphical sudo) to set the file capability.
- // This is a one-time operation — the capability persists across runs.
+ // Use pkexec to patch RPATH to absolute paths and set
+ // the file capability. $ORIGIN in RPATH is ignored by
+ // glibc for capability binaries (AT_SECURE mode).
+ const QFileInfo fi(binary);
+ const QString binDir = fi.absolutePath();
+ const QString absRpath = binDir + "/lib:" + binDir + "/python/lib";
+
QProcess proc;
proc.setProgram("pkexec");
- proc.setArguments({"setcap", "cap_sys_admin+ep", binary});
+ proc.setArguments({"bash", "-c",
+ QString("patchelf --force-rpath --set-rpath '%1' '%2' && "
+ "setcap cap_sys_admin+ep '%2'")
+ .arg(absRpath, binary)});
proc.start();
proc.waitForFinished(60000); // 60s timeout for user to auth