mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-06 09:20:32 +01:00
libnm/vpn: allow specifying non-absolute plugin name in VPN .name file
Since commit 3dfbbb227e, 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.
This commit is contained in:
parent
cb22f02588
commit
ca000cffbb
3 changed files with 87 additions and 39 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue