From 8fd798208777f502a3bd86b02b07a24397792f3f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 6 Apr 2026 14:18:22 +0200 Subject: [PATCH] only dlopen from the defined search paths Don't accept absolute library paths and skip the ../ in paths to avoid opening arbitrary libraries from unexpected places. --- spa/plugins/filter-graph/plugin_ladspa.c | 51 +++++++++++------------ src/modules/module-jack-tunnel/weakjack.h | 44 ++++++++++--------- src/pipewire/impl-module.c | 3 ++ src/pipewire/pipewire.c | 3 ++ 4 files changed, 51 insertions(+), 50 deletions(-) diff --git a/spa/plugins/filter-graph/plugin_ladspa.c b/spa/plugins/filter-graph/plugin_ladspa.c index 1aebafe35..c8a1b4209 100644 --- a/spa/plugins/filter-graph/plugin_ladspa.c +++ b/spa/plugins/filter-graph/plugin_ladspa.c @@ -236,40 +236,37 @@ static inline const char *split_walk(const char *str, const char *delimiter, siz static int load_ladspa_plugin(struct plugin *impl, const char *path) { int res = -ENOENT; + const char *search_dirs, *p, *state = NULL; + char filename[PATH_MAX]; + size_t len; - if (path[0] != '/') { - const char *search_dirs, *p, *state = NULL; - char filename[PATH_MAX]; - size_t len; + while ((p = strstr(path, "../")) != NULL) + path = p + 3; - search_dirs = getenv("LADSPA_PATH"); - if (!search_dirs) - search_dirs = "/usr/lib64/ladspa:/usr/lib/ladspa:" LIBDIR; + search_dirs = getenv("LADSPA_PATH"); + if (!search_dirs) + search_dirs = "/usr/lib64/ladspa:/usr/lib/ladspa:" LIBDIR; - /* - * set the errno for the case when `ladspa_handle_load_by_path()` - * is never called, which can only happen if the supplied - * LADSPA_PATH contains too long paths - */ - res = -ENAMETOOLONG; + /* + * set the errno for the case when `ladspa_handle_load_by_path()` + * is never called, which can only happen if the supplied + * LADSPA_PATH contains too long paths + */ + res = -ENAMETOOLONG; - while ((p = split_walk(search_dirs, ":", &len, &state))) { - int namelen; + while ((p = split_walk(search_dirs, ":", &len, &state))) { + int namelen; - if (len >= sizeof(filename)) - continue; + if (len >= sizeof(filename)) + continue; - namelen = snprintf(filename, sizeof(filename), "%.*s/%s.so", (int) len, p, path); - if (namelen < 0 || (size_t) namelen >= sizeof(filename)) - continue; + namelen = snprintf(filename, sizeof(filename), "%.*s/%s.so", (int) len, p, path); + if (namelen < 0 || (size_t) namelen >= sizeof(filename)) + continue; - res = ladspa_handle_load_by_path(impl, filename); - if (res >= 0) - break; - } - } - else { - res = ladspa_handle_load_by_path(impl, path); + res = ladspa_handle_load_by_path(impl, filename); + if (res >= 0) + break; } return res; } diff --git a/src/modules/module-jack-tunnel/weakjack.h b/src/modules/module-jack-tunnel/weakjack.h index 6d5b5503e..c35bf44b8 100644 --- a/src/modules/module-jack-tunnel/weakjack.h +++ b/src/modules/module-jack-tunnel/weakjack.h @@ -158,34 +158,32 @@ static inline int weakjack_load_by_path(struct weakjack *jack, const char *path) static inline int weakjack_load(struct weakjack *jack, const char *lib) { int res = -ENOENT; + const char *search_dirs, *p, *state = NULL; + char path[PATH_MAX]; + size_t len; - if (lib[0] != '/') { - const char *search_dirs, *p, *state = NULL; - char path[PATH_MAX]; - size_t len; + while ((p = strstr(lib, "../")) != NULL) + lib = p + 3; - search_dirs = getenv("LIBJACK_PATH"); - if (!search_dirs) - search_dirs = PREFIX "/lib64/:" PREFIX "/lib/:" - "/usr/lib64/:/usr/lib/:" LIBDIR; + search_dirs = getenv("LIBJACK_PATH"); + if (!search_dirs) + search_dirs = PREFIX "/lib64/:" PREFIX "/lib/:" + "/usr/lib64/:/usr/lib/:" LIBDIR; - while ((p = pw_split_walk(search_dirs, ":", &len, &state))) { - int pathlen; + while ((p = pw_split_walk(search_dirs, ":", &len, &state))) { + int pathlen; - if (len >= sizeof(path)) { - res = -ENAMETOOLONG; - continue; - } - pathlen = snprintf(path, sizeof(path), "%.*s/%s", (int) len, p, lib); - if (pathlen < 0 || (size_t) pathlen >= sizeof(path)) { - res = -ENAMETOOLONG; - continue; - } - if ((res = weakjack_load_by_path(jack, path)) == 0) - break; + if (len >= sizeof(path)) { + res = -ENAMETOOLONG; + continue; } - } else { - res = weakjack_load_by_path(jack, lib); + pathlen = snprintf(path, sizeof(path), "%.*s/%s", (int) len, p, lib); + if (pathlen < 0 || (size_t) pathlen >= sizeof(path)) { + res = -ENAMETOOLONG; + continue; + } + if ((res = weakjack_load_by_path(jack, path)) == 0) + break; } return res; } diff --git a/src/pipewire/impl-module.c b/src/pipewire/impl-module.c index 22c8e91fa..d670f883a 100644 --- a/src/pipewire/impl-module.c +++ b/src/pipewire/impl-module.c @@ -154,6 +154,9 @@ pw_context_load_module(struct pw_context *context, NULL }; + while ((p = strstr(name, "../")) != NULL) + name = p + 3; + pw_log_info("%p: name:%s args:%s", context, name, args); module_dir = getenv("PIPEWIRE_MODULE_DIR"); diff --git a/src/pipewire/pipewire.c b/src/pipewire/pipewire.c index 4451fa525..bccd48f35 100644 --- a/src/pipewire/pipewire.c +++ b/src/pipewire/pipewire.c @@ -232,6 +232,9 @@ static struct spa_handle *load_spa_handle(const char *lib, if (lib == NULL) lib = sup->support_lib; + while ((p = strstr(lib, "../")) != NULL) + lib = p + 3; + pw_log_debug("load lib:'%s' factory-name:'%s'", lib, factory_name); plugin = NULL;