Skip to content

Thunks crash (NoExec segfault) inside Steam Linux Runtime / pressure-vessel containers — overlay redirection is host-side only, and pv's graphics capture copies guest thunk stubs into the container #5787

Description

@shuuri-labs

Summary

Running x86_64 Vulkan apps inside a Steam Linux Runtime container (pressure-vessel, with
its FEX interpreter-root integration active) with ThunksDB enabled reliably segfaults with:

E NoExec instruction in entry block: 7FFFF75D2890

Root cause, as far as we can determine: ThunksDB Overlay redirection is only applied in
the host-side rootfs view (the FEXServer mount). pressure-vessel's graphics-library capture
(an x86_64 tool running under FEX) reads the "host" through that overlay, so the guest
thunk stubs get captured byte-for-byte into the container's overrides
as if they were the
real libvulkan.so.1 / libwayland-client.so.0. Inside the container there is no rootfs
mount and no overlay interception, so the guest loads those stub copies as ordinary
libraries from unbless-able paths — the thunk trampolines link, but the invoker region is
never marked executable-for-guest, and the first call through it dies with the NoExec error
above (SIGSEGV, core dumped).

With thunks disabled via FEX_APP_CONFIG (ThunksDB all zero) for the entire launch chain,
everything works: pressure-vessel captures the real rootfs libraries, the emulated x86_64
turnip enumerates, and full x86_64 Proton runs Windows games on this device. So the rest of
the stack is fine — the crash is specific to thunk libraries entering the container.

Environment

  • Device: Retroid Pocket 6 (SM8550, Adreno 740), Arch Linux ARM based distro (pocknix-os)
  • FEX: 2607, built with thunks (ROCKNIX-lineage packaging; happy to attempt a stock-FEX
    repro if useful)
  • RootFS: FEX CDN ArchLinux image 2026-01-08 (squashfs, served by FEXServer/squashfuse),
    x86 turnip updated to Mesa 26.1.5
  • Container: Steam Linux Runtime 4.0 (appid 4183110), launched via _v2-entry-point;
    pressure-vessel runs in interpreter-root mode (/run/pressure-vessel/interpreter-root
    is created, srt-bwrap and pv-adverb run under FEX)
  • Client: native ARM64 Steam (steamdeck_publicbeta), FEX-x86_64/FEX-x86 binfmt_misc
    handlers enabled
  • ThunksDB config: Vulkan/GL/EGL/drm/WaylandClient/asound = 1, standard @PREFIX_LIB@
    overlay paths

Repro

  1. ARM64 device with FEX binfmt handlers enabled and a thunk-enabled FEX + rootfs.
  2. Install Steam Linux Runtime 4.0 from the native ARM64 Steam client.
  3. Run anything Vulkan inside the container, e.g.:
    ~/.local/share/Steam/steamapps/common/SteamLinuxRuntime_4/_v2-entry-point --verb=run -- \
      sh -c 'LD_LIBRARY_PATH=/usr/lib/pressure-vessel/overrides/lib/x86_64-linux-gnu vulkaninfo --summary'
    
  4. Segfault. With FEX_SILENTLOG=0 FEX_OUTPUTLOG=stderr:
    D LoadLib: libwayland-client -> /usr/lib/fex-emu/HostThunks/libwayland-client-host.so
    D LoadLib: libvulkan -> /usr/lib/fex-emu/HostThunks/libvulkan-host.so
    E NoExec instruction in entry block: 7FFFF75D2890
    Segmentation fault (core dumped)
    
    (the faulting address is inside the guest-trampoline/host-invoker range printed by the
    preceding Linking address ... to host invoker ... lines)

Diagnostic evidence

  • The container's /usr/lib/pressure-vessel/overrides/lib/x86_64-linux-gnu/libvulkan.so.1
    is byte-identical to GuestThunks/libvulkan-guest.so (cmp inside the container).
    Same for the wayland-client capture. The capture files' mtimes equal the GuestThunks
    libs' mtimes, not the real libraries'.
  • The pv graphics-provider tree (/var/pressure-vessel/gfx/main/usr/lib/) contains
    libvulkan.so / libvulkan.so.1 as thunk-stub copies, while libvulkan.so.1.4.335
    (not listed in the ThunksDB overlay) kept the real loader bytes — i.e. exactly the
    overlay-listed names were substituted at capture time.
  • Adding container-side paths (the overrides path, the gfx-provider path) to the ThunksDB
    Overlay arrays changes nothing — consistent with overlay interception not existing
    in-container (no rootfs mount there; the FEXServer abstract socket crosses the mount
    namespace but its mount isn't visible).
  • Host-side pieces ARE reachable inside the container: /usr/lib/fex-emu/HostThunks is
    visible (host thunk libs load — see LoadLib lines above) and /run/host exposes the
    full host root, including the native aarch64 Vulkan driver.
  • Disabling thunks for the whole launch (FEX_APP_CONFIG pointing at a ThunksDB-all-zero
    json) produces a fully working container: DXVK enumerates the emulated x86 turnip and
    x86_64 Proton 11 + SLR runs Windows games end-to-end on this device.

Asks / suggestions

  1. Graceful failure: when a guest thunk library is loaded from a path FEX doesn't
    recognize (so the invoker pages can't be blessed), fail the library load or fall back
    to non-thunked operation instead of segfaulting at first call. Even just a clear log
    line would have saved most of this investigation.
  2. Thunks inside containers: consider recognizing thunk guest libraries by content
    (build-id/hash) rather than only by overlay path, or applying overlay redirection
    client-side from the ThunksDB config, so thunking can work under pressure-vessel.
    The host-side ingredients (HostThunks, host driver via /run/host) are already
    reachable in-container thanks to the interpreter-root integration.
  3. Possibly related existing issues: X1E: Steam: Break when enabling thunks #4639 (Steam break with thunks), FEXInterpreter: Punch through a /sys/fex/rootfs node #4228 (rootfs
    visibility across namespaces).

Happy to provide full logs, the coredump, or test patches on hardware.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions