From 8d93b6b0ca96de5bf4ab836df9fd2b824a6d307e Mon Sep 17 00:00:00 2001 From: Ikey Doherty Date: Thu, 9 Nov 2017 21:58:25 +0000 Subject: [PATCH] intercept: Add support for snapd libGL redirection Under a snapd environment, the dynamic linker gets very confused about where libGL really is, and this causes 32-bit driver usage under LSI to completely fall flat. When snapd support is enabled, we'll check for specific path matches and attempt to override the input request with the intended bi-arch replacement. This doesn't yet support multiarch, but that will be added in time. This is part of the ongoing issue #30. Signed-off-by: Ikey Doherty --- src/intercept/intercept.h | 41 +++++++++++++ src/intercept/main.c | 15 ++--- src/intercept/meson.build | 4 ++ src/intercept/snapd.c | 121 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 src/intercept/intercept.h create mode 100644 src/intercept/snapd.c diff --git a/src/intercept/intercept.h b/src/intercept/intercept.h new file mode 100644 index 0000000..29ef0ff --- /dev/null +++ b/src/intercept/intercept.h @@ -0,0 +1,41 @@ +/* + * This file is part of linux-steam-integration. + * + * Copyright © 2016-2017 Ikey Doherty + * + * linux-steam-integration is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + */ + +#pragma once + +#include + +/** + * Attempt to handle snapd specific paths and perform any necessary redirections + * for the solus-runtime-gaming based LSI snap package. + * + * @note This must run for all processes, as we handle libGL interception. + * + * @param name Original search name + * @param flag rtld-audit flags + * @param soname Pointer to store the final soname in + * + * @returns True if we performed any redirection, to stop further processing. + */ +bool lsi_override_snapd(const char *name, unsigned int flag, const char **soname); + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=8 tabstop=8 expandtab: + * :indentSize=8:tabSize=8:noTabs=true: + */ diff --git a/src/intercept/main.c b/src/intercept/main.c index 30558a2..577ccf7 100644 --- a/src/intercept/main.c +++ b/src/intercept/main.c @@ -22,6 +22,7 @@ #include "../common/files.h" #include "../common/log.h" #include "config.h" +#include "intercept.h" #include "nica/util.h" /** @@ -582,16 +583,12 @@ _nica_public_ char *la_objsearch(const char *name, __lsi_unused__ uintptr_t *coo unsigned int flag) { #ifdef HAVE_SNAPD_SUPPORT - /* - * Super special case. If we're a snap, and the file being requested is - * actually within the private snapd trees, we must unconditionally permit - * that file, as it is most likely a driver - */ - if (strstr(name, "/var/lib/snapd/gl") || strstr(name, "/var/lib/snapd/hostfs")) { - lsi_log_debug("skipping snapd file: %s", name); - return name; + const char *out_name = NULL; + + /* Only attempt snapd overrides if snapd support is enabled */ + if (lsi_override_snapd(name, flag, &out_name)) { + return (char *)out_name; } - lsi_log_debug("snapd debug: %s", name); #endif switch (work_mode) { case INTERCEPT_MODE_STEAM: diff --git a/src/intercept/meson.build b/src/intercept/meson.build index 8d131d3..2aaa2f5 100644 --- a/src/intercept/meson.build +++ b/src/intercept/meson.build @@ -6,6 +6,10 @@ if with_libintercept == true 'main.c', ] + if with_snap_support == true + intercept_sources += 'snapd.c' + endif + sym_map = join_paths(meson.current_source_dir(), 'sym.map') main_intercept = shared_library( diff --git a/src/intercept/snapd.c b/src/intercept/snapd.c new file mode 100644 index 0000000..2899ac2 --- /dev/null +++ b/src/intercept/snapd.c @@ -0,0 +1,121 @@ +/* + * This file is part of linux-steam-integration. + * + * Copyright © 2016-2017 Ikey Doherty + * + * linux-steam-integration is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + */ + +#define _GNU_SOURCE + +#include +#include +#include + +#include "../common/common.h" +#include "../common/files.h" +#include "../common/log.h" +#include "intercept.h" + +/** + * Contains the exact soname paths that the linker will request + */ +static const char *libgl_source_table[] = { +#if UINTPTR_MAX == 0xffffffffffffffff + "/usr/lib64/libGL.so.1", + "/usr/lib64/libEGL.so.1", + /* Duped due to lib vs lib64 differences between solus + snap */ + "/usr/lib/libGL.so.1", + "/usr/lib/libEGL.so.1", +#else + /* 32bit support */ + "/usr/lib32/libGL.so.1", + "/usr/lib32/libEGL.so.1", +#endif +}; + +/** + * Contains the exact soname paths that we'll return for biarch situations + * + * TODO: Also support Ubuntu/Debian multiarch overlay + */ +static const char *libgl_target_table[] = { +#if UINTPTR_MAX == 0xffffffffffffffff + "/var/lib/snapd/lib/gl/libGL.so.1", + "/var/lib/snapd/lib/gl/libEGL.so.1", + /* Duped due to lib vs lib64 differences between solus + snap */ + "/var/lib/snapd/lib/gl/libGL.so.1", + "/var/lib/snapd/lib/gl/libEGL.so.1", +#else + /* 32bit support */ + "/var/lib/snapd/lib/gl/32/libGL.so.1", + "/var/lib/snapd/lib/gl/32/libEGL.so.1", +#endif +}; + +/** + * If the hostfs provided links don't exist, then we didn't get any links from + * the snapd setup routine, so we'll just repoint back to mesa. + */ +static const char *libgl_mesa_table[] = { +#if UINTPTR_MAX == 0xffffffffffffffff + "/usr/lib64/glx-provider/default/libGL.so.1", + "/usr/lib64/glx-provider/default/libEGL.so.1", + /* Duped due to lib vs lib64 differences between solus + snap */ + "/usr/lib/glx-provider/default/libGL.so.1", + "/usr/lib/glx-provider/default/libEGL.so.1", +#else + /* 32bit support */ + "/usr/lib32/glx-provider/default/libGL.so.1", + "/usr/lib32/glx-provider/default/libEGL.so.1", +#endif +}; + +bool lsi_override_snapd(const char *name, __lsi_unused__ unsigned int flag, const char **soname) +{ + for (size_t i = 0; i < ARRAY_SIZE(libgl_source_table); i++) { + const char *source = libgl_source_table[i]; + const char *target = NULL; + + if (strcmp(name, source) != 0) { + continue; + } + + if (lsi_file_exists(libgl_target_table[i])) { + target = libgl_target_table[i]; + lsi_log_debug( + "Enforcing hostfs snapd driver links: \033[31;1m%s\033[0m -> " + "\033[34;1m%s\033[0m", + name, + target); + } else { + target = libgl_mesa_table[i]; + lsi_log_debug( + "Enforcing Mesa snapd driver links: \033[31;1m%s\033[0m -> " + "\033[34;1m%s\033[0m", + name, + target); + } + *soname = target; + return true; + } + + /* We didn't get a match. Allow to continue */ + return false; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=8 tabstop=8 expandtab: + * :indentSize=8:tabSize=8:noTabs=true: + */