summary refs log tree commit diff
path: root/src/contrib/nm-vpn-plugin-utils.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2025-02-12 13:46:50 +0100
committerMichael Biebl <biebl@debian.org>2025-02-12 13:46:50 +0100
commit8bdf070ff046f482f6eb5e2b15ebc216f5d1e3da (patch)
treef706478d189d54c6532e8863d4b0d5ff5575af60 /src/contrib/nm-vpn-plugin-utils.c
parent818258cf34b83fbc754633295e1052d4752d7b15 (diff)
New upstream version 1.51.90 upstream/1.51.90
Diffstat (limited to 'src/contrib/nm-vpn-plugin-utils.c')
-rw-r--r--src/contrib/nm-vpn-plugin-utils.c97
1 files changed, 58 insertions, 39 deletions
diff --git a/src/contrib/nm-vpn-plugin-utils.c b/src/contrib/nm-vpn-plugin-utils.c
index 32af40cf..a9407608 100644
--- a/src/contrib/nm-vpn-plugin-utils.c
+++ b/src/contrib/nm-vpn-plugin-utils.c
@@ -11,8 +11,47 @@
 
 /*****************************************************************************/
 
+char *
+nm_vpn_plugin_utils_get_editor_module_path(const char *module_name, GError **error)
+{
+    gs_free char *module_path = NULL;
+    gs_free char *dirname     = NULL;
+    Dl_info       plugin_info;
+
+    g_return_val_if_fail(module_name, NULL);
+    g_return_val_if_fail(!error || !*error, NULL);
+
+    /*
+     * Look for the editor from the same directory this plugin is in.
+     * Ideally, we'd get our .so name from the NMVpnEditorPlugin if it
+     * would just have a property with it...
+     */
+    if (!dladdr(nm_vpn_plugin_utils_load_editor, &plugin_info)) {
+        /* Really a "can not happen" scenario. */
+        g_set_error(error,
+                    NM_VPN_PLUGIN_ERROR,
+                    NM_VPN_PLUGIN_ERROR_FAILED,
+                    _("unable to get editor plugin name: %s"),
+                    dlerror());
+    }
+
+    dirname     = g_path_get_dirname(plugin_info.dli_fname);
+    module_path = g_build_filename(dirname, module_name, NULL);
+
+    if (!g_file_test(module_path, G_FILE_TEST_EXISTS)) {
+        g_set_error(error,
+                    G_FILE_ERROR,
+                    G_FILE_ERROR_NOENT,
+                    _("missing plugin file \"%s\""),
+                    module_path);
+        return NULL;
+    }
+
+    return g_steal_pointer(&module_path);
+}
+
 NMVpnEditor *
-nm_vpn_plugin_utils_load_editor(const char                   *module_name,
+nm_vpn_plugin_utils_load_editor(const char                   *module_path,
                                 const char                   *factory_name,
                                 NMVpnPluginUtilsEditorFactory editor_factory,
                                 NMVpnEditorPlugin            *editor_plugin,
@@ -21,48 +60,36 @@ nm_vpn_plugin_utils_load_editor(const char                   *module_name,
                                 GError                      **error)
 
 {
+    gs_free char *compat_module_path = NULL;
     static struct {
         gpointer factory;
         void    *dl_module;
-        char    *module_name;
+        char    *module_path;
         char    *factory_name;
     } cached = {0};
-    NMVpnEditor  *editor;
-    gs_free char *module_path = NULL;
-    gs_free char *dirname     = NULL;
-    Dl_info       plugin_info;
+    NMVpnEditor *editor;
 
-    g_return_val_if_fail(module_name, NULL);
+    g_return_val_if_fail(module_path, NULL);
     g_return_val_if_fail(factory_name && factory_name[0], NULL);
     g_return_val_if_fail(editor_factory, NULL);
     g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(editor_plugin), NULL);
     g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL);
     g_return_val_if_fail(!error || !*error, NULL);
 
-    if (!g_path_is_absolute(module_name)) {
-        /*
-         * Load an editor from the same directory this plugin is in.
-         * Ideally, we'd get our .so name from the NMVpnEditorPlugin if it
-         * would just have a property with it...
-         */
-        if (!dladdr(nm_vpn_plugin_utils_load_editor, &plugin_info)) {
-            /* Really a "can not happen" scenario. */
-            g_set_error(error,
-                        NM_VPN_PLUGIN_ERROR,
-                        NM_VPN_PLUGIN_ERROR_FAILED,
-                        _("unable to get editor plugin name: %s"),
-                        dlerror());
-        }
-
-        dirname     = g_path_get_dirname(plugin_info.dli_fname);
-        module_path = g_build_filename(dirname, module_name, NULL);
-    } else {
-        module_path = g_strdup(module_name);
+    if (!g_path_is_absolute(module_path)) {
+        /* This presumably means the VPN plugin factory() didn't verify that the plugin is there.
+         * Now it might be too late to do so. */
+        g_warning("VPN plugin bug: load_editor() argument not an absolute path. Continuing...");
+        compat_module_path = nm_vpn_plugin_utils_get_editor_module_path(module_path, error);
+        if (compat_module_path == NULL)
+            return NULL;
+        else
+            module_path = compat_module_path;
     }
 
-    /* we really expect this function to be called with unchanging @module_name
+    /* we really expect this function to be called with unchanging @module_path
      * and @factory_name. And we only want to load the module once, hence it would
-     * be more complicated to accept changing @module_name/@factory_name arguments.
+     * be more complicated to accept changing @module_path/@factory_name arguments.
      *
      * The reason for only loading once is that due to glib types, we cannot create a
      * certain type-name more then once, so loading the same module or another version
@@ -70,12 +97,12 @@ nm_vpn_plugin_utils_load_editor(const char                   *module_name,
      * name.
      *
      * Only support loading once, any future calls will reuse the handle. To simplify
-     * that, we enforce that the @factory_name and @module_name is the same. */
+     * that, we enforce that the @factory_name and @module_path is the same. */
     if (cached.factory) {
         g_return_val_if_fail(cached.dl_module, NULL);
         g_return_val_if_fail(cached.factory_name && nm_streq0(cached.factory_name, factory_name),
                              NULL);
-        g_return_val_if_fail(cached.module_name && nm_streq0(cached.module_name, module_name),
+        g_return_val_if_fail(cached.module_path && nm_streq0(cached.module_path, module_path),
                              NULL);
     } else {
         gpointer factory;
@@ -83,14 +110,6 @@ nm_vpn_plugin_utils_load_editor(const char                   *module_name,
 
         dl_module = dlopen(module_path, RTLD_LAZY | RTLD_LOCAL);
         if (!dl_module) {
-            if (!g_file_test(module_path, G_FILE_TEST_EXISTS)) {
-                g_set_error(error,
-                            G_FILE_ERROR,
-                            G_FILE_ERROR_NOENT,
-                            _("missing plugin file \"%s\""),
-                            module_path);
-                return NULL;
-            }
             g_set_error(error,
                         NM_VPN_PLUGIN_ERROR,
                         NM_VPN_PLUGIN_ERROR_FAILED,
@@ -117,7 +136,7 @@ nm_vpn_plugin_utils_load_editor(const char                   *module_name,
          * Thus we just leak the dl_module handle indefinitely. */
         cached.factory      = factory;
         cached.dl_module    = dl_module;
-        cached.module_name  = g_strdup(module_name);
+        cached.module_path  = g_strdup(module_path);
         cached.factory_name = g_strdup(factory_name);
     }