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 <ikey@solus-project.com>
This commit is contained in:
Ikey Doherty
2017-11-09 22:00:21 +00:00
parent 103ab0a673
commit 8d93b6b0ca
4 changed files with 172 additions and 9 deletions
+41
View File
@@ -0,0 +1,41 @@
/*
* This file is part of linux-steam-integration.
*
* Copyright © 2016-2017 Ikey Doherty <ikey@solus-project.com>
*
* 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 <stdbool.h>
/**
* 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:
*/
+6 -9
View File
@@ -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:
+4
View File
@@ -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(
+121
View File
@@ -0,0 +1,121 @@
/*
* This file is part of linux-steam-integration.
*
* Copyright © 2016-2017 Ikey Doherty <ikey@solus-project.com>
*
* 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#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:
*/