summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2017-12-26 09:28:54 +0100
committerLubomir Rintel <lkundrak@v3.sk>2018-01-08 10:15:29 +0100
commitcd476e4dc922f0acfd65b02639032ee67339ad95 (patch)
treede3b396fe5a6ad5944c692ad4a953dc5b91bfcb9
parentda4c9e51a038279e261b896e5156308adaea4572 (diff)
core: load jansson on demand
Avoid using it if the symbols clash is detected.
-rw-r--r--Makefile.am12
-rw-r--r--config.h.meson3
-rw-r--r--configure.ac10
-rw-r--r--libnm-core/meson.build1
-rw-r--r--libnm-core/nm-jansson.c117
-rw-r--r--libnm-core/nm-jansson.h45
-rw-r--r--libnm-core/nm-utils.c81
-rw-r--r--meson.build14
8 files changed, 248 insertions, 35 deletions
diff --git a/Makefile.am b/Makefile.am
index c7b8a1b8f7..8584866405 100644
--- a/Makefile.am
+++ b/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)
diff --git a/config.h.meson b/config.h.meson
index 67de050b0e..704c0a48d2 100644
--- a/config.h.meson
+++ b/config.h.meson
@@ -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
diff --git a/configure.ac b/configure.ac
index f90a89d45d..141e07a390 100644
--- a/configure.ac
+++ b/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
diff --git a/libnm-core/meson.build b/libnm-core/meson.build
index 97040709f9..7aa85b1728 100644
--- a/libnm-core/meson.build
+++ b/libnm-core/meson.build
@@ -151,6 +151,7 @@ cflags = [
]
if enable_json_validation
+ libnm_core_sources += files('nm-jansson.c')
deps += jansson_dep
endif
diff --git a/libnm-core/nm-jansson.c b/libnm-core/nm-jansson.c
new file mode 100644
index 0000000000..154afa2749
--- /dev/null
+++ b/libnm-core/nm-jansson.c
@@ -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;
+}
diff --git a/libnm-core/nm-jansson.h b/libnm-core/nm-jansson.h
new file mode 100644
index 0000000000..d3e8285e8e
--- /dev/null
+++ b/libnm-core/nm-jansson.h
@@ -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
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index f845d14cdf..dbb7a99919 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -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
diff --git a/meson.build b/meson.build
index cc704a47a9..5a033dbd7f 100644
--- a/meson.build
+++ b/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())