mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-19 17:00:36 +01:00
libnm/vpn: allow specifying non-absolute plugin name in VPN .name file
Since commit3dfbbb227e, 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. (cherry picked from commitca000cffbb)
This commit is contained in:
parent
e10f50400f
commit
5bc6e22528
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 shared 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