From 6053e75e863ee76362cceb6912c001b738c11b13 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 1 Nov 2021 15:59:10 -0400 Subject: [PATCH] Refactoring/fix: syscall table unregister/destroy 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 Change-Id: Ia69f6be86da651022c5d5f4f6bce6e321156c070 --- include/lttng/events-internal.h | 27 ++++++++++---------- src/lttng-events.c | 9 ++++--- src/lttng-syscalls.c | 45 ++------------------------------- 3 files changed, 20 insertions(+), 61 deletions(-) diff --git a/include/lttng/events-internal.h b/include/lttng/events-internal.h index 435c1a25..a7dbe0f6 100644 --- a/include/lttng/events-internal.h +++ b/include/lttng/events-internal.h @@ -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) diff --git a/src/lttng-events.c b/src/lttng-events.c index b5b1bcec..dd8b55e0 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -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) diff --git a/src/lttng-syscalls.c b/src/lttng-syscalls.c index 33f05ea3..3bbb266c 100644 --- a/src/lttng-syscalls.c +++ b/src/lttng-syscalls.c @@ -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 -- 2.34.1