Fix module get/put handling wrt data free (use after free)
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 25 May 2011 02:19:43 +0000 (22:19 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 25 May 2011 02:19:43 +0000 (22:19 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
ltt-events.c
ltt-events.h
probes/lttng-ftrace.c
probes/lttng-kprobes.c

index c08079b5840654f7977477c61f0c8a032f4ec08d..84ad1de50a34d998248e7ea05129852c0c7b80c9 100644 (file)
@@ -253,6 +253,8 @@ 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:
                ret = lttng_ftrace_register(event_param->name,
@@ -260,6 +262,8 @@ 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;
        default:
                WARN_ON_ONCE(1);
@@ -299,7 +303,6 @@ int _ltt_event_unregister(struct ltt_event *event)
                                                  event);
                if (ret)
                        return ret;
-               ltt_event_put(event->desc);
                break;
        case LTTNG_KERNEL_KPROBE:
                lttng_kprobes_unregister(event);
@@ -321,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);
 }
index 4179fb7c6720e7107f78d2d492f393d8fbc00227..ce030ae3173c58127505d828b44f4792fdbf74e4 100644 (file)
@@ -269,6 +269,7 @@ int lttng_kprobes_register(const char *name,
                uint64_t addr,
                struct ltt_event *event);
 void lttng_kprobes_unregister(struct ltt_event *event);
+void lttng_kprobes_destroy_private(struct ltt_event *event);
 #else
 static inline
 int lttng_kprobes_register(const char *name,
@@ -284,6 +285,11 @@ static inline
 void lttng_kprobes_unregister(struct ltt_event *event)
 {
 }
+
+static inline
+void lttng_kprobes_destroy_private(struct ltt_event *event)
+{
+}
 #endif
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -291,6 +297,7 @@ int lttng_ftrace_register(const char *name,
                          const char *symbol_name,
                          struct ltt_event *event);
 void lttng_ftrace_unregister(struct ltt_event *event);
+void lttng_ftrace_destroy_private(struct ltt_event *event);
 #else
 static inline
 int lttng_ftrace_register(const char *name,
@@ -304,6 +311,11 @@ static inline
 void lttng_ftrace_unregister(struct ltt_event *event)
 {
 }
+
+static inline
+void lttng_ftrace_destroy_private(struct ltt_event *event)
+{
+}
 #endif
 
 extern const struct file_operations lttng_tracepoint_list_fops;
index c866876e6f07dcf5b4d7612d27d4d9e6de08f223..ec086902892d644fcee8c57f70d78231cc4944f2 100644 (file)
@@ -146,12 +146,17 @@ void lttng_ftrace_unregister(struct ltt_event *event)
 {
        wrapper_unregister_ftrace_function_probe(event->u.ftrace.symbol_name,
                        &lttng_ftrace_ops, event);
+}
+EXPORT_SYMBOL_GPL(lttng_ftrace_unregister);
+
+void lttng_ftrace_destroy_private(struct ltt_event *event)
+{
        kfree(event->u.ftrace.symbol_name);
        kfree(event->desc->fields);
        kfree(event->desc->name);
        kfree(event->desc);
 }
-EXPORT_SYMBOL_GPL(lttng_ftrace_unregister);
+EXPORT_SYMBOL_GPL(lttng_ftrace_destroy_private);
 
 int lttng_ftrace_init(void)
 {
index 650144cbe0cdc4793c91bf46825f74a5f9ae042b..9dd3569b4a794d59f5a7cbec2a060fb1d3cd9a6f 100644 (file)
@@ -136,12 +136,17 @@ EXPORT_SYMBOL_GPL(lttng_kprobes_register);
 void lttng_kprobes_unregister(struct ltt_event *event)
 {
        unregister_kprobe(&event->u.kprobe.kp);
+}
+EXPORT_SYMBOL_GPL(lttng_kprobes_unregister);
+
+void lttng_kprobes_destroy_private(struct ltt_event *event)
+{
        kfree(event->u.kprobe.symbol_name);
        kfree(event->desc->fields);
        kfree(event->desc->name);
        kfree(event->desc);
 }
-EXPORT_SYMBOL_GPL(lttng_kprobes_unregister);
+EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_private);
 
 MODULE_LICENSE("GPL and additional rights");
 MODULE_AUTHOR("Mathieu Desnoyers");
This page took 0.029077 seconds and 4 git commands to generate.