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=6e9f0699b334bbeebb00957b0e9a9b0bd486ea1b;hb=55d097957f5bb8138959ad2202a40d85d49f029e;hpb=0b2dc8df2a6d7b3341a72a04767dd6328907c97c diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index 6e9f0699b..65ba82c1b 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -23,6 +23,7 @@ #include #include "ust-registry.h" +#include "ust-app.h" #include "utils.h" /* @@ -71,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"); @@ -185,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; @@ -198,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, " @@ -279,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; } @@ -324,6 +391,7 @@ void destroy_channel_rcu(struct rcu_head *head) if (chan->ht) { ht_cleanup_push(chan->ht); } + free(chan->ctx_fields); free(chan); } @@ -552,8 +620,6 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) } rcu_read_unlock(); - if (reg->channels) { - ht_cleanup_push(reg->channels); - } + ht_cleanup_push(reg->channels); free(reg->metadata); }