Fix module get/put handling wrt data free (use after free)
[lttng-modules.git] / ltt-events.c
index 8a6f8e9930fa24acb27bb2fee4a7d2534fc8ccad..84ad1de50a34d998248e7ea05129852c0c7b80c9 100644 (file)
@@ -169,12 +169,17 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session,
                goto nomem;
        chan->session = session;
        init_waitqueue_head(&chan->notify_wait);
+       chan->id = session->free_chan_id++;
+       /*
+        * Note: the channel creation op already writes into the packet
+        * headers. Therefore the "chan" information used as input
+        * should be already accessible.
+        */
        chan->chan = transport->ops.channel_create("[lttng]", chan, buf_addr,
                        subbuf_size, num_subbuf, switch_timer_interval,
                        read_timer_interval);
        if (!chan->chan)
                goto create_error;
-       chan->id = session->free_chan_id++;
        chan->ops = &transport->ops;
        list_add(&chan->list, &session->chan);
        mutex_unlock(&sessions_mutex);
@@ -230,7 +235,7 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan,
        /* Populate ltt_event structure before tracepoint registration. */
        smp_wmb();
        switch (event_param->instrumentation) {
-       case LTTNG_KERNEL_TRACEPOINTS:
+       case LTTNG_KERNEL_TRACEPOINT:
                event->desc = ltt_event_get(event_param->name);
                if (!event->desc)
                        goto register_error;
@@ -240,7 +245,7 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan,
                if (ret)
                        goto register_error;
                break;
-       case LTTNG_KERNEL_KPROBES:
+       case LTTNG_KERNEL_KPROBE:
                ret = lttng_kprobes_register(event_param->name,
                                event_param->u.kprobe.symbol_name,
                                event_param->u.kprobe.offset,
@@ -248,13 +253,17 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan,
                                event);
                if (ret)
                        goto register_error;
+               ret = try_module_get(event->desc->owner);
+               WARN_ON_ONCE(!ret);
                break;
-       case LTTNG_KERNEL_FUNCTION_TRACER:
+       case LTTNG_KERNEL_FUNCTION:
                ret = lttng_ftrace_register(event_param->name,
                                event_param->u.ftrace.symbol_name,
                                event);
                if (ret)
                        goto register_error;
+               ret = try_module_get(event->desc->owner);
+               WARN_ON_ONCE(!ret);
                break;
        default:
                WARN_ON_ONCE(1);
@@ -288,19 +297,18 @@ int _ltt_event_unregister(struct ltt_event *event)
        int ret = -EINVAL;
 
        switch (event->instrumentation) {
-       case LTTNG_KERNEL_TRACEPOINTS:
+       case LTTNG_KERNEL_TRACEPOINT:
                ret = tracepoint_probe_unregister(event->desc->name,
                                                  event->desc->probe_callback,
                                                  event);
                if (ret)
                        return ret;
-               ltt_event_put(event->desc);
                break;
-       case LTTNG_KERNEL_KPROBES:
+       case LTTNG_KERNEL_KPROBE:
                lttng_kprobes_unregister(event);
                ret = 0;
                break;
-       case LTTNG_KERNEL_FUNCTION_TRACER:
+       case LTTNG_KERNEL_FUNCTION:
                lttng_ftrace_unregister(event);
                ret = 0;
                break;
@@ -316,7 +324,21 @@ int _ltt_event_unregister(struct ltt_event *event)
 static
 void _ltt_event_destroy(struct ltt_event *event)
 {
-       ltt_event_put(event->desc);
+       switch (event->instrumentation) {
+       case LTTNG_KERNEL_TRACEPOINT:
+               ltt_event_put(event->desc);
+               break;
+       case LTTNG_KERNEL_KPROBE:
+               module_put(event->desc->owner);
+               lttng_kprobes_destroy_private(event);
+               break;
+       case LTTNG_KERNEL_FUNCTION:
+               module_put(event->desc->owner);
+               lttng_ftrace_destroy_private(event);
+               break;
+       default:
+               WARN_ON_ONCE(1);
+       }
        list_del(&event->list);
        kmem_cache_free(event_cache, event);
 }
@@ -362,7 +384,7 @@ int lttng_metadata_printf(struct ltt_session *session,
                 */
                waitret = wait_event_interruptible_timeout(*chan->ops->get_reader_wait_queue(chan),
                        ({
-                               ret = chan->ops->event_reserve(&ctx);
+                               ret = chan->ops->event_reserve(&ctx, 0);
                                ret != -ENOBUFS || !ret;
                        }),
                        msecs_to_jiffies(LTTNG_METADATA_TIMEOUT_MSEC));
This page took 0.025061 seconds and 4 git commands to generate.