Skip to content

capsule-capture-libs treats $ORIGIN literally in DT_RUNPATH dependency lookup #837

Description

@tracyliving

Your system information

  • Steam Runtime Version: Steam Linux Runtime 3.0 (sniper) 3.0.20260608.242788; steam-runtime-tools / pressure-vessel 0.20260601.0
  • Distribution (e.g. Ubuntu 18.04): Ubuntu 26.04 LTS
  • Link to your full system information (Help -> Steam Runtime Diagnostics) in a Gist: https://gist.github.com/tracyliving/e82c7ab2fc0377924a1dad785c4bd333 (home directory redacted)
  • Have you checked for system updates?: Steam verified its installation; host package updates were not checked because the standalone reproducer does not depend on the graphics stack
  • What compatibility tool are you using?: Steam Linux Runtime 3.0 (sniper); the reproducer also invokes its capsule-capture-libs directly
  • What versions are listed in steamapps/common/SteamLinuxRuntime/VERSIONS.txt? Not installed
  • What versions are listed in steamapps/common/SteamLinuxRuntime_soldier/VERSIONS.txt? Not installed
  • What versions are listed in steamapps/common/SteamLinuxRuntime_sniper/VERSIONS.txt? depot 3.0.20260608.242788, pressure-vessel 0.20260601.0, sniper 3.0.20260608.242788
  • What versions are listed in steamapps/common/SteamLinuxRuntime_4/VERSIONS.txt? depot 4.0.20260608.242786, pressure-vessel 0.20260601.0, steamrt4 4.0.20260608.242786

Please describe your issue in as much detail as possible:

x86_64-linux-gnu-capsule-capture-libs recognizes a DSO's DT_RUNPATH=$ORIGIN, but appears to treat $ORIGIN as a literal directory name instead of expanding it relative to the DSO containing the RUNPATH.

A minimal layer DSO has:

NEEDED  Shared library: [libcapsule-origin-helper.so.1]
RUNPATH Library runpath: [$ORIGIN]

The layer and helper are in the same directory. A normal dlopen(..., RTLD_NOW) succeeds and calls into the helper (result=42). The same layer fails dependency resolution in capsule-capture-libs.

Relevant debug output:

_dso_iterate_sections: .../libcapsule-origin-layer.so.1 DT_RUNPATHs "$ORIGIN"
search_ldpath: searching for libcapsule-origin-helper.so.1 in $ORIGIN (prefix: /)
search_ldpath: examining /$ORIGIN/libcapsule-origin-helper.so.1
error: code 2: Missing dependencies: Could not find
       "libcapsule-origin-helper.so.1" in LD_LIBRARY_PATH (unset),
       ld.so.cache, DT_RUNPATH or fallback ...

I expected $ORIGIN to resolve to the directory containing libcapsule-origin-layer.so.1, matching the dynamic loader. This affects importing host Vulkan layers that have private sibling dependencies.

Sanitized standalone reproducer and observed output:
https://gist.github.com/tracyliving/43714c213b92c677aee924697c97f345

Workarounds include adding the sibling directory to LD_LIBRARY_PATH, using an absolute RUNPATH, or removing the DT_NEEDED edge and loading the sibling explicitly. PRESSURE_VESSEL_IMPORT_VULKAN_LAYERS=0 bypasses this path but disables host Vulkan-layer import, so it is not equivalent behavior.

I found issue #478 while searching, but that concerns non-standard Guix library locations rather than $ORIGIN expansion.

Steps for reproducing this issue:

  1. Clone the reproducer:

    git clone https://gist.github.com/43714c213b92c677aee924697c97f345.git capsule-origin-repro
    cd capsule-origin-repro
  2. Pass the installed Sniper tool to the script:

    sh reproduce.sh \
      "$HOME/.local/share/Steam/steamapps/common/SteamLinuxRuntime_sniper/pressure-vessel/libexec/steam-runtime-tools-0/x86_64-linux-gnu-capsule-capture-libs"
  3. Observe that the native loader prints result=42, then capsule-capture-libs exits nonzero after examining /$ORIGIN/libcapsule-origin-helper.so.1.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions