mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-01 13:55:36 +00:00
core: load jansson on demand
Avoid using it if the symbols clash is detected.
This commit is contained in:
parent
da4c9e51a0
commit
cd476e4dc9
12
Makefile.am
12
Makefile.am
|
@ -516,6 +516,14 @@ libnm_core_lib_c_real = \
|
|||
libnm-core/nm-utils.c \
|
||||
libnm-core/nm-vpn-editor-plugin.c \
|
||||
libnm-core/nm-vpn-plugin-info.c
|
||||
|
||||
if WITH_JSON_VALIDATION
|
||||
libnm_core_lib_h_priv += \
|
||||
libnm-core/nm-jansson.h
|
||||
libnm_core_lib_c_real += \
|
||||
libnm-core/nm-jansson.c
|
||||
endif
|
||||
|
||||
libnm_core_lib_c_mkenums = \
|
||||
libnm-core/nm-core-enum-types.c
|
||||
|
||||
|
@ -596,10 +604,6 @@ libnm_core_libnm_core_la_LIBADD = \
|
|||
$(UUID_LIBS) \
|
||||
$(LIBUDEV_LIBS)
|
||||
|
||||
if WITH_JSON_VALIDATION
|
||||
libnm_core_libnm_core_la_LIBADD += $(JANSSON_LIBS)
|
||||
endif
|
||||
|
||||
libnm_core_libnm_core_la_LDFLAGS = \
|
||||
$(CODE_COVERAGE_LDFLAGS)
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@
|
|||
/* Define to path of iptables binary */
|
||||
#mesondefine IPTABLES_PATH
|
||||
|
||||
/* Define to path to the Jansson shared library */
|
||||
#mesondefine JANSSON_SONAME
|
||||
|
||||
/* Define to path of the kernel firmware directory */
|
||||
#mesondefine KERNEL_FIRMWARE_DIR
|
||||
|
||||
|
|
10
configure.ac
10
configure.ac
|
@ -629,12 +629,20 @@ PKG_CHECK_MODULES(UUID, uuid)
|
|||
PKG_CHECK_MODULES(JANSSON, [jansson], [have_jansson=yes], [have_jansson=no])
|
||||
if test "$have_jansson" = "yes"; then
|
||||
AC_DEFINE(WITH_JANSSON, 1, [Define if JANSSON is enabled])
|
||||
|
||||
AC_CHECK_TOOLS(READELF, [eu-readelf readelf])
|
||||
JANSSON_LIBDIR=`$PKG_CONFIG --variable=libdir jansson`
|
||||
JANSSON_SONAME=`$READELF -d $JANSSON_LIBDIR/libjansson.so |sed -n 's/.*SONAME.*\[[\([^]]*\)]]/\1/p'`
|
||||
|
||||
if test "$JANSSON_SONAME" = ""; then
|
||||
AC_MSG_ERROR(Unable to locate the Jansson library)
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(JANSSON_SONAME, "$JANSSON_SONAME", [Define to path to the Jansson shared library])
|
||||
else
|
||||
AC_DEFINE(WITH_JANSSON, 0, [Define if JANSSON is enabled])
|
||||
fi
|
||||
AM_CONDITIONAL(WITH_JANSSON, test "${have_jansson}" = "yes")
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(LIBTEAMDCTL, [libteamdctl >= 1.9], [have_teamdctl=yes],[have_teamdctl=no])
|
||||
if test "$have_jansson" = "yes" -a "$have_teamdctl" = "yes"; then
|
||||
have_team_prereq=yes
|
||||
|
|
|
@ -151,6 +151,7 @@ cflags = [
|
|||
]
|
||||
|
||||
if enable_json_validation
|
||||
libnm_core_sources += files('nm-jansson.c')
|
||||
deps += jansson_dep
|
||||
endif
|
||||
|
||||
|
|
117
libnm-core/nm-jansson.c
Normal file
117
libnm-core/nm-jansson.c
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright 2017, 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <link.h>
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#define NM_JAONSSON_C
|
||||
#include "nm-jansson.h"
|
||||
|
||||
void *_nm_jansson_json_object_iter_value;
|
||||
void *_nm_jansson_json_object_key_to_iter;
|
||||
void *_nm_jansson_json_integer;
|
||||
void *_nm_jansson_json_object_del;
|
||||
void *_nm_jansson_json_array_get;
|
||||
void *_nm_jansson_json_array_size;
|
||||
void *_nm_jansson_json_array_append_new;
|
||||
void *_nm_jansson_json_string;
|
||||
void *_nm_jansson_json_object_iter_next;
|
||||
void *_nm_jansson_json_loads;
|
||||
void *_nm_jansson_json_dumps;
|
||||
void *_nm_jansson_json_object_iter_key;
|
||||
void *_nm_jansson_json_object;
|
||||
void *_nm_jansson_json_object_get;
|
||||
void *_nm_jansson_json_array;
|
||||
void *_nm_jansson_json_false;
|
||||
void *_nm_jansson_json_delete;
|
||||
void *_nm_jansson_json_true;
|
||||
void *_nm_jansson_json_object_size;
|
||||
void *_nm_jansson_json_object_set_new;
|
||||
void *_nm_jansson_json_object_iter;
|
||||
void *_nm_jansson_json_integer_value;
|
||||
void *_nm_jansson_json_string_value;
|
||||
|
||||
#define TRY_BIND_SYMBOL(symbol) \
|
||||
G_STMT_START { \
|
||||
void *sym = dlsym (handle, #symbol); \
|
||||
if (_nm_jansson_ ## symbol && sym != _nm_jansson_ ## symbol) \
|
||||
return FALSE; \
|
||||
_nm_jansson_ ## symbol = sym; \
|
||||
} G_STMT_END
|
||||
|
||||
static gboolean
|
||||
bind_symbols (void *handle)
|
||||
{
|
||||
TRY_BIND_SYMBOL (json_object_iter_value);
|
||||
TRY_BIND_SYMBOL (json_object_key_to_iter);
|
||||
TRY_BIND_SYMBOL (json_integer);
|
||||
TRY_BIND_SYMBOL (json_object_del);
|
||||
TRY_BIND_SYMBOL (json_array_get);
|
||||
TRY_BIND_SYMBOL (json_array_size);
|
||||
TRY_BIND_SYMBOL (json_array_append_new);
|
||||
TRY_BIND_SYMBOL (json_string);
|
||||
TRY_BIND_SYMBOL (json_object_iter_next);
|
||||
TRY_BIND_SYMBOL (json_loads);
|
||||
TRY_BIND_SYMBOL (json_dumps);
|
||||
TRY_BIND_SYMBOL (json_object_iter_key);
|
||||
TRY_BIND_SYMBOL (json_object);
|
||||
TRY_BIND_SYMBOL (json_object_get);
|
||||
TRY_BIND_SYMBOL (json_array);
|
||||
TRY_BIND_SYMBOL (json_false);
|
||||
TRY_BIND_SYMBOL (json_delete);
|
||||
TRY_BIND_SYMBOL (json_true);
|
||||
TRY_BIND_SYMBOL (json_object_size);
|
||||
TRY_BIND_SYMBOL (json_object_set_new);
|
||||
TRY_BIND_SYMBOL (json_object_iter);
|
||||
TRY_BIND_SYMBOL (json_integer_value);
|
||||
TRY_BIND_SYMBOL (json_string_value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_jansson_load (void)
|
||||
{
|
||||
static enum {
|
||||
UNKNOWN,
|
||||
AVAILABLE,
|
||||
MISSING,
|
||||
} state = UNKNOWN;
|
||||
void *handle;
|
||||
|
||||
if (G_LIKELY (state != UNKNOWN))
|
||||
goto out;
|
||||
|
||||
/* First just resolve the symbols to see if there's a conflict already. */
|
||||
if (!bind_symbols (RTLD_DEFAULT))
|
||||
goto out;
|
||||
|
||||
handle = dlopen (JANSSON_SONAME, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND);
|
||||
if (!handle)
|
||||
goto out;
|
||||
|
||||
/* Now do the actual binding. */
|
||||
if (!bind_symbols (handle))
|
||||
goto out;
|
||||
|
||||
state = AVAILABLE;
|
||||
out:
|
||||
return state == AVAILABLE;
|
||||
}
|
45
libnm-core/nm-jansson.h
Normal file
45
libnm-core/nm-jansson.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright 2017, 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
gboolean nm_jansson_load (void);
|
||||
|
||||
#ifndef NM_JAONSSON_C
|
||||
#define json_object_iter_value (*_nm_jansson_json_object_iter_value)
|
||||
#define json_object_key_to_iter (*_nm_jansson_json_object_key_to_iter)
|
||||
#define json_integer (*_nm_jansson_json_integer)
|
||||
#define json_object_del (*_nm_jansson_json_object_del)
|
||||
#define json_array_get (*_nm_jansson_json_array_get)
|
||||
#define json_array_size (*_nm_jansson_json_array_size)
|
||||
#define json_array_append_new (*_nm_jansson_json_array_append_new)
|
||||
#define json_string (*_nm_jansson_json_string)
|
||||
#define json_object_iter_next (*_nm_jansson_json_object_iter_next)
|
||||
#define json_loads (*_nm_jansson_json_loads)
|
||||
#define json_dumps (*_nm_jansson_json_dumps)
|
||||
#define json_object_iter_key (*_nm_jansson_json_object_iter_key)
|
||||
#define json_object (*_nm_jansson_json_object)
|
||||
#define json_object_get (*_nm_jansson_json_object_get)
|
||||
#define json_array (*_nm_jansson_json_array)
|
||||
#define json_false (*_nm_jansson_json_false)
|
||||
#define json_delete (*_nm_jansson_json_delete)
|
||||
#define json_true (*_nm_jansson_json_true)
|
||||
#define json_object_size (*_nm_jansson_json_object_size)
|
||||
#define json_object_set_new (*_nm_jansson_json_object_set_new)
|
||||
#define json_object_iter (*_nm_jansson_json_object_iter)
|
||||
#define json_integer_value (*_nm_jansson_json_integer_value)
|
||||
#define json_string_value (*_nm_jansson_json_string_value)
|
||||
#endif
|
|
@ -35,6 +35,10 @@
|
|||
#include <net/if.h>
|
||||
#include <linux/pkt_sched.h>
|
||||
|
||||
#if WITH_JSON_VALIDATION
|
||||
#include "nm-jansson.h"
|
||||
#endif
|
||||
|
||||
#include "nm-utils/nm-jansson.h"
|
||||
#include "nm-utils/nm-enum-utils.h"
|
||||
#include "nm-common-macros.h"
|
||||
|
@ -4852,6 +4856,41 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_nm_utils_is_json_object_no_validation (const char *str, GError **error)
|
||||
{
|
||||
if (str) {
|
||||
/* libjansson also requires only utf-8 encoding. */
|
||||
if (!g_utf8_validate (str, -1, NULL)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("not valid utf-8"));
|
||||
return FALSE;
|
||||
}
|
||||
while (g_ascii_isspace (str[0]))
|
||||
str++;
|
||||
}
|
||||
|
||||
/* do some very basic validation to see if this might be a JSON object. */
|
||||
if (str[0] == '{') {
|
||||
gsize l;
|
||||
|
||||
l = strlen (str) - 1;
|
||||
while (l > 0 && g_ascii_isspace (str[l]))
|
||||
l--;
|
||||
|
||||
if (str[l] == '}')
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("is not a JSON object"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if WITH_JSON_VALIDATION
|
||||
|
||||
static void
|
||||
|
@ -5298,6 +5337,9 @@ nm_utils_is_json_object (const char *str, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_jansson_load ())
|
||||
return _nm_utils_is_json_object_no_validation (str, error);
|
||||
|
||||
json = json_loads (str, JSON_REJECT_DUPLICATES, &jerror);
|
||||
if (!json) {
|
||||
g_set_error (error,
|
||||
|
@ -5339,6 +5381,8 @@ _nm_utils_team_config_equal (const char *conf1,
|
|||
|
||||
if (nm_streq0 (conf1, conf2))
|
||||
return TRUE;
|
||||
else if (!nm_jansson_load ())
|
||||
return FALSE;
|
||||
|
||||
/* A NULL configuration is equivalent to default value '{}' */
|
||||
json1 = json_loads (conf1 ?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
||||
|
@ -5396,6 +5440,9 @@ _nm_utils_team_config_get (const char *conf,
|
|||
if (!key)
|
||||
return NULL;
|
||||
|
||||
if (!nm_jansson_load ())
|
||||
return NULL;
|
||||
|
||||
json = json_loads (conf ?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
||||
|
||||
/* Invalid json in conf */
|
||||
|
@ -5503,6 +5550,9 @@ _nm_utils_team_config_set (char **conf,
|
|||
|
||||
g_return_val_if_fail (key, FALSE);
|
||||
|
||||
if (!nm_jansson_load ())
|
||||
return FALSE;
|
||||
|
||||
json = json_loads (*conf?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
||||
if (!json)
|
||||
return FALSE;
|
||||
|
@ -5620,19 +5670,6 @@ nm_utils_is_json_object (const char *str, GError **error)
|
|||
{
|
||||
g_return_val_if_fail (!error || !*error, FALSE);
|
||||
|
||||
if (str) {
|
||||
/* libjansson also requires only utf-8 encoding. */
|
||||
if (!g_utf8_validate (str, -1, NULL)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("not valid utf-8"));
|
||||
return FALSE;
|
||||
}
|
||||
while (g_ascii_isspace (str[0]))
|
||||
str++;
|
||||
}
|
||||
|
||||
if (!str || !str[0]) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
|
@ -5641,23 +5678,7 @@ nm_utils_is_json_object (const char *str, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* do some very basic validation to see if this might be a JSON object. */
|
||||
if (str[0] == '{') {
|
||||
gsize l;
|
||||
|
||||
l = strlen (str) - 1;
|
||||
while (l > 0 && g_ascii_isspace (str[l]))
|
||||
l--;
|
||||
|
||||
if (str[l] == '}')
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("is not a JSON object"));
|
||||
return FALSE;
|
||||
return _nm_utils_is_json_object_no_validation (str, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
14
meson.build
14
meson.build
|
@ -179,6 +179,20 @@ libnl_dep = dependency('libnl-3.0', version: '>= 3.2.8', required: false)
|
|||
jansson_dep = dependency('jansson', required: false)
|
||||
config_h.set10('WITH_JANSSON', jansson_dep.found())
|
||||
|
||||
if jansson_dep.found()
|
||||
jansson_libdir = jansson_dep.get_pkgconfig_variable('libdir')
|
||||
readelf = find_program('readelf', 'readelf')
|
||||
res = run_command(readelf, '-d', join_paths(jansson_libdir, 'libjansson.so'))
|
||||
jansson_soname = ''
|
||||
foreach line: res.stdout().split('\n')
|
||||
if line.strip().contains('SONAME')
|
||||
jansson_soname = line.split('[')[1].split(']')[0]
|
||||
endif
|
||||
endforeach
|
||||
assert(jansson_soname != '', 'Unable to determine Jansson SONAME')
|
||||
config_h.set_quoted('JANSSON_SONAME', jansson_soname)
|
||||
endif
|
||||
|
||||
libsystemd_dep = dependency('libsystemd', version: '>= 209', required: false)
|
||||
config_h.set10('HAVE_LIBSYSTEMD', libsystemd_dep.found())
|
||||
|
||||
|
|
Loading…
Reference in a new issue