From 3eeb7312243d6fc1c70eb02a3a3bad66aa5b0f26 Mon Sep 17 00:00:00 2001 From: Ikey Doherty Date: Wed, 8 Nov 2017 01:10:35 +0000 Subject: [PATCH] intercept: Blacklist vendoring libmpg123/libz/libfreetype Discovered while validating 'Overlord II', these libraries should be provided by the LSI integrator, especially at such a low level in the stack (and mpg123 being security sensitive.) Additionally these files are relative to the CWD so got missed by the previous "./" grouping, thus we'll conditionally replace these guys with the host libraries per the blacklist only. Signed-off-by: Ikey Doherty --- src/intercept/main.c | 109 +++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 24 deletions(-) diff --git a/src/intercept/main.c b/src/intercept/main.c index 5438df1..bfac2b5 100644 --- a/src/intercept/main.c +++ b/src/intercept/main.c @@ -108,6 +108,11 @@ static const char *vendor_blacklist[] = { "libstdc++", "libSDL", + /* vendor-owned */ + "libz.so.1", + "libfreetype.so.6", + "libmpg123.so.0", + /* general problem causer. */ "libopenal.so.", @@ -133,6 +138,8 @@ static const char *vendor_blacklist[] = { "libcrypto.so.1.0.0", "libssl.so.1.0.0", #endif + /* TODO/FUTURE: + "libaudiofile.so.1", */ }; /** @@ -357,15 +364,10 @@ static bool lsi_override_x86_derp(__lsi_unused__ const char *orig_name, } /** - * lsi_override_dlopen is used to override simple dlopen() requests typically - * used by Mono games, i.e.: - * - * - * - * We'll attempt to do a trivial lookup for "/usr/./lib64/libSDL2-2.0.so.0 in this - * case. + * Internal helper for path replacement to host lib */ -static bool lsi_override_dlopen(const char *orig_name, const char **soname) +static bool lsi_override_replace_with_host(const char *orig_name, const char **soname, + const char *msg) { static char path_lookup[PATH_MAX]; static char path_copy[PATH_MAX]; @@ -382,18 +384,6 @@ static bool lsi_override_dlopen(const char *orig_name, const char **soname) #endif }; - if (lsi_override_dll_fail(orig_name, soname)) { - return true; - } - - if (!lsi_file_exists(orig_name)) { - return false; - } - - if (lsi_override_x86_derp(orig_name, soname)) { - return true; - } - if (!strcpy(path_copy, orig_name)) { return false; } @@ -422,16 +412,42 @@ static bool lsi_override_dlopen(const char *orig_name, const char **soname) } *soname = path_lookup; - lsi_log_debug( - "intercepting vendor dlopen() \033[31;1m%s\033[0m -> \033[34;1m%s\033[0m", - orig_name, - path_lookup); + lsi_log_debug("%s \033[31;1m%s\033[0m -> \033[34;1m%s\033[0m", + msg, + orig_name, + path_lookup); return true; } return false; } +/** + * lsi_override_dlopen is used to override simple dlopen() requests typically + * used by Mono games, i.e.: + * + * + * + * We'll attempt to do a trivial lookup for "/usr/./lib64/libSDL2-2.0.so.0 in this + * case. + */ +static bool lsi_override_dlopen(const char *orig_name, const char **soname) +{ + if (lsi_override_dll_fail(orig_name, soname)) { + return true; + } + + if (!lsi_file_exists(orig_name)) { + return false; + } + + if (lsi_override_x86_derp(orig_name, soname)) { + return true; + } + + return lsi_override_replace_with_host(orig_name, soname, "intercepting vendor dlopen()"); +} + /** * lsi_override_soname will deal with LA_SER_ORIG entries, i.e. the original * soname request when the linker tries to load a library. @@ -480,6 +496,46 @@ static bool lsi_override_soname(unsigned int flag, const char *orig_name, const return false; } +/** + * If the library exists locally, and we're attempting to load this from a + * relative location, strongly attempt to actually use the system-version instead. + * + * Thus, if our CWD is our LD_LIBRARY_PATH and contains "libfreetype.so.6", we'll + * try to use the host version of the library if that exists, instead of relying + * on the locally vendored, potentially insecure/buggy version. + */ +static bool lsi_override_local(unsigned int flag, const char *orig_name, const char **soname) +{ + *soname = NULL; + + /* We only need to deal with LA_SER_ORIG */ + if ((flag & LA_SER_ORIG) != LA_SER_ORIG) { + return false; + } + + /* We only care about relative paths */ + if (strstr(orig_name, "/")) { + return false; + } + + /* We also only care about relative paths */ + if (!lsi_file_exists(orig_name)) { + return false; + } + + /* Resolve all paths back to the real library path version if they exist */ + for (size_t i = 0; i < ARRAY_SIZE(vendor_blacklist); i++) { + if (!strstr(orig_name, vendor_blacklist[i])) { + continue; + } + return lsi_override_replace_with_host(orig_name, + soname, + "forcing use of host library"); + } + + return false; +} + char *lsi_blacklist_vendor(unsigned int flag, const char *name) { /* Find out if it exists */ @@ -491,6 +547,11 @@ char *lsi_blacklist_vendor(unsigned int flag, const char *name) return (char *)override_soname; } + /* Locally exists due to directory foobar */ + if (lsi_override_local(flag, name, &override_soname)) { + return (char *)override_soname; + } + /* Find out if its a Steam private lib.. These are relative "./" files too! */ if (name && (strstr(name, "/Steam/") || strncmp(name, "./", 2) == 0)) { for (size_t i = 0; i < ARRAY_SIZE(vendor_blacklist); i++) {