Detect unsupported use of .so.0 and .so.1 libraries within same process
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 27 Apr 2021 16:13:04 +0000 (12:13 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 14 May 2021 21:03:37 +0000 (17:03 -0400)
Abort process if unsupported use of liblttng-ust and
liblttng-ust-tracepoint .so.0 vs .so.1 within the same process
is detected.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I2842ec43bf8840ddf88e0dd04bddb4c9e04e3a04

src/lib/lttng-ust-tracepoint/tracepoint.c
src/lib/lttng-ust/lttng-ust-comm.c

index 38d57cec626c8181b86bf9acf48bfb3f2187ec13..12bc561c3342693cbdafbefac0a87612b5852981 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdint.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <dlfcn.h>
 
 #include <urcu/arch.h>
 #include <lttng/urcu/urcu-ust.h>
@@ -607,6 +608,39 @@ static void tracepoint_release_queue_add_old_probes(void *old)
        }
 }
 
+/*
+ * Use a symbol of the previous ABI to detect if liblttng-ust-tracepoint.so.0
+ * is loaded in the current process.
+ */
+#define LTTNG_UST_TRACEPOINT_SONAME_0_SYM      "tracepoint_unregister_lib"
+
+static
+void lttng_ust_tracepoint_check_soname_0(void)
+{
+       if (!dlsym(RTLD_DEFAULT, LTTNG_UST_TRACEPOINT_SONAME_0_SYM))
+               return;
+
+       CRIT("Incompatible library ABIs detected within the same process. "
+               "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+               "The detection was triggered by lookup of ABI 0 symbol \"%s\" in the Global Symbol Table\n",
+               LTTNG_UST_TRACEPOINT_SONAME_0_SYM);
+}
+
+/*
+ * Expose a canary symbol of the previous ABI to ensure we catch uses of a
+ * liblttng-ust-tracepoint.so.0 dlopen'd after .so.1 has been loaded. Use a
+ * different symbol than the detection code to ensure we don't detect ourself.
+ */
+int tracepoint_register_lib(void *arg0 __attribute__((unused)), int arg1 __attribute__((unused)));
+int tracepoint_register_lib(void *arg0 __attribute__((unused)), int arg1 __attribute__((unused)))
+{
+       CRIT("Incompatible library ABIs detected within the same process. "
+               "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+               "The detection was triggered by canary symbol \"%s\"\n", __func__);
+
+       return -1;
+}
+
 /**
  * lttng_ust_tracepoint_provider_register -  Connect a probe to a tracepoint
  * @name: tracepoint provider name
@@ -623,6 +657,14 @@ int lttng_ust_tracepoint_provider_register(const char *provider_name, const char
        void *old;
        int ret = 0;
 
+       /*
+        * Check if we find a symbol of the previous ABI in the current process
+        * as different ABIs of liblttng-ust can't co-exist in a process. If we
+        * do so, emit a critical log message which will also abort if the
+        * LTTNG_UST_ABORT_ON_CRITICAL environment variable is set.
+        */
+       lttng_ust_tracepoint_check_soname_0();
+
        DBG("Registering probe to tracepoint \"%s:%s\"", provider_name, event_name);
 
        pthread_mutex_lock(&tracepoint_mutex);
index 5330e5c2a0c9ed2c6e63170203cc862d80199075..f180c3bc8277874ddd673954b1e3bf8467b7e95a 100644 (file)
@@ -2100,6 +2100,37 @@ void lttng_ust_libc_wrapper_malloc_ctor(void)
 {
 }
 
+/*
+ * Use a symbol of the previous ABI to detect if liblttng-ust.so.0 is loaded in
+ * the current process.
+ */
+#define LTTNG_UST_SONAME_0_SYM "ltt_probe_register"
+
+static
+void lttng_ust_check_soname_0(void)
+{
+       if (!dlsym(RTLD_DEFAULT, LTTNG_UST_SONAME_0_SYM))
+               return;
+
+       CRIT("Incompatible library ABIs detected within the same process. "
+               "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+               "The detection was triggered by lookup of ABI 0 symbol \"%s\" in the Global Symbol Table\n",
+               LTTNG_UST_SONAME_0_SYM);
+}
+
+/*
+ * Expose a canary symbol of the previous ABI to ensure we catch uses of a
+ * liblttng-ust.so.0 dlopen'd after .so.1 has been loaded. Use a different
+ * symbol than the detection code to ensure we don't detect ourself.
+ */
+void init_usterr(void);
+void init_usterr(void)
+{
+       CRIT("Incompatible library ABIs detected within the same process. "
+               "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+               "The detection was triggered by canary symbol \"%s\"\n", __func__);
+}
+
 /*
  * sessiond monitoring thread: monitor presence of global and per-user
  * sessiond by polling the application common named pipe.
@@ -2129,6 +2160,14 @@ void lttng_ust_ctor(void)
 
        lttng_ust_loaded = 1;
 
+       /*
+        * Check if we find a symbol of the previous ABI in the current process
+        * as different ABIs of liblttng-ust can't co-exist in a process. If we
+        * do so, emit a critical log message which will also abort if the
+        * LTTNG_UST_ABORT_ON_CRITICAL environment variable is set.
+        */
+       lttng_ust_check_soname_0();
+
        /*
         * We need to ensure that the liblttng-ust library is not unloaded to avoid
         * the unloading of code used by the ust_listener_threads as we can not
@@ -2147,6 +2186,8 @@ void lttng_ust_ctor(void)
        handle = dlopen(LTTNG_UST_LIB_SONAME, RTLD_LAZY | RTLD_NODELETE);
        if (!handle) {
                ERR("dlopen of liblttng-ust shared library (%s).", LTTNG_UST_LIB_SONAME);
+       } else {
+               DBG("dlopened liblttng-ust shared library (%s).", LTTNG_UST_LIB_SONAME);
        }
 
        /*
This page took 0.027556 seconds and 4 git commands to generate.