From ca80d5127e56dd2ee056fdf3f4204017b78b89e0 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 29 Jun 2020 18:28:38 +0100 Subject: [PATCH] build: Add a symbol version to all exported symbols for glibc The --default-symver linker option attaches a default version definition (the SONAME) to every exported symbol. It is supported since at least GNU binutils 2.22 in 2011 (older versions not tested). With this version definition, newly-linked binaries that depend on the jansson shared library will refer to its symbols in a versioned form, preventing their references from being resolved to a symbol of the same name exported by json-c or json-glib if those libraries appear in dependency search order before jansson, which will usually result in a crash. This is necessary because ELF symbol resolution normally uses a single flat namespace, not a tree like Windows symbol resolution. At least one symbol (json_object_iter_next()) is exported by all three JSON libraries. Linking with -Bsymbolic is not enough to have this effect in all cases, because -Bsymbolic only affects symbol lookup within a shared object, for example when parse_json() calls json_decref(). It does not affect calls from external code into jansson, unless jansson was statically linked into the external caller. This change will also not prevent code that depends on json-c or json-glib from finding jansson's symbols and crashing; to prevent that, a corresponding change in json-c or json-glib would be needed. Adding a symbol-version is a backwards-compatible change, but once added, removing or changing the symbol-version would be an incompatible change that requires a SONAME bump. Resolves: https://github.com/akheron/jansson/issues/523 (when combined with an equivalent change to json-c). Signed-off-by: Simon McVittie --- CMakeLists.txt | 7 +++++++ configure.ac | 4 ++++ src/Makefile.am | 1 + 3 files changed, 12 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f8e7e84..02b9785 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,9 @@ if (HAS_NO_FORMAT_TRUNCATION) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format-truncation") endif() +include (CheckSymbolExists) +check_symbol_exists("__GLIBC__" "stdlib.h" LIBC_IS_GLIBC) + if (MSVC) # Turn off Microsofts "security" warnings. add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo" ) @@ -366,6 +369,10 @@ if(JANSSON_BUILD_SHARED_LIBS) ${JANSSON_HDR_PUBLIC} src/jansson.def) + if (LIBC_IS_GLIBC) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--default-symver") + endif() + set_target_properties(jansson PROPERTIES VERSION ${JANSSON_VERSION} SOVERSION ${JANSSON_SOVERSION}) diff --git a/configure.ac b/configure.ac index d923eef..3a4d187 100644 --- a/configure.ac +++ b/configure.ac @@ -137,6 +137,10 @@ fi AS_IF([test "x$with_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions]) AC_SUBST(JSON_BSYMBOLIC_LDFLAGS) +# Enable symbol versioning on GNU libc +JSON_SYMVER_LDFLAGS= +AC_CHECK_DECL([__GLIBC__], [JSON_SYMVER_LDFLAGS=-Wl,--default-symver]) +AC_SUBST([JSON_SYMVER_LDFLAGS]) AC_ARG_ENABLE([ossfuzzers], [AS_HELP_STRING([--enable-ossfuzzers], diff --git a/src/Makefile.am b/src/Makefile.am index 91280c8..c61d199 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,4 +26,5 @@ libjansson_la_LDFLAGS = \ -no-undefined \ -export-symbols-regex '^json_|^jansson_' \ -version-info 17:0:13 \ + @JSON_SYMVER_LDFLAGS@ \ @JSON_BSYMBOLIC_LDFLAGS@