diff --git a/src/intercept/intercept.h b/src/intercept/intercept.h index 29ef0ff..edf6666 100644 --- a/src/intercept/intercept.h +++ b/src/intercept/intercept.h @@ -20,12 +20,22 @@ * @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); +bool lsi_override_snapd_gl(const char *name, const char **soname); + +/** + * Handle redirection of snapd NVIDIA libraries when they can't be found + * sanely due to compounded LD_LIBRARY_PATH abuse. + * + * @param name Original search name + * @param soname Pointer to store the final soname in + * + * @returns True if we performed any redirection, to stop further processing. + */ +bool lsi_override_snapd_nvidia(const char *name, const char **soname); /* * Editor modelines - https://www.wireshark.org/tools/modelines.html diff --git a/src/intercept/main.c b/src/intercept/main.c index 577ccf7..5715d1f 100644 --- a/src/intercept/main.c +++ b/src/intercept/main.c @@ -586,7 +586,10 @@ _nica_public_ char *la_objsearch(const char *name, __lsi_unused__ uintptr_t *coo const char *out_name = NULL; /* Only attempt snapd overrides if snapd support is enabled */ - if (lsi_override_snapd(name, flag, &out_name)) { + if (lsi_override_snapd_gl(name, &out_name)) { + return (char *)out_name; + } + if (lsi_override_snapd_nvidia(name, &out_name)) { return (char *)out_name; } #endif diff --git a/src/intercept/snapd.c b/src/intercept/snapd.c index 2899ac2..6b495fa 100644 --- a/src/intercept/snapd.c +++ b/src/intercept/snapd.c @@ -11,7 +11,9 @@ #define _GNU_SOURCE +#include #include +#include #include #include @@ -74,7 +76,84 @@ static const char *libgl_mesa_table[] = { #endif }; -bool lsi_override_snapd(const char *name, __lsi_unused__ unsigned int flag, const char **soname) +/** + * These are the NVIDIA libraries will attempt to redirect on demand. + */ +static const char *libgl_nvidia_matches[] = { + "libGLdispatch", "libnv", "NVIDIA", "nvidia.so", "cuda", "GLX", +}; + +bool lsi_override_snapd_nvidia(const char *name, const char **soname) +{ + const char *nvidia_target_dir = NULL; + static char path_lookup[PATH_MAX]; + static char path_copy[PATH_MAX]; + char *small_name = NULL; + bool match = false; + + /* Only mangle when we start looking for paths */ + if (!strstr(name, "/")) { + return false; + } + + /* Must be proper versioned libs */ + if (!strstr(name, ".so.")) { + return false; + } + + /* If this guy exists we don't actually care.. */ + if (lsi_file_exists(name)) { + return false; + } + + /* Check if we have some basic pattern for an NVIDIA library here */ + for (size_t i = 0; i < ARRAY_SIZE(libgl_nvidia_matches); i++) { + if (strstr(name, libgl_nvidia_matches[i])) { + match = true; + break; + } + } + + /* Unwanted library */ + if (!match) { + return false; + } + +#if UINTPTR_MAX == 0xffffffffffffffff + /* 64-bit libdir */ + nvidia_target_dir = "/var/lib/snapd/lib/gl"; +#else + /* 32-bit libdir */ + nvidia_target_dir = "/var/lib/snapd/lib/gl/32"; +#endif + + /* Grab the link name */ + if (!strcpy(path_copy, name)) { + return false; + } + small_name = basename(path_copy); + + if (snprintf(path_lookup, sizeof(path_lookup), "%s/%s", nvidia_target_dir, small_name) < + 0) { + return false; + } + + /* Sod all we can do here */ + if (!lsi_file_exists(path_lookup)) { + lsi_log_error("Missing NVIDIA file: %s (%s)", name, path_lookup); + return false; + } + + *soname = path_lookup; + lsi_log_debug( + "Enforcing NVIDIA snapd driver links: \033[31;1m%s\033[0m -> \033[34;1m%s\033[0m", + name, + path_lookup); + + return true; +} + +bool lsi_override_snapd_gl(const char *name, const char **soname) { for (size_t i = 0; i < ARRAY_SIZE(libgl_source_table); i++) { const char *source = libgl_source_table[i];