Refactoring/fix: syscall table unregister/destroy
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 1 Nov 2021 19:59:10 +0000 (15:59 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 1 Nov 2021 19:59:10 +0000 (15:59 -0400)
Combine syscall table unregister/destroy for both channel buffers and
notifier groups.

This fixes an issue within notifier groups where the syscall dispatch
tables are freed before waiting for an RCU grace period.

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

include/lttng/events-internal.h
src/lttng-events.c
src/lttng-syscalls.c

index 435c1a250085aeb3d8fe72081afc150f75e7627b..a7dbe0f6fa66d663de3fb9d93a876d8e421b28af 100644 (file)
@@ -810,11 +810,12 @@ void lttng_enabler_link_bytecode(const struct lttng_kernel_event_desc *event_des
 
 #if defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
 int lttng_syscalls_register_event(struct lttng_event_recorder_enabler *event_enabler);
-int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan);
-int lttng_syscalls_destroy_channel(struct lttng_kernel_channel_buffer *chan);
 int lttng_syscall_filter_enable_event_recorder(struct lttng_kernel_event_recorder *event_recorder);
 int lttng_syscall_filter_disable_event_recorder(struct lttng_kernel_event_recorder *event_recorder);
 
+int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table);
+int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table);
+
 long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
                struct lttng_kernel_abi_syscall_mask __user *usyscall_mask);
 
@@ -822,7 +823,6 @@ int lttng_syscalls_register_event_notifier(
                struct lttng_event_notifier_enabler *event_notifier_enabler);
 int lttng_syscalls_create_matching_event_notifiers(
                struct lttng_event_notifier_enabler *event_notifier_enabler);
-int lttng_syscalls_unregister_event_notifier_group(struct lttng_event_notifier_group *group);
 int lttng_syscall_filter_enable_event_notifier(struct lttng_kernel_event_notifier *event_notifier);
 int lttng_syscall_filter_disable_event_notifier(struct lttng_kernel_event_notifier *event_notifier);
 #else
@@ -832,24 +832,24 @@ static inline int lttng_syscalls_register_event(
        return -ENOSYS;
 }
 
-static inline int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan)
+static inline int lttng_syscall_filter_enable_event_recorder(struct lttng_kernel_event_recorder *event_recorder)
 {
-       return 0;
+       return -ENOSYS;
 }
 
-static inline int lttng_syscalls_destroy(struct lttng_kernel_channel_buffer *chan)
+static inline int lttng_syscall_filter_disable_event_recorder(struct lttng_kernel_event_recorder *event_recorder)
 {
-       return 0;
+       return -ENOSYS;
 }
 
-static inline int lttng_syscall_filter_enable_event_recorder(struct lttng_kernel_event_recorder *event_recorder)
+static inline int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
-       return -ENOSYS;
+       return 0;
 }
 
-static inline int lttng_syscall_filter_disable_event_recorder(struct lttng_kernel_event_recorder *event_recorder)
+static inline int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
-       return -ENOSYS;
+       return 0;
 }
 
 static inline long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
@@ -864,10 +864,9 @@ static inline int lttng_syscalls_register_event_notifier(
        return -ENOSYS;
 }
 
-static inline int lttng_syscalls_unregister_event_notifier_group(
-               struct lttng_event_notifier_group *group)
+static inline int lttng_syscalls_create_matching_event_notifiers(struct lttng_event_notifier_enabler *event_notifier_enabler)
 {
-       return 0;
+       return -ENOSYS;
 }
 
 static inline int lttng_syscall_filter_enable_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
