From edeb3137b6064818f310567ded5c60e442a933e6 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 24 May 2011 22:19:43 -0400 Subject: [PATCH] Fix module get/put handling wrt data free (use after free) Signed-off-by: Mathieu Desnoyers --- ltt-events.c | 21 +++++++++++++++++++-- ltt-events.h | 12 ++++++++++++ probes/lttng-ftrace.c | 7 ++++++- probes/lttng-kprobes.c | 7 ++++++- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/ltt-events.c b/ltt-events.c index c08079b5..84ad1de5 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -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); } diff --git a/ltt-events.h b/ltt-events.h index 4179fb7c..ce030ae3 100644 --- a/ltt-events.h +++ b/ltt-events.h @@ -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; diff --git a/probes/lttng-ftrace.c b/probes/lttng-ftrace.c index c866876e..ec086902 100644 --- a/probes/lttng-ftrace.c +++ b/probes/lttng-ftrace.c @@ -146,12 +146,17 @@ void lttng_ftrace_unregister(struct ltt_event *event) { wrapper_unregister_ftrace_function_probe(event->u.ftrace.symbol_name, <tng_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) { diff --git a/probes/lttng-kprobes.c b/probes/lttng-kprobes.c index 650144cb..9dd3569b 100644 --- a/probes/lttng-kprobes.c +++ b/probes/lttng-kprobes.c @@ -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"); -- 2.34.1