Remove libust-initializer
[ust.git] / libust / lttng-ust-comm.c
index 13b3895e40127b7a57c9ff6b5081545dcb093d2b..1e4031be273fcbcc7a29d397ab0bb8db3bbcfa22 100644 (file)
 #include <semaphore.h>
 #include <time.h>
 #include <assert.h>
+#include <signal.h>
 #include <urcu/uatomic.h>
 
 #include <lttng-ust-comm.h>
 #include <ust/usterr-signal-safe.h>
 #include <ust/lttng-ust-abi.h>
 #include <ust/tracepoint.h>
+#include <ust/tracepoint-internal.h>
+#include <ust/ust.h>
 
 /*
  * Has lttng ust comm constructor been called ?
@@ -74,7 +77,8 @@ struct sock_info {
        int socket;
        pthread_t ust_listener; /* listener thread */
        int root_handle;
-       int constructor_sem_posted;;
+       int constructor_sem_posted;
+       int allowed;
 };
 
 /* Socket from app (connect) to session daemon (listen) for communication */
@@ -83,6 +87,7 @@ struct sock_info global_apps = {
        .sock_path = DEFAULT_GLOBAL_APPS_UNIX_SOCK,
        .socket = -1,
        .root_handle = -1,
+       .allowed = 1,
 };
 
 /* TODO: allow global_apps_sock_path override */
@@ -91,6 +96,7 @@ struct sock_info local_apps = {
        .name = "local",
        .socket = -1,
        .root_handle = -1,
+       .allowed = 0,   /* Check setuid bit first */
 };
 
 extern void ltt_ring_buffer_client_overwrite_init(void);
@@ -101,10 +107,19 @@ extern void ltt_ring_buffer_client_discard_exit(void);
 extern void ltt_ring_buffer_metadata_client_exit(void);
 
 static
-int setup_local_apps_socket(void)
+int setup_local_apps(void)
 {
        const char *home_dir;
 
+       /*
+        * Disallow per-user tracing for setuid binaries.
+        */
+       if (getuid() != geteuid()) {
+               local_apps.allowed = 0;
+               return 0;
+       } else {
+               local_apps.allowed = 1;
+       }
        home_dir = (const char *) getenv("HOME");
        if (!home_dir)
                return -ENOENT;
@@ -449,16 +464,20 @@ void __attribute__((constructor)) lttng_ust_init(void)
        ret = sem_init(&constructor_wait, 0, 0);
        assert(!ret);
 
-       ret = setup_local_apps_socket();
+       ret = setup_local_apps();
        if (ret) {
-               ERR("Error setting up to local apps socket");
+               ERR("Error setting up to local apps");
        }
-
-       ret = pthread_create(&global_apps.ust_listener, NULL,
-                       ust_listener_thread, &global_apps);
        ret = pthread_create(&local_apps.ust_listener, NULL,
                        ust_listener_thread, &local_apps);
 
+       if (local_apps.allowed) {
+               ret = pthread_create(&global_apps.ust_listener, NULL,
+                               ust_listener_thread, &global_apps);
+       } else {
+               handle_register_done(&local_apps);
+       }
+
        switch (timeout_mode) {
        case 1: /* timeout wait */
                do {
@@ -508,12 +527,14 @@ void __attribute__((destructor)) lttng_ust_exit(void)
 
        cleanup_sock_info(&global_apps);
 
-       ret = pthread_cancel(local_apps.ust_listener);
-       if (ret) {
-               ERR("Error cancelling local ust listener thread");
-       }
+       if (local_apps.allowed) {
+               ret = pthread_cancel(local_apps.ust_listener);
+               if (ret) {
+                       ERR("Error cancelling local ust listener thread");
+               }
 
-       cleanup_sock_info(&local_apps);
+               cleanup_sock_info(&local_apps);
+       }
 
        lttng_ust_abi_exit();
        ltt_events_exit();
@@ -522,3 +543,58 @@ void __attribute__((destructor)) lttng_ust_exit(void)
        ltt_ring_buffer_metadata_client_exit();
        exit_tracepoint();
 }
+
+/*
+ * We exclude the worker threads across fork and clone (except
+ * CLONE_VM), because these system calls only keep the forking thread
+ * running in the child.  Therefore, we don't want to call fork or clone
+ * in the middle of an tracepoint or ust tracing state modification.
+ * Holding this mutex protects these structures across fork and clone.
+ */
+void ust_before_fork(ust_fork_info_t *fork_info)
+{
+       /*
+        * Disable signals. This is to avoid that the child intervenes
+        * before it is properly setup for tracing. It is safer to
+        * disable all signals, because then we know we are not breaking
+        * anything by restoring the original mask.
+         */
+       sigset_t all_sigs;
+       int ret;
+
+       /* Disable signals */
+       sigfillset(&all_sigs);
+       ret = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs);
+       if (ret == -1) {
+               PERROR("sigprocmask");
+       }
+       pthread_mutex_lock(&lttng_ust_comm_mutex);
+       rcu_bp_before_fork();
+}
+
+static void ust_after_fork_common(ust_fork_info_t *fork_info)
+{
+       int ret;
+
+       pthread_mutex_unlock(&lttng_ust_comm_mutex);
+       /* Restore signals */
+       ret = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
+       if (ret == -1) {
+               PERROR("sigprocmask");
+       }
+}
+
+void ust_after_fork_parent(ust_fork_info_t *fork_info)
+{
+       rcu_bp_after_fork_parent();
+       /* Release mutexes and reenable signals */
+       ust_after_fork_common(fork_info);
+}
+
+void ust_after_fork_child(ust_fork_info_t *fork_info)
+{
+       /* Release urcu mutexes */
+       rcu_bp_after_fork_child();
+       /* Release mutexes and reenable signals */
+       ust_after_fork_common(fork_info);
+}
This page took 0.025687 seconds and 4 git commands to generate.