mirror of
https://github.com/clearlinux/linux-steam-integration.git
synced 2026-10-04 07:58:37 +00:00
redirect: Add our initial dlsym/dlopen dance to grab real open
Instead of relying on RTLD_NEXT we'll do the correct thing and open a reference to libc.so.6 and load the `open` function from there, as our linking order might be janky, causing lookups for `open` to actually fail. Signed-off-by: Ikey Doherty <ikey@solus-project.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -21,6 +22,28 @@
|
||||
|
||||
static volatile bool lsi_init = false;
|
||||
|
||||
/**
|
||||
* Handle definitions
|
||||
*/
|
||||
typedef int (*lsi_open_file)(const char *p, int flags);
|
||||
|
||||
/**
|
||||
* Global storage of handles for nicer organisation.
|
||||
*/
|
||||
typedef struct LsiRedirectTable {
|
||||
lsi_open_file open;
|
||||
|
||||
/* Allow future handle opens.. */
|
||||
struct {
|
||||
void *libc;
|
||||
} handles;
|
||||
} LsiRedirectTable;
|
||||
|
||||
/**
|
||||
* Our redirect instance, stack only.
|
||||
*/
|
||||
static LsiRedirectTable lsi_table = { 0 };
|
||||
|
||||
/**
|
||||
* Determine the basename'd process
|
||||
*/
|
||||
@@ -48,6 +71,11 @@ __attribute__((destructor)) static void lsi_redirect_shutdown(void)
|
||||
}
|
||||
lsi_init = false;
|
||||
fprintf(stderr, "Unloading lsi_redirect\n");
|
||||
|
||||
if (lsi_table.handles.libc) {
|
||||
dlclose(lsi_table.handles.libc);
|
||||
lsi_table.handles.libc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,6 +89,9 @@ __attribute__((destructor)) static void lsi_redirect_shutdown(void)
|
||||
__attribute__((constructor)) static void lsi_redirect_init(void)
|
||||
{
|
||||
autofree(char) *process_name = get_process_name();
|
||||
void *symbol_lookup = NULL;
|
||||
char *dl_error = NULL;
|
||||
|
||||
if (!process_name) {
|
||||
fprintf(stderr, "Failure to allocate memory! %s\n", strerror(errno));
|
||||
return;
|
||||
@@ -69,8 +100,38 @@ __attribute__((constructor)) static void lsi_redirect_init(void)
|
||||
fprintf(stderr, "Loading lsi_redirect for: %s\n", process_name);
|
||||
lsi_init = true;
|
||||
|
||||
/* Try to explicitly open libc. We can't safely rely on RTLD_NEXT
|
||||
* as we might be dealing with a strange link order
|
||||
*/
|
||||
lsi_table.handles.libc = dlopen("libc.so.6", RTLD_LAZY);
|
||||
if (!lsi_table.handles.libc) {
|
||||
fprintf(stderr, "Unable to grab libc.so.6 handle: %s\n", dlerror());
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Safely look up the symbol */
|
||||
symbol_lookup = dlsym(lsi_table.handles.libc, "open");
|
||||
dl_error = dlerror();
|
||||
if (dl_error || !symbol_lookup) {
|
||||
fprintf(stderr, "Failed to bind 'open': %s\n", dl_error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Have the symbol correctly, copy it to make it usable */
|
||||
memcpy(&lsi_table.open, &symbol_lookup, sizeof(lsi_table.open));
|
||||
|
||||
fprintf(stderr, "lsi_redirect now loaded\n");
|
||||
|
||||
/* We might not get an unload, so chain onto atexit */
|
||||
atexit(lsi_redirect_shutdown);
|
||||
return;
|
||||
|
||||
failed:
|
||||
|
||||
/* Failed to initialise so just unload ourselves and let the process continue
|
||||
* unimpeded, so as not to break the user experience.
|
||||
*/
|
||||
lsi_redirect_shutdown();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
if with_libredirect == true
|
||||
|
||||
# Might not need libdl for alt libcs
|
||||
libdl = meson.get_compiler('c').find_library('dl', required : false)
|
||||
|
||||
redirect_sources = [
|
||||
'main.c',
|
||||
]
|
||||
@@ -11,6 +14,9 @@ if with_libredirect == true
|
||||
sources: redirect_sources,
|
||||
c_args: ['-fvisibility=hidden'],
|
||||
include_directories: nica_includes,
|
||||
dependencies: [
|
||||
libdl,
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
endif
|
||||
|
||||
Reference in New Issue
Block a user