From 67e5f39161d80ea3d972a37ecf76f45a260c480d Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 1 Mar 2012 17:03:09 -0500 Subject: [PATCH] Fix: Add signature check in tracepoint activation Signed-off-by: Mathieu Desnoyers --- include/lttng/tracepoint.h | 6 +++-- liblttng-ust/ltt-events.c | 4 ++-- liblttng-ust/tracepoint-internal.h | 7 ++++-- liblttng-ust/tracepoint.c | 36 ++++++++++++++++++++++++------ 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/include/lttng/tracepoint.h b/include/lttng/tracepoint.h index b43f8f98..b1c2d360 100644 --- a/include/lttng/tracepoint.h +++ b/include/lttng/tracepoint.h @@ -149,7 +149,8 @@ end: \ static inline void __tracepoint_register_##_provider##___##_name(char *name, \ void *func, void *data) \ { \ - __tracepoint_probe_register(name, func, data); \ + __tracepoint_probe_register(name, func, data, \ + __tracepoint_##_provider##___##_name.signature); \ } \ static inline void __tracepoint_unregister_##_provider##___##_name(char *name, \ void *func, void *data) \ @@ -157,7 +158,8 @@ static inline void __tracepoint_unregister_##_provider##___##_name(char *name, __tracepoint_probe_unregister(name, func, data); \ } -extern int __tracepoint_probe_register(const char *name, void *func, void *data); +extern int __tracepoint_probe_register(const char *name, void *func, void *data, + const char *signature); extern int __tracepoint_probe_unregister(const char *name, void *func, void *data); /* diff --git a/liblttng-ust/ltt-events.c b/liblttng-ust/ltt-events.c index 72e315ec..ce4c2bb0 100644 --- a/liblttng-ust/ltt-events.c +++ b/liblttng-ust/ltt-events.c @@ -279,7 +279,7 @@ int pending_probe_fix_events(const struct lttng_event_desc *desc) remove_pending_probe(e); ret |= __tracepoint_probe_register(name, event->desc->probe_callback, - event); + event, event->desc->signature); if (ret) continue; event->id = chan->free_event_id++; @@ -550,7 +550,7 @@ int ltt_event_create(struct ltt_channel *chan, if (event->desc) { ret = __tracepoint_probe_register(event_param->name, event->desc->probe_callback, - event); + event, event->desc->signature); if (ret) goto register_error; event->id = chan->free_event_id++; diff --git a/liblttng-ust/tracepoint-internal.h b/liblttng-ust/tracepoint-internal.h index d302e6ba..98688ace 100644 --- a/liblttng-ust/tracepoint-internal.h +++ b/liblttng-ust/tracepoint-internal.h @@ -31,8 +31,11 @@ struct tracepoint_lib { int tracepoints_count; }; -extern int tracepoint_probe_register_noupdate(const char *name, void *callback, void *priv); -extern int tracepoint_probe_unregister_noupdate(const char *name, void *callback, void *priv); +extern int tracepoint_probe_register_noupdate(const char *name, + void *callback, void *priv, + const char *signature); +extern int tracepoint_probe_unregister_noupdate(const char *name, + void *callback, void *priv); extern void tracepoint_probe_update_all(void); /* diff --git a/liblttng-ust/tracepoint.c b/liblttng-ust/tracepoint.c index 7144fab4..a14c8b34 100644 --- a/liblttng-ust/tracepoint.c +++ b/liblttng-ust/tracepoint.c @@ -94,6 +94,7 @@ struct tracepoint_entry { struct cds_hlist_node hlist; struct tracepoint_probe *probes; int refcount; /* Number of times armed. 0 if disarmed. */ + const char *signature; char name[0]; }; @@ -243,7 +244,8 @@ static struct tracepoint_entry *get_tracepoint(const char *name) * Add the tracepoint to the tracepoint hash table. Must be called with * tracepoint mutex held. */ -static struct tracepoint_entry *add_tracepoint(const char *name) +static struct tracepoint_entry *add_tracepoint(const char *name, + const char *signature) { struct cds_hlist_head *head; struct cds_hlist_node *node; @@ -274,6 +276,7 @@ static struct tracepoint_entry *add_tracepoint(const char *name) e->name[name_len] = '\0'; e->probes = NULL; e->refcount = 0; + e->signature = signature; cds_hlist_add_head(&e->hlist, head); return e; } @@ -295,6 +298,23 @@ static void set_tracepoint(struct tracepoint_entry **entry, struct tracepoint *elem, int active) { WARN_ON(strncmp((*entry)->name, elem->name, LTTNG_UST_SYM_NAME_LEN - 1) != 0); + /* + * Check that signatures match before connecting a probe to a + * tracepoint. Warn the user if they don't. + */ + if (strcmp(elem->signature, (*entry)->signature) != 0) { + static int warned = 0; + + /* Only print once, don't flood console. */ + if (!warned) { + WARN("Tracepoint signature mismatch, not enabling one or more tracepoints. Ensure that the tracepoint probes prototypes match the application."); + WARN("Tracepoint \"%s\" signatures: call: \"%s\" vs probe: \"%s\".", + elem->name, elem->signature, (*entry)->signature); + warned = 1; + } + /* Don't accept connecting non-matching signatures. */ + return; + } /* * rcu_assign_pointer has a cmm_smp_wmb() which makes sure that the new @@ -370,14 +390,15 @@ static void tracepoint_update_probes(void) } static struct tracepoint_probe * -tracepoint_add_probe(const char *name, void *probe, void *data) +tracepoint_add_probe(const char *name, void *probe, void *data, + const char *signature) { struct tracepoint_entry *entry; struct tracepoint_probe *old; entry = get_tracepoint(name); if (!entry) { - entry = add_tracepoint(name); + entry = add_tracepoint(name, signature); if (IS_ERR(entry)) return (struct tracepoint_probe *)entry; } @@ -396,7 +417,8 @@ tracepoint_add_probe(const char *name, void *probe, void *data) * The probe address must at least be aligned on the architecture pointer size. * Called with the tracepoint mutex held. */ -int __tracepoint_probe_register(const char *name, void *probe, void *data) +int __tracepoint_probe_register(const char *name, void *probe, void *data, + const char *signature) { void *old; int ret = 0; @@ -404,7 +426,7 @@ int __tracepoint_probe_register(const char *name, void *probe, void *data) DBG("Registering probe to tracepoint %s", name); pthread_mutex_lock(&tracepoint_mutex); - old = tracepoint_add_probe(name, probe, data); + old = tracepoint_add_probe(name, probe, data, signature); if (IS_ERR(old)) { ret = PTR_ERR(old); goto end; @@ -477,13 +499,13 @@ static void tracepoint_add_old_probes(void *old) * caller must call tracepoint_probe_update_all() */ int tracepoint_probe_register_noupdate(const char *name, void *probe, - void *data) + void *data, const char *signature) { void *old; int ret = 0; pthread_mutex_lock(&tracepoint_mutex); - old = tracepoint_add_probe(name, probe, data); + old = tracepoint_add_probe(name, probe, data, signature); if (IS_ERR(old)) { ret = PTR_ERR(old); goto end; -- 2.34.1