X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-registry.c;h=65ba82c1b99b16bb51991161bc32f42dafcadcae;hp=399d48f681d8e0aa22bd269109e580f0e2206d77;hb=55d097957f5bb8138959ad2202a40d85d49f029e;hpb=9dbcf3320e5aebb599ea97f74a8e35dd71a7ba6d diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index 399d48f68..65ba82c1b 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -23,6 +23,8 @@ #include #include "ust-registry.h" +#include "ust-app.h" +#include "utils.h" /* * Hash table match function for event in the registry. @@ -70,16 +72,78 @@ static unsigned long ht_hash_event(void *_key, unsigned long seed) return hash_key_u64(&xored_key, seed); } +/* + * Return negative value on error, 0 if OK. + * + * TODO: we could add stricter verification of more types to catch + * errors in liblttng-ust implementation earlier than consumption by the + * trace reader. + */ +static +int validate_event_field(struct ustctl_field *field, + const char *event_name, + struct ust_app *app) +{ + switch(field->type.atype) { + case ustctl_atype_integer: + case ustctl_atype_enum: + case ustctl_atype_array: + case ustctl_atype_sequence: + case ustctl_atype_string: + break; + + case ustctl_atype_float: + switch (field->type.u.basic._float.mant_dig) { + case 0: + WARN("UST application '%s' (pid: %d) has unknown float mantissa '%u' " + "in field '%s', rejecting event '%s'", + app->name, app->pid, + field->type.u.basic._float.mant_dig, + field->name, + event_name); + return -EINVAL; + default: + break; + } + break; + + default: + return -ENOENT; + } + return 0; +} + +static +int validate_event_fields(size_t nr_fields, struct ustctl_field *fields, + const char *event_name, struct ust_app *app) +{ + unsigned int i; + + for (i = 0; i < nr_fields; i++) { + if (validate_event_field(&fields[i], event_name, app) < 0) + return -EINVAL; + } + return 0; +} + /* * Allocate event and initialize it. This does NOT set a valid event id from a * registry. */ static struct ust_registry_event *alloc_event(int session_objd, int channel_objd, char *name, char *sig, size_t nr_fields, - struct ustctl_field *fields, int loglevel, char *model_emf_uri) + struct ustctl_field *fields, int loglevel, char *model_emf_uri, + struct ust_app *app) { struct ust_registry_event *event = NULL; + /* + * Ensure that the field content is valid. + */ + if (validate_event_fields(nr_fields, fields, name, app) < 0) { + return NULL; + } + event = zmalloc(sizeof(*event)); if (!event) { PERROR("zmalloc ust registry event"); @@ -184,7 +248,8 @@ end: int ust_registry_create_event(struct ust_registry_session *session, uint64_t chan_key, int session_objd, int channel_objd, char *name, char *sig, size_t nr_fields, struct ustctl_field *fields, int loglevel, - char *model_emf_uri, int buffer_type, uint32_t *event_id_p) + char *model_emf_uri, int buffer_type, uint32_t *event_id_p, + struct ust_app *app) { int ret; uint32_t event_id; @@ -197,34 +262,34 @@ int ust_registry_create_event(struct ust_registry_session *session, assert(sig); assert(event_id_p); + rcu_read_lock(); + /* * This should not happen but since it comes from the UST tracer, an * external party, don't assert and simply validate values. */ if (session_objd < 0 || channel_objd < 0) { ret = -EINVAL; - goto error; + goto error_free; } - rcu_read_lock(); - chan = ust_registry_channel_find(session, chan_key); if (!chan) { ret = -EINVAL; - goto error_unlock; + goto error_free; } /* Check if we've reached the maximum possible id. */ if (ust_registry_is_max_id(chan->used_event_id)) { ret = -ENOENT; - goto error_unlock; + goto error_free; } event = alloc_event(session_objd, channel_objd, name, sig, nr_fields, - fields, loglevel, model_emf_uri); + fields, loglevel, model_emf_uri, app); if (!event) { ret = -ENOMEM; - goto error_unlock; + goto error_free; } DBG3("UST registry creating event with event: %s, sig: %s, id: %u, " @@ -278,9 +343,12 @@ int ust_registry_create_event(struct ust_registry_session *session, rcu_read_unlock(); return 0; +error_free: + free(sig); + free(fields); + free(model_emf_uri); error_unlock: rcu_read_unlock(); -error: destroy_event(event); return ret; } @@ -310,9 +378,9 @@ void ust_registry_destroy_event(struct ust_registry_channel *chan, /* * We need to execute ht_destroy outside of RCU read-side critical - * section, so we postpone its execution using call_rcu. It is simpler - * than to change the semantic of the many callers of - * destroy_channel(). + * section and outside of call_rcu thread, so we postpone its execution + * using ht_cleanup_push. It is simpler than to change the semantic of + * the many callers of delete_ust_app_session(). */ static void destroy_channel_rcu(struct rcu_head *head) @@ -321,8 +389,9 @@ void destroy_channel_rcu(struct rcu_head *head) caa_container_of(head, struct ust_registry_channel, rcu_head); if (chan->ht) { - lttng_ht_destroy(chan->ht); + ht_cleanup_push(chan->ht); } + free(chan->ctx_fields); free(chan); } @@ -551,8 +620,6 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) } rcu_read_unlock(); - if (reg->channels) { - lttng_ht_destroy(reg->channels); - } + ht_cleanup_push(reg->channels); free(reg->metadata); }