exports: Try harder to export usrmerge symlinks as symlinks

In applications with --filesystem=host or --filesystem=host-os, the
library directories in /run/host/usr and /run/host/lib* can be used
like a sysroot to inspect the host's library stack, regardless of
whether the host system has undergone the "/usr merge" or not. This is
particularly relevant for Steam's pressure-vessel container tool,
which imports graphics drivers from the host system, or for potential
future work on using host graphics drivers via libcapsule in Flatpak
apps.

The original implementation of this feature assumed that the /usr merge
always creates symbolic links /foo -> /usr/foo or /foo -> usr/foo, for
some value of foo. However, Arch Linux uses a variation of multilib
in which /usr/lib contains 64-bit libraries, and has a non-matching
symbolic link /lib64 -> usr/lib (instead of a chain of symlinks
/lib64 -> usr/lib64 -> lib). Similarly, Arch uses /sbin -> usr/bin
and /usr/sbin -> bin, instead of a chain of symlinks
/sbin -> usr/sbin -> bin.

This led to Flatpak ignoring the symlink and treating it like a directory,
so the host /usr/lib would be bind-mounted on both /run/host/usr/lib and
/run/host/lib64. This is *mostly* equivalent, but whether a directory
is a symlink or a real directory sometimes matters, for example when
evaluating relative symlinks that contain ".."  components; so try harder
to preserve symlinks as symlinks.

Fixes: 08d65c54 "exports: If --filesystem=host, provide /run/host/lib etc."
Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie
2020-07-31 15:13:33 +01:00
committed by Alexander Larsson
parent 2612e9df18
commit 12e3dc051f

View File

@@ -325,18 +325,17 @@ flatpak_exports_append_bwrap_args (FlatpakExports *exports,
target = glnx_readlinkat_malloc (-1, subdir, NULL, NULL);
if (target != NULL &&
g_str_has_prefix (target, "usr/") &&
g_strcmp0 (target + 3, subdir) == 0)
g_str_has_prefix (target, "usr/"))
{
/* e.g. /lib32 is a relative symlink to usr/lib32;
/* e.g. /lib32 is a relative symlink to usr/lib32, or
* on Arch Linux, /lib64 is a relative symlink to usr/lib;
* keep it relative */
flatpak_bwrap_add_args (bwrap,
"--symlink", target, run_host_subdir,
NULL);
}
else if (target != NULL &&
g_str_has_prefix (target, "/usr/") &&
g_strcmp0 (target + 4, subdir) == 0)
g_str_has_prefix (target, "/usr/"))
{
/* e.g. /lib32 is an absolute symlink to /usr/lib32; make
* it a relative symlink to usr/lib32 instead by skipping