Case 52: RPATH Leak (Hardcoded Build Directory)¶
| Field | Value |
|---|---|
| Verdict | ๐ข COMPATIBLE |
| Category | Quality (Compatible) |
| Platforms | Linux |
| Flags | Bad practice |
Detected ChangeKinds |
โ |
| Source files | browse on GitHub |
Category: ELF / Deployment | Verdict: BAD PRACTICE
What this case is about¶
Both libraries export identical symbols with identical signatures. The
difference is in the DT_RUNPATH / DT_RPATH metadata: v1 has a hardcoded
absolute path (/home/build/myproject/lib) baked into the binary, while v2
uses $ORIGIN-relative paths.
This is a deployment-level bad practice: build-directory paths in shared libraries break on every machine except the one where the library was built.
Why hardcoded RPATH is bad practice¶
- Non-portable: The library only works if the exact build directory exists on the target machine. Deploying to another machine or container fails.
- Security risk: If an attacker can write to the hardcoded path
(
/home/build/myproject/lib), they can inject malicious libraries that get loaded by any binary using this RPATH. - Package manager conflicts: Distribution packages must never contain hardcoded build paths. rpmlint and lintian flag this as a critical error.
- Reproducibility: Build artifacts contain host-specific paths, making reproducible builds impossible.
What abicheck detects¶
RPATH_LEAK: The library hasDT_RPATHorDT_RUNPATHcontaining an absolute path that looks like a build directory. This is classified as a deployment metadata issue.
Overall verdict: COMPATIBLE (same ABI surface; RPATH is deployment concern).
How to reproduce¶
# Build bad version (with hardcoded RPATH)
gcc -shared -fPIC -g bad.c -o libbad.so -Wl,-rpath,/home/build/myproject/lib
# Build good version (with $ORIGIN-relative RUNPATH)
gcc -shared -fPIC -g good.c -o libgood.so '-Wl,-rpath,$ORIGIN'
# Check RPATH
readelf -d libbad.so | grep -E 'RPATH|RUNPATH'
# โ (RUNPATH) Library runpath: [/home/build/myproject/lib] โ leaked!
readelf -d libgood.so | grep -E 'RPATH|RUNPATH'
# โ (RUNPATH) Library runpath: [$ORIGIN] โ correct
# Run abicheck
python3 -m abicheck.cli dump libbad.so -o /tmp/v1.json
python3 -m abicheck.cli dump libgood.so -o /tmp/v2.json
python3 -m abicheck.cli compare /tmp/v1.json /tmp/v2.json
# โ COMPATIBLE + RPATH_LEAK warning
How to fix¶
Use $ORIGIN-relative paths instead of absolute build paths:
In CMake, use proper install RPATH:
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_WITH_INSTALL_RPATH OFF)
set(CMAKE_INSTALL_RPATH_USE_LINK_LIBRARIES OFF)
Or strip RPATH entirely and rely on system paths:
Real-world example¶
Fedora's packaging guidelines explicitly forbid hardcoded RPATH. The
check-rpaths tool rejects any package with non-standard paths in
DT_RPATH/DT_RUNPATH. Debian's lintian reports binary-or-shlib-defines-rpath
as a warning for the same reason.
References¶
Source files¶
See also: Examples overview ยท All COMPATIBLE cases ยท Category: Quality (Compatible).