merged-/usr FEX-Emu rootfs + non-merged-/usr aarch64 OS breaks pressure-vessel
tl;dr: FEX-Emu's rootfs (pseudo-overlayfs) causes us problems when the real root filesystem is not merged-/usr, but the FEX-Emu rootfs is merged-/usr.
To reproduce
Have an aarch64 device running Debian with a non-merged-/usr root filesystem: /lib
, /bin
, /sbin
are real directories (containing low-level/core executables and libraries like ld.so
, glibc and sh
), and /usr/lib
, /usr/bin
and /usr/sbin
are separate real directories (containing higher-level executables and libraries like libGL and env
). The original report from @Sonicadvance1 involved a somewhat outdated Debian 12 'bookworm' installation.
(Note that modern versions of debootstrap
default to merged-/usr for Debian 12, and debian-installer defaults to merged-/usr since Debian 10, so you will have to explicitly use debootstrap --no-merged-usr
to set up a system on which to reproduce this.)
Have a FEX-Emu rootfs with a merged-/usr layout: ${FEX_ROOTFS}/lib -> usr/lib
, ${FEX_ROOTFS}/bin -> usr/bin
etc. are symlinks, and the corresponding directories in ${FEX_ROOTFS}/usr
contain both the low-level and higher-level stuff (usr/bin/sh
, usr/bin/env
and so on).
Launch an x86 game using an x86 pressure-vessel and FEX-Emu.
Expected result
pressure-vessel successfully builds up a container whose filesystem namespace looks like this:
lib/
aarch64-linux-gnu/
ld-linux-aarch64.so.1
libc.so.6, etc. from the real aarch64 root
bin/
sh, etc. from the real aarch64 root
...
run/
gfx/
bin -> usr/bin
lib -> usr/lib
usr/
bin/
env, sh, etc. from the FEX-Emu rootfs
lib/
x86_64-linux-gnu/
libc.so.6, libGL.so.1, etc. from the FEX-Emu rootfs
i386-linux-gnu/
libc.so.6, libGL.so.1, etc. from the FEX-Emu rootfs
host/
...
pressure-vessel/
interpreter-root/
bin -> usr/bin
lib -> usr/lib
overrides -> usr/lib/pressure-vessel/overrides
usr/
bin/
env, sh, etc. from the soldier runtime
lib/
x86_64-linux-gnu/
SDL, etc. from the soldier runtime
i386-linux-gnu/
SDL, etc. from the soldier runtime
pressure-vessel/
overrides/
lib/
x86_64-linux-gnu/
symlinks to /run/gfx/usr/lib/x86_64-linux-gnu/libc.so.6, etc.
i386-linux-gnu/
symlinks to /run/gfx/usr/lib/i386-linux-gnu/libc.so.6, etc.
Actual result
There is some sort of confusion between the real root filesystem not being merged-/usr and the FEX-Emu rootfs being merged-/usr, which results in execve()
failing:
execvp /run/pressure-vessel/interpreter-root/usr/lib/pressure-vessel/from-host/bin/pressure-vessel-adverb: No such file or directory
I have not reproduced this myself, so I don't know the full root cause, but I would guess that either the x86_64 ld.so
is not found, or a core library like glibc is not found.
Tested workaround
Install usrmerge
on the aarch64 device to get a merged-/usr OS image, or re-image with a fresh debootstrap --merged-usr
.
(Note that merged /usr will be the only supported layout for Debian 12 and (likely) Ubuntu ≥ 22.10, so this is going to solve itself over time. Merged /usr is also the only supported layout for Arch and Fedora, and the default for new installations of Debian ≥ 10 and Ubuntu ≥ 20.04.)
Untested workaround
Alternatively, making the FEX-Emu "rootfs" be non-merged-/usr might mitigate this.