fix(relinker): validate Linux guest runpaths with target syntax

This commit is contained in:
ArjenS-LA 2026-10-12 15:10:28 -07:00 committed by Dean Galvin
parent ee9037d851
commit 394c5a231e
2 changed files with 14 additions and 5 deletions

View File

@ -285,7 +285,7 @@ std::vector<GuestArtifact> GuestModuleBuilder::Build(const std::filesystem::path
};
for (const auto index : order) if (!windows && !deferred(index)) addNeeded("$ORIGIN/" + appDirectory(images[index]) + "/" + images[index].OutputName);
for (const auto& name : hostLibraries) addNeeded(name);
if (!windows && runPath != "$ORIGIN" && !runPath.starts_with("$ORIGIN/") && !runPath.starts_with("$ORIGIN:") && !std::filesystem::path(runPath).is_absolute()) throw Domain::RelinkerException("Guest Linux run path must be absolute or begin with $ORIGIN");
if (!windows && runPath != "$ORIGIN" && !runPath.starts_with("$ORIGIN/") && !runPath.starts_with("$ORIGIN:") && !runPath.starts_with('/')) throw Domain::RelinkerException("Guest Linux run path must be absolute or begin with $ORIGIN");
const auto outputDirectory = outputPath.parent_path().lexically_normal();
std::vector<GuestArtifact> artifacts;
for (const auto index : order) {

View File

@ -17,7 +17,8 @@ def main():
checked = 0
for index, module_directory in enumerate(("sce_module", "prx")):
for label, run_path in (("default", None), ("origin", "$ORIGIN"),
("custom", "$ORIGIN/host libs"), ("absolute", str(work / "absolute libs")),
("custom", "$ORIGIN/host libs"), ("absolute", "/opt/absolute libs"),
("absolute-root", "/"), ("absolute-list", "/opt/libs:/usr/local/lib"),
("list", "$ORIGIN/first:$ORIGIN/second"),
("list-bare", "$ORIGIN:$ORIGIN/libs:$ORIGIN")):
case = work / f"{index}-{label}"
@ -43,13 +44,21 @@ def main():
assert 0 <= offset < len(strings) and end >= 0, (tags, strings)
actual = strings[offset:end].decode()
configured = run_path if run_path is not None else "$ORIGIN/libs"
configured_paths = configured.split(":") if label.startswith("list") else [configured]
actual_paths = actual.split(":") if label.startswith("list") else [actual]
path_list = label.startswith("list") or label == "absolute-list"
configured_paths = configured.split(":") if path_list else [configured]
actual_paths = actual.split(":") if path_list else [actual]
expected = [Path(path.replace("$ORIGIN", str(output.parent))).resolve() for path in configured_paths]
resolved = [Path(path.replace("$ORIGIN", str(artifact.parent))).resolve() for path in actual_paths]
if resolved != expected or (label == "absolute" and actual != run_path):
if resolved != expected or (label.startswith("absolute") and actual != run_path):
failures.append((str(relative), label, actual, str(resolved), str(expected)))
checked += 1
for index, run_path in enumerate(("relative/libs", "C:/host/libs", "C:\\host\\libs", "\\\\server\\share")):
output = work / f"invalid-{index}.elf"
result = subprocess.run([str(relinker), "--rpath", run_path, str(source), str(output)],
capture_output=True, text=True, timeout=20)
assert result.returncode == 2 and "run path must be absolute or begin with $ORIGIN" in result.stderr, (
run_path, result.returncode, result.stdout, result.stderr)
assert not output.exists()
assert not failures, failures
print(f"Guest run path tests passed: {checked} module/path combinations")