index b5b1bcec9fb164d24923eb7859d19ea0c6e407a9..dd8b55e065f06b16b63d6ab966f27174678f56f7 100644 (file)
@@ -360,7 +360,7 @@ void lttng_session_destroy(struct lttng_kernel_session *session)
        mutex_lock(&sessions_mutex);
        WRITE_ONCE(session->active, 0);
        list_for_each_entry(chan_priv, &session->priv->chan, node) {
-               ret = lttng_syscalls_unregister_channel(chan_priv->pub);
+               ret = lttng_syscalls_unregister_syscall_table(&chan_priv->parent.syscall_table);
                WARN_ON(ret);
        }
        list_for_each_entry(event_recorder_priv, &session->priv->events, node) {
@@ -369,7 +369,7 @@ void lttng_session_destroy(struct lttng_kernel_session *session)
        }
        synchronize_trace();    /* Wait for in-flight events to complete */
        list_for_each_entry(chan_priv, &session->priv->chan, node) {
-               ret = lttng_syscalls_destroy_channel(chan_priv->pub);
+               ret = lttng_syscalls_destroy_syscall_table(&chan_priv->parent.syscall_table);
                WARN_ON(ret);
        }
        list_for_each_entry_safe(event_recorder_enabler, tmp_event_recorder_enabler,
@@ -410,7 +410,7 @@ void lttng_event_notifier_group_destroy(
 
        mutex_lock(&sessions_mutex);
 
-       ret = lttng_syscalls_unregister_event_notifier_group(event_notifier_group);
+       ret = lttng_syscalls_unregister_syscall_table(&event_notifier_group->syscall_table);
        WARN_ON(ret);
 
        list_for_each_entry_safe(event_notifier_priv, tmpevent_notifier_priv,
@@ -424,7 +424,8 @@ void lttng_event_notifier_group_destroy(
 
        irq_work_sync(&event_notifier_group->wakeup_pending);
 
-       kfree(event_notifier_group->syscall_table.sc_filter);
+       ret = lttng_syscalls_destroy_syscall_table(&event_notifier_group->syscall_table);
+       WARN_ON(ret);
 
        list_for_each_entry_safe(event_notifier_enabler, tmp_event_notifier_enabler,
                        &event_notifier_group->enablers_head, node)
index 33f05ea358b13a45e0dbd115acfd8f666b5f3b1b..3bbb266c3bf118527d5914db5fe8333025baa941 100644 (file)
@@ -1108,47 +1108,8 @@ end:
        return ret;
 }
 
-/*
- * Unregister the syscall event_notifier probes from the callsites.
- */
-int lttng_syscalls_unregister_event_notifier_group(
-               struct lttng_event_notifier_group *event_notifier_group)
-{
-       struct lttng_kernel_syscall_table *syscall_table = &event_notifier_group->syscall_table;
-       int ret;
-
-       /*
-        * Only register the event_notifier probe on the `sys_enter` callsite for now.
-        * At the moment, we don't think it's desirable to have one fired
-        * event_notifier for the entry and one for the exit of a syscall.
-        */
-       if (syscall_table->sys_enter_registered) {
-               ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
-                               (void *) syscall_entry_event_probe, syscall_table);
-               if (ret)
-                       return ret;
-               syscall_table->sys_enter_registered = 0;
-       }
-       if (syscall_table->sys_exit_registered) {
-               ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
-                               (void *) syscall_exit_event_probe, syscall_table);
-               if (ret)
-                       return ret;
-               syscall_table->sys_enter_registered = 0;
-       }
-
-       kfree(syscall_table->syscall_dispatch);
-       kfree(syscall_table->syscall_exit_dispatch);
-#ifdef CONFIG_COMPAT
-       kfree(syscall_table->compat_syscall_dispatch);
-       kfree(syscall_table->compat_syscall_exit_dispatch);
-#endif
-       return 0;
-}
-
-int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan)
+int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
-       struct lttng_kernel_syscall_table *syscall_table = &chan->priv->parent.syscall_table;
        int ret;
 
        if (!syscall_table->syscall_dispatch)
@@ -1170,10 +1131,8 @@ int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan)
        return 0;
 }
 
-int lttng_syscalls_destroy_channel(struct lttng_kernel_channel_buffer *chan)
+int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
-       struct lttng_kernel_syscall_table *syscall_table = &chan->priv->parent.syscall_table;
-
        kfree(syscall_table->syscall_dispatch);
        kfree(syscall_table->syscall_exit_dispatch);
 #ifdef CONFIG_COMPAT
This page took 0.030009 seconds and 4 git commands to generate.