summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-04-18 18:19:04 +0200
committerThomas Haller <thaller@redhat.com>2016-04-19 13:47:42 +0200
commitca000cffbb9ef20c6dd965283df3f1babf0a7745 (patch)
tree972c5d4434d02c9f4e8b6ae52cc0c9dc47ea9ce8
parentcb22f025886ffdeca7dec3615e0e5cbb0fe2470b (diff)
downloadNetworkManager-ca000cffbb9ef20c6dd965283df3f1babf0a7745.tar.gz
libnm/vpn: allow specifying non-absolute plugin name in VPN .name file
Since commit 3dfbbb227e82b47973f612b6b031d8d591727436, we enforce that the plugin path in the .name file is absolute and we perform several checks on the file before loading it (ownership, etc). Relax that, to also allow libray names without path component. In that case, g_module_open()/dlopen() will search for a library in various search paths. This allows, to omit absolute paths in the .name file. The latter is problematic, because by default we install the .name file in the architecture independent location /usr/lib/NetworkManager. As such, it should not contain paths to architecture dependent libraries. With this change, a .name file can contain only the library name and it will be loaded using the usual mechanism. However, specifying absolute paths is still possible and works same as before, including checking file permissions. As such, distributions probably should package the VPN plugins to have no path in the .name file. On the other hand, a user compiling from source probably wants to specify an absolute path. The reason is, that the user probably doesn't build the plugin for multiple achitectures and that way, he can install the plugin in a separate (private) prefix.
-rw-r--r--libnm-core/nm-core-internal.h9
-rw-r--r--libnm-core/nm-vpn-editor-plugin.c104
-rw-r--r--libnm-core/nm-vpn-plugin-info.c13
3 files changed, 87 insertions, 39 deletions
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 082ebc9e28..8d97b066ee 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -72,6 +72,7 @@
#include "nm-utils.h"
#include "nm-vpn-dbus-interface.h"
#include "nm-core-types-internal.h"
+#include "nm-vpn-editor-plugin.h"
/* NM_SETTING_COMPARE_FLAG_INFERRABLE: check whether a device-generated
* connection can be replaced by a already-defined connection. This flag only
@@ -245,6 +246,14 @@ GSList *_nm_vpn_plugin_info_list_load_dir (const char *dirname,
NMUtilsCheckFilePredicate check_file,
gpointer user_data);
+NMVpnEditorPlugin * _nm_vpn_editor_plugin_load (const char *plugin_filename,
+ gboolean force_absolute_path,
+ const char *check_service,
+ int check_owner,
+ NMUtilsCheckFilePredicate check_file,
+ gpointer user_data,
+ GError **error);
+
/***********************************************************/
typedef struct {
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c
index e1c2f450ef..32f6cbcdde 100644
--- a/libnm-core/nm-vpn-editor-plugin.c
+++ b/libnm-core/nm-vpn-editor-plugin.c
@@ -71,56 +71,55 @@ nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface)
/*********************************************************************/
-/**
- * nm_vpn_editor_plugin_load_from_file:
- * @plugin_filename: The path to the share library to load.
- * The path must be an absolute filename to an existing file.
- * @check_service: if not-null, check that the loaded plugin advertises
- * the given service.
- * @check_owner: if non-negative, check whether the file is owned
- * by UID @check_owner or by root. In this case also check that
- * the file is not writable by anybody else.
- * @check_file: (scope call): optional callback to validate the file prior to
- * loading the shared library.
- * @user_data: user data for @check_file
- * @error: on failure the error reason.
- *
- * Load the shared libary @plugin_filename and create a new
- * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory
- * function.
- *
- * Returns: (transfer full): a new plugin instance or %NULL on error.
- *
- * Since: 1.2
- */
NMVpnEditorPlugin *
-nm_vpn_editor_plugin_load_from_file (const char *plugin_filename,
- const char *check_service,
- int check_owner,
- NMUtilsCheckFilePredicate check_file,
- gpointer user_data,
- GError **error)
+_nm_vpn_editor_plugin_load (const char *plugin_filename,
+ gboolean force_absolute_filename,
+ const char *check_service,
+ int check_owner,
+ NMUtilsCheckFilePredicate check_file,
+ gpointer user_data,
+ GError **error)
{
GModule *module = NULL;
gs_free_error GError *local = NULL;
NMVpnEditorPluginFactory factory = NULL;
NMVpnEditorPlugin *editor_plugin = NULL;
+ gboolean search_lib = FALSE;
g_return_val_if_fail (plugin_filename && *plugin_filename, NULL);
+ if ( !force_absolute_filename
+ && !strchr (plugin_filename, '/')
+ && !g_str_has_suffix (plugin_filename, ".la")) {
+ /* we allow omitting the (absolute) path.
+ *
+ * If the @plugin_filename contains no '/', we skip any checks
+ * for the file and pass it directly to g_module_open()/dlopen().
+ * One exception is that we don't allow for the "la" suffix. The
+ * reason is that g_module_open() interprets files with this extension
+ * special and we don't want that. */
+ search_lib = TRUE;
+ }
+
/* _nm_utils_check_module_file() fails with ENOENT if the plugin file
* does not exist. That is relevant, because nm-applet checks for that. */
- if (_nm_utils_check_module_file (plugin_filename,
- check_owner,
- check_file,
- user_data,
- &local))
+ if ( search_lib
+ || _nm_utils_check_module_file (plugin_filename,
+ check_owner,
+ check_file,
+ user_data,
+ &local))
module = g_module_open (plugin_filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
if (!module) {
if (local) {
g_propagate_error (error, local);
local = NULL;
+ } else if (search_lib) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ G_FILE_ERROR_NOENT,
+ _("Plugin does not exist (%s)"), plugin_filename);
} else {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
@@ -197,6 +196,45 @@ nm_vpn_editor_plugin_load_from_file (const char *plugin_filename,
return editor_plugin;
}
+/**
+ * nm_vpn_editor_plugin_load_from_file:
+ * @plugin_filename: The path to the share library to load.
+ * The path must be an absolute filename to an existing file.
+ * @check_service: if not-null, check that the loaded plugin advertises
+ * the given service.
+ * @check_owner: if non-negative, check whether the file is owned
+ * by UID @check_owner or by root. In this case also check that
+ * the file is not writable by anybody else.
+ * @check_file: (scope call): optional callback to validate the file prior to
+ * loading the shared library.
+ * @user_data: user data for @check_file
+ * @error: on failure the error reason.
+ *
+ * Load the shared libary @plugin_filename and create a new
+ * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory
+ * function.
+ *
+ * Returns: (transfer full): a new plugin instance or %NULL on error.
+ *
+ * Since: 1.2
+ */
+NMVpnEditorPlugin *
+nm_vpn_editor_plugin_load_from_file (const char *plugin_filename,
+ const char *check_service,
+ int check_owner,
+ NMUtilsCheckFilePredicate check_file,
+ gpointer user_data,
+ GError **error)
+{
+ return _nm_vpn_editor_plugin_load (plugin_filename,
+ TRUE,
+ check_service,
+ check_owner,
+ check_file,
+ user_data,
+ error);
+}
+
/*********************************************************************/
/**
diff --git a/libnm-core/nm-vpn-plugin-info.c b/libnm-core/nm-vpn-plugin-info.c
index 2e6275e341..6c77f3c142 100644
--- a/libnm-core/nm-vpn-plugin-info.c
+++ b/libnm-core/nm-vpn-plugin-info.c
@@ -752,12 +752,13 @@ nm_vpn_plugin_info_load_editor_plugin (NMVpnPluginInfo *self, GError **error)
}
priv->editor_plugin_loaded = TRUE;
- priv->editor_plugin = nm_vpn_editor_plugin_load_from_file (plugin_filename,
- priv->service,
- getuid (),
- NULL,
- NULL,
- error);
+ priv->editor_plugin = _nm_vpn_editor_plugin_load (plugin_filename,
+ FALSE,
+ priv->service,
+ getuid (),
+ NULL,
+ NULL,
+ error);
return priv->editor_plugin;
}