Skip to content

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 has DT_RPATH or DT_RUNPATH containing 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:

gcc -shared -fPIC lib.c -o libfoo.so '-Wl,-rpath,$ORIGIN'

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:

chrpath -d libfoo.so
# or
patchelf --remove-rpath libfoo.so

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).