diff options
author | Thomas Haller <thaller@redhat.com> | 2016-04-18 18:19:04 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-04-19 13:47:42 +0200 |
commit | ca000cffbb9ef20c6dd965283df3f1babf0a7745 (patch) | |
tree | 972c5d4434d02c9f4e8b6ae52cc0c9dc47ea9ce8 | |
parent | cb22f025886ffdeca7dec3615e0e5cbb0fe2470b (diff) | |
download | NetworkManager-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.h | 9 | ||||
-rw-r--r-- | libnm-core/nm-vpn-editor-plugin.c | 104 | ||||
-rw-r--r-- | libnm-core/nm-vpn-plugin-info.c | 13 |
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; } |