Fix: generate probe registration constructor as a C++ constuctor
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 6 Dec 2021 21:51:48 +0000 (16:51 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 9 Dec 2021 19:04:50 +0000 (14:04 -0500)
commit05bfa3dc3a6e6b2ece3686a5f384b6645c2a5010
treef802f3b5cd3e06797b5ff98537224a46baa970f4
parentd0cd72be0eacd90e56470e9cb954fa129997037e
Fix: generate probe registration constructor as a C++ constuctor

Observed issue
==============

Applications which transitively dlopen() a library which, in turn,
dlopen() providers crash when they are compiled with clang or
if LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP is defined.

  Core was generated by `././myapp.exe'.
  Program terminated with signal SIGSEGV, Segmentation fault.
  #0  0x00007fa94f860bc2 in check_event_provider (probe_desc=<optimized out>) at lttng-probes.c:153
  153 if (!check_type_provider(field->type)) {
  [Current thread is 1 (Thread 0x7fa94fcbc740 (LWP 511754))]

  (gdb) bt
  #0  0x00007fa94f860bc2 in check_event_provider (probe_desc=<optimized out>) at lttng-probes.c:153
  #1  lttng_ust_probe_register (desc=0x7fa94fe9dc80 <lttng_ust__probe_desc___embedded_sys>)
      at lttng-probes.c:242
  #2  0x00007fa94fe9ba3c in lttng_ust__tracepoints__ptrs_destroy ()
      at /usr/include/lttng/tracepoint.h:590
  #3  0x00007fa94fedfe2e in call_init () from /lib64/ld-linux-x86-64.so.2
  #4  0x00007fa94fedff1c in _dl_init () from /lib64/ld-linux-x86-64.so.2
  #5  0x00007fa94fdf7d45 in _dl_catch_exception () from /usr/lib/libc.so.6
  #6  0x00007fa94fee420a in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
  #7  0x00007fa94fdf7ce8 in _dl_catch_exception () from /usr/lib/libc.so.6
  #8  0x00007fa94fee39bb in _dl_open () from /lib64/ld-linux-x86-64.so.2
  #9  0x00007fa94fe8d36c in ?? () from /usr/lib/libdl.so.2
  #10 0x00007fa94fdf7ce8 in _dl_catch_exception () from /usr/lib/libc.so.6
  #11 0x00007fa94fdf7db3 in _dl_catch_error () from /usr/lib/libc.so.6
  #12 0x00007fa94fe8db99 in ?? () from /usr/lib/libdl.so.2
  #13 0x00007fa94fe8d3f8 in dlopen () from /usr/lib/libdl.so.2
  #14 0x00007fa94fecc647 in mon_constructeur () at mylib.cpp:20
  #15 0x00007fa94fedfe2e in call_init () from /lib64/ld-linux-x86-64.so.2
  #16 0x00007fa94fedff1c in _dl_init () from /lib64/ld-linux-x86-64.so.2
  #17 0x00007fa94fdf7d45 in _dl_catch_exception () from /usr/lib/libc.so.6
  #18 0x00007fa94fee420a in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
  #19 0x00007fa94fdf7ce8 in _dl_catch_exception () from /usr/lib/libc.so.6
  #20 0x00007fa94fee39bb in _dl_open () from /lib64/ld-linux-x86-64.so.2
  #21 0x00007fa94fe8d36c in ?? () from /usr/lib/libdl.so.2
  #22 0x00007fa94fdf7ce8 in _dl_catch_exception () from /usr/lib/libc.so.6
  #23 0x00007fa94fdf7db3 in _dl_catch_error () from /usr/lib/libc.so.6
  #24 0x00007fa94fe8db99 in ?? () from /usr/lib/libdl.so.2
  #25 0x00007fa94fe8d3f8 in dlopen () from /usr/lib/libdl.so.2
  #26 0x00005594f478c18c in main ()

Cause
=====

Building tracepoint instrumentation as C++ using clang causes
LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP to be defined due to a
compiler version detection problem addressed by another patch.

However, building with LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP
defined still results in the crash.

When LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP is defined, the
lttng_ust_event_field lttng_ust__event_fields__[...] structure is
initialized by dynamically-allocating field structures for the various
fields.

As the initialization can't be performed statically, it is performed at
run-time _after_ the execution of the library constructors has
completed.

Moreover, the generated initialization
function of the provider (lttng_ust__events_init__[...]) is declared as being a library
constructor. Hence, this causes it to run before the
tracepoint fields structures has a chance to be initialized.

This all results in a NULL pointer dereference during the validation of
the fields.

Solution
========

When building providers as C++, the initialization function is defined
as the constructor of a class. This class is, in turn, instantiated in
an anonymous namespace.

For the purposes of this patch, the use of an anonymous namespace is
equivalent to declaring the instance as 'static', but it is preferred in
C++11.

Known drawbacks
===============

None.

References
==========

A reproducer is available:
https://github.com/jgalar/ust-clang-reproducer

Problem initially reported on dotnet/runtime's issue tracker:
https://github.com/dotnet/runtime/issues/62398

Relevant LTTng-UST issue:
https://bugs.lttng.org/issues/1339

Fixes: #1339
Change-Id: I51cfbe74729bd45e2613a30bc8de17e08ea8233d
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/lttng/ust-compiler.h
include/lttng/ust-tracepoint-event.h
This page took 0.026295 seconds and 4 git commands to generate.