#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
+#include <dlfcn.h>
#include <urcu/compiler.h>
#include <urcu/tls-compat.h>
#include <urcu/system.h>
DEL_FD_FROM_SET(fd, lttng_fd_set);
}
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+static int (*__lttng_ust_safe_close_fd)(int fd, int (*close_cb)(int fd)) = NULL;
+
+static
+void *_init_lttng_ust_safe_close_fd(void)
+{
+ if (__lttng_ust_safe_close_fd == NULL) {
+ __lttng_ust_safe_close_fd = dlsym(RTLD_DEFAULT, "lttng_ust_safe_close_fd");
+
+ if (__lttng_ust_safe_close_fd == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __lttng_ust_safe_close_fd;
+}
+
+static int lttng_ust_safe_close_fd_chain(int fd, int (*close_cb)(int fd))
+{
+ if (_init_lttng_ust_safe_close_fd()) {
+ /* Chain on ust-2.12 preload */
+ return __lttng_ust_safe_close_fd(fd, close_cb);
+ } else {
+ /* Fallback to libc symbol */
+ return close_cb(fd);
+ }
+}
+#endif
+
/*
* Interface allowing applications to close arbitrary file descriptors.
* We check if it is owned by lttng-ust, and return -1, errno=EBADF
* If called from lttng-ust, we directly call close without
* validating whether the FD is part of the tracked set.
*/
- if (URCU_TLS(ust_fd_mutex_nest))
+ if (URCU_TLS(ust_fd_mutex_nest)) {
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ return lttng_ust_safe_close_fd_chain(fd, close_cb);
+#else
return close_cb(fd);
+#endif
+ }
lttng_ust_lock_fd_tracker();
if (IS_FD_VALID(fd) && IS_FD_SET(fd, lttng_fd_set)) {
ret = -1;
errno = EBADF;
} else {
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ ret = lttng_ust_safe_close_fd_chain(fd, close_cb);
+#else
ret = close_cb(fd);
+#endif
}
lttng_ust_unlock_fd_tracker();
return ret;
}
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+static int (*__lttng_ust_safe_fclose_stream)(FILE *stream, int (*fclose_cb)(FILE *stream)) = NULL;
+
+static
+void *_init_lttng_ust_safe_fclose_stream(void)
+{
+ if (__lttng_ust_safe_fclose_stream == NULL) {
+ __lttng_ust_safe_fclose_stream = dlsym(RTLD_DEFAULT, "lttng_ust_safe_fclose_stream");
+
+ if (__lttng_ust_safe_fclose_stream == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __lttng_ust_safe_fclose_stream;
+}
+
+static int lttng_ust_safe_fclose_stream_chain(FILE *stream, int (*fclose_cb)(FILE *stream))
+{
+ if (_init_lttng_ust_safe_fclose_stream()) {
+ /* Chain on ust-2.12 preload */
+ return __lttng_ust_safe_fclose_stream(stream, fclose_cb);
+ } else {
+ /* Fallback to libc symbol */
+ return fclose_cb(stream);
+ }
+}
+#endif
+
/*
* Interface allowing applications to close arbitrary streams.
* We check if it is owned by lttng-ust, and return -1, errno=EBADF
* If called from lttng-ust, we directly call fclose without
* validating whether the FD is part of the tracked set.
*/
- if (URCU_TLS(ust_fd_mutex_nest))
+ if (URCU_TLS(ust_fd_mutex_nest)) {
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ return lttng_ust_safe_fclose_stream_chain(stream, fclose_cb);
+#else
return fclose_cb(stream);
+#endif
+ }
fd = fileno(stream);
ret = -1;
errno = EBADF;
} else {
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ ret = lttng_ust_safe_fclose_stream_chain(stream, fclose_cb);
+#else
ret = fclose_cb(stream);
+#endif
}
lttng_ust_unlock_fd_tracker();
#include <lttng/ust-fork.h>
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+static int (*__ust_before_fork)(sigset_t *save_sigset) = NULL;
+static int (*__ust_after_fork_child)(sigset_t *restore_sigset) = NULL;
+static int (*__ust_after_fork_parent)(sigset_t *restore_sigset) = NULL;
+
+static void (*__ust_after_setns)(void) = NULL;
+static void (*__ust_after_unshare)(void) = NULL;
+static void (*__ust_after_setuid)(void) = NULL;
+static void (*__ust_after_setgid)(void) = NULL;
+static void (*__ust_after_seteuid)(void) = NULL;
+static void (*__ust_after_setegid)(void) = NULL;
+static void (*__ust_after_setreuid)(void) = NULL;
+static void (*__ust_after_setregid)(void) = NULL;
+static void (*__ust_after_setresuid)(void) = NULL;
+static void (*__ust_after_setresgid)(void) = NULL;
+
+static
+void *_init_ust_before_fork(void)
+{
+ if (__ust_before_fork == NULL) {
+ __ust_before_fork = dlsym(RTLD_DEFAULT, "ust_before_fork");
+
+ if (__ust_before_fork == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_before_fork;
+}
+
+static
+void *_init_ust_after_fork_child(void)
+{
+ if (__ust_after_fork_child == NULL) {
+ __ust_after_fork_child = dlsym(RTLD_DEFAULT, "ust_after_fork_child");
+
+ if (__ust_after_fork_child == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_fork_child;
+}
+
+static
+void *_init_ust_after_fork_parent(void)
+{
+ if (__ust_after_fork_parent == NULL) {
+ __ust_after_fork_parent = dlsym(RTLD_DEFAULT, "ust_after_fork_parent");
+
+ if (__ust_after_fork_parent == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_fork_parent;
+}
+
+static
+void *_init_ust_after_setns(void)
+{
+ if (__ust_after_setns == NULL) {
+ __ust_after_setns = dlsym(RTLD_DEFAULT, "ust_after_setns");
+
+ if (__ust_after_setns == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setns;
+}
+
+static
+void *_init_ust_after_unshare(void)
+{
+ if (__ust_after_unshare == NULL) {
+ __ust_after_unshare = dlsym(RTLD_DEFAULT, "ust_after_unshare");
+
+ if (__ust_after_unshare == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_unshare;
+}
+
+static
+void *_init_ust_after_setuid(void)
+{
+ if (__ust_after_setuid == NULL) {
+ __ust_after_setuid = dlsym(RTLD_DEFAULT, "ust_after_setuid");
+
+ if (__ust_after_setuid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setuid;
+}
+
+static
+void *_init_ust_after_setgid(void)
+{
+ if (__ust_after_setgid == NULL) {
+ __ust_after_setgid = dlsym(RTLD_DEFAULT, "ust_after_setgid");
+
+ if (__ust_after_setgid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setgid;
+}
+
+static
+void *_init_ust_after_seteuid(void)
+{
+ if (__ust_after_seteuid == NULL) {
+ __ust_after_seteuid = dlsym(RTLD_DEFAULT, "ust_after_seteuid");
+
+ if (__ust_after_seteuid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_seteuid;
+}
+
+static
+void *_init_ust_after_setegid(void)
+{
+ if (__ust_after_setegid == NULL) {
+ __ust_after_setegid = dlsym(RTLD_DEFAULT, "ust_after_setegid");
+
+ if (__ust_after_setegid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setegid;
+}
+
+static
+void *_init_ust_after_setreuid(void)
+{
+ if (__ust_after_setreuid == NULL) {
+ __ust_after_setreuid = dlsym(RTLD_DEFAULT, "ust_after_setreuid");
+
+ if (__ust_after_setreuid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setreuid;
+}
+
+static
+void *_init_ust_after_setregid(void)
+{
+ if (__ust_after_setregid == NULL) {
+ __ust_after_setregid = dlsym(RTLD_DEFAULT, "ust_after_setregid");
+
+ if (__ust_after_setregid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setregid;
+}
+
+static
+void *_init_ust_after_setresuid(void)
+{
+ if (__ust_after_setresuid == NULL) {
+ __ust_after_setresuid = dlsym(RTLD_DEFAULT, "ust_after_setresuid");
+
+ if (__ust_after_setresuid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setresuid;
+}
+
+static
+void *_init_ust_after_setresgid(void)
+{
+ if (__ust_after_setresgid == NULL) {
+ __ust_after_setresgid = dlsym(RTLD_DEFAULT, "ust_after_setresgid");
+
+ if (__ust_after_setresgid == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ }
+
+ return __ust_after_setresgid;
+}
+
+static
+void _lttng_ust_fork_ctor(void)
+ __attribute__((constructor));
+static
+void _lttng_ust_fork_ctor(void)
+{
+ void *handle = NULL;
+
+ /*
+ * Load ust-2.12 in the global symbol namespace.
+ */
+ handle = dlopen("liblttng-ust.so.0", RTLD_GLOBAL | RTLD_NOW);
+ if (!handle) {
+ fprintf(stderr, "liblttng-ust-fork.so.1: Failed to dlopen liblttng-ust.so.0: %s\n", dlerror());
+ abort();
+ }
+}
+#endif
+
pid_t fork(void)
{
static pid_t (*plibc_func)(void) = NULL;
}
lttng_ust_before_fork(&sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_before_fork()) {
+ __ust_before_fork(&sigset);
+ }
+#endif
+
/* Do the real fork */
retval = plibc_func();
saved_errno = errno;
if (retval == 0) {
/* child */
lttng_ust_after_fork_child(&sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_fork_child()) {
+ __ust_after_fork_child(&sigset);
+ }
+#endif
} else {
lttng_ust_after_fork_parent(&sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_fork_parent()) {
+ __ust_after_fork_parent(&sigset);
+ }
+#endif
}
errno = saved_errno;
return retval;
}
lttng_ust_before_fork(&sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_before_fork()) {
+ __ust_before_fork(&sigset);
+ }
+#endif
+
/* Do the real daemon call */
retval = plibc_func(nochdir, noclose);
saved_errno = errno;
if (retval == 0) {
/* child, parent called _exit() directly */
lttng_ust_after_fork_child(&sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_fork_child()) {
+ __ust_after_fork_child(&sigset);
+ }
+#endif
} else {
/* on error in the parent */
lttng_ust_after_fork_parent(&sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_fork_parent()) {
+ __ust_after_fork_parent(&sigset);
+ }
+#endif
}
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setuid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setuid()) {
+ __ust_after_setuid();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setgid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setgid()) {
+ __ust_after_setgid();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_seteuid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_seteuid()) {
+ __ust_after_seteuid();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setegid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setegid()) {
+ __ust_after_setegid();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setreuid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setreuid()) {
+ __ust_after_setreuid();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setregid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setregid()) {
+ __ust_after_setregid();
+ }
+#endif
errno = saved_errno;
return retval;
/* clone is now done and we are in child */
lttng_ust_after_fork_child(&info->sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_fork_child()) {
+ __ust_after_fork_child(&info->sigset);
+ }
+#endif
return info->fn(info->arg);
}
struct ustfork_clone_info info = { .fn = fn, .arg = arg };
lttng_ust_before_fork(&info.sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_before_fork()) {
+ __ust_before_fork(&info.sigset);
+ }
+#endif
retval = plibc_func(clone_fn, child_stack, flags, &info,
ptid, tls, ctid);
saved_errno = errno;
/* The child doesn't get here. */
lttng_ust_after_fork_parent(&info.sigset);
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_fork_parent()) {
+ __ust_after_fork_parent(&info.sigset);
+ }
+#endif
}
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setns();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setns()) {
+ __ust_after_setns();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_unshare();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_unshare()) {
+ __ust_after_unshare();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setresuid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setresuid()) {
+ __ust_after_setresuid();
+ }
+#endif
errno = saved_errno;
return retval;
saved_errno = errno;
lttng_ust_after_setresgid();
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+ if (_init_ust_after_setresgid()) {
+ __ust_after_setresgid();
+ }
+#endif
errno = saved_errno;
return retval;