Fix: kretprobe: null ptr deref on session destroy
[lttng-modules.git] / src / lttng-events.c
index 3f9d0f9a91fdf7b50b7a647d1aea55413d8412b0..d819c9e20dac0e28719b61aeb6373da868cc5efc 100644 (file)
@@ -90,21 +90,21 @@ int _lttng_field_statedump(struct lttng_session *session,
 
 void synchronize_trace(void)
 {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,1,0))
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,1,0))
        synchronize_rcu();
 #else
        synchronize_sched();
 #endif
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,4,0))
 #ifdef CONFIG_PREEMPT_RT_FULL
        synchronize_rcu();
 #endif
-#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) */
+#else /* (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,4,0)) */
 #ifdef CONFIG_PREEMPT_RT
        synchronize_rcu();
 #endif
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) */
+#endif /* (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,4,0)) */
 }
 
 void lttng_lock_sessions(void)
@@ -412,6 +412,7 @@ void lttng_event_notifier_group_destroy(
 
        if (event_notifier_group->error_counter) {
                struct lttng_counter *error_counter = event_notifier_group->error_counter;
+
                error_counter->ops->counter_destroy(error_counter->counter);
                module_put(error_counter->transport->owner);
                lttng_kvfree(error_counter);
@@ -948,6 +949,8 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan,
                event_return->enabled = 0;
                event_return->registered = 1;
                event_return->instrumentation = itype;
+               INIT_LIST_HEAD(&event_return->filter_bytecode_runtime_head);
+               INIT_LIST_HEAD(&event_return->enablers_ref_head);
                /*
                 * Populate lttng_event structure before kretprobe registration.
                 */
@@ -1071,6 +1074,7 @@ struct lttng_event_notifier *_lttng_event_notifier_create(
                void *filter, enum lttng_kernel_instrumentation itype)
 {
        struct lttng_event_notifier *event_notifier;
+       struct lttng_counter *error_counter;
        const char *event_name;
        struct hlist_head *head;
        int ret;
@@ -1234,9 +1238,12 @@ struct lttng_event_notifier *_lttng_event_notifier_create(
 
        /*
         * Clear the error counter bucket. The sessiond keeps track of which
-        * bucket is currently in use. We trust it.
+        * bucket is currently in use. We trust it. The session lock
+        * synchronizes against concurrent creation of the error
+        * counter.
         */
-       if (event_notifier_group->error_counter) {
+       error_counter = event_notifier_group->error_counter;
+       if (error_counter) {
                size_t dimension_index[1];
 
                /*
@@ -1250,9 +1257,7 @@ struct lttng_event_notifier *_lttng_event_notifier_create(
                }
 
                dimension_index[0] = event_notifier->error_counter_index;
-               ret = event_notifier_group->error_counter->ops->counter_clear(
-                               event_notifier_group->error_counter->counter,
-                               dimension_index);
+               ret = error_counter->ops->counter_clear(error_counter->counter, dimension_index);
                if (ret) {
                        printk(KERN_INFO "LTTng: event_notifier: Unable to clear error counter bucket %llu\n",
                                event_notifier->error_counter_index);
@@ -1482,6 +1487,8 @@ int _lttng_event_notifier_unregister(
 static
 void _lttng_event_destroy(struct lttng_event *event)
 {
+       struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref;
+
        switch (event->instrumentation) {
        case LTTNG_KERNEL_TRACEPOINT:
                lttng_event_desc_put(event->desc);
@@ -1507,6 +1514,11 @@ void _lttng_event_destroy(struct lttng_event *event)
        }
        list_del(&event->list);
        lttng_destroy_context(event->ctx);
+       lttng_free_event_filter_runtime(event);
+       /* Free event enabler refs */
+       list_for_each_entry_safe(enabler_ref, tmp_enabler_ref,
+                                &event->enablers_ref_head, node)
+               kfree(enabler_ref);
        kmem_cache_free(event_cache, event);
 }
 
@@ -1516,6 +1528,8 @@ void _lttng_event_destroy(struct lttng_event *event)
 static
 void _lttng_event_notifier_destroy(struct lttng_event_notifier *event_notifier)
 {
+       struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref;
+
        switch (event_notifier->instrumentation) {
        case LTTNG_KERNEL_TRACEPOINT:
                lttng_event_desc_put(event_notifier->desc);
@@ -1537,6 +1551,11 @@ void _lttng_event_notifier_destroy(struct lttng_event_notifier *event_notifier)
                WARN_ON_ONCE(1);
        }
        list_del(&event_notifier->list);
+       lttng_free_event_notifier_filter_runtime(event_notifier);
+       /* Free event enabler refs */
+       list_for_each_entry_safe(enabler_ref, tmp_enabler_ref,
+                                &event_notifier->enablers_ref_head, node)
+               kfree(enabler_ref);
        kmem_cache_free(event_notifier_cache, event_notifier);
 }
 
@@ -4026,7 +4045,7 @@ void lttng_counter_transport_unregister(struct lttng_counter_transport *transpor
 }
 EXPORT_SYMBOL_GPL(lttng_counter_transport_unregister);
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0))
 
 enum cpuhp_state lttng_hp_prepare;
 enum cpuhp_state lttng_hp_online;
@@ -4142,7 +4161,7 @@ static void __exit lttng_exit_cpu_hotplug(void)
        cpuhp_remove_multi_state(lttng_hp_prepare);
 }
 
-#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */
+#else /* #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */
 static int lttng_init_cpu_hotplug(void)
 {
        return 0;
@@ -4150,7 +4169,7 @@ static int lttng_init_cpu_hotplug(void)
 static void lttng_exit_cpu_hotplug(void)
 {
 }
-#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */
+#endif /* #else #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */
 
 
 static int __init lttng_events_init(void)
This page took 0.025262 seconds and 4 git commands to generate.