From: Mathieu Desnoyers Date: Wed, 13 Apr 2022 20:24:52 +0000 (-0400) Subject: Implement extensible LTTNG_UST_ABI_COUNTER_EVENT protocol command X-Git-Url: http://git.lttng.org./?a=commitdiff_plain;h=2ec133bef8c5dd9cf4e72817a7081936ca92eeb3;p=lttng-ust.git Implement extensible LTTNG_UST_ABI_COUNTER_EVENT protocol command Signed-off-by: Mathieu Desnoyers Change-Id: Ib0414f90ab74d21e6847e79062bd7b5236e2097b --- diff --git a/include/lttng/ust-abi.h b/include/lttng/ust-abi.h index e9d77c74..a995e3ac 100644 --- a/include/lttng/ust-abi.h +++ b/include/lttng/ust-abi.h @@ -107,8 +107,6 @@ struct lttng_ust_abi_event_notifier_notification { char padding[LTTNG_UST_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING]; } __attribute__((packed)); -#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4 - enum lttng_ust_abi_key_token_type { LTTNG_UST_ABI_KEY_TOKEN_STRING = 0, /* arg: strtab_offset. */ LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME = 1, /* no arg. */ @@ -125,33 +123,35 @@ enum lttng_ust_abi_counter_bitness { LTTNG_UST_ABI_COUNTER_BITNESS_64 = 1, }; -#define LTTNG_UST_ABI_KEY_ARG_PADDING1 256 -#define LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX 256 +#define LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX 4096 + +struct lttng_ust_abi_counter_key_string { + uint32_t string_len; /* string length (includes \0) */ + char str[]; /* Null-terminated string. */ +} __attribute__((packed)); + struct lttng_ust_abi_key_token { - uint32_t type; /* enum lttng_ust_key_token_type */ - union { - char string[LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX]; - char padding[LTTNG_UST_ABI_KEY_ARG_PADDING1]; - } arg; + uint32_t len; /* length of this structure. */ + uint32_t type; /* enum lttng_ust_key_token_type */ + + /* Followed by a struct lttng_ust_abi_counter_key_string for LTTNG_UST_ABI_KEY_TOKEN_STRING. */ } __attribute__((packed)); -#define LTTNG_UST_ABI_NR_KEY_TOKEN 4 struct lttng_ust_abi_counter_key_dimension { + uint32_t len; /* length of this structure */ uint32_t nr_key_tokens; - struct lttng_ust_abi_key_token key_tokens[LTTNG_UST_ABI_NR_KEY_TOKEN]; -} __attribute__((packed)); -#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4 -struct lttng_ust_abi_counter_key { - uint32_t nr_dimensions; - struct lttng_ust_abi_counter_key_dimension key_dimensions[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX]; + /* Followed by a variable-length array of key tokens */ } __attribute__((packed)); -#define LTTNG_UST_ABI_COUNTER_EVENT_PADDING1 16 +#define LTTNG_UST_ABI_COUNTER_EVENT_MAX_LEN 4096U struct lttng_ust_abi_counter_event { + uint32_t len; /* length of this structure */ + struct lttng_ust_abi_event event; - struct lttng_ust_abi_counter_key key; - char padding[LTTNG_UST_ABI_COUNTER_EVENT_PADDING1]; + uint32_t number_key_dimensions; /* array of dimensions is an array of var. len. elements. */ + + /* Followed by a variable-length array of key dimensions */ } __attribute__((packed)); enum lttng_ust_abi_counter_dimension_flags { @@ -180,12 +180,6 @@ struct lttng_ust_abi_counter_conf { uint32_t elem_len; /* array stride (size of lttng_ust_abi_counter_dimension) */ } __attribute__((packed)); -struct lttng_ust_abi_counter_value { - uint32_t number_dimensions; - uint64_t dimension_indexes[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX]; - int64_t value; -} __attribute__((packed)); - #define LTTNG_UST_ABI_COUNTER_DATA_MAX_LEN 4096U struct lttng_ust_abi_counter { uint64_t len; diff --git a/include/lttng/ust-ctl.h b/include/lttng/ust-ctl.h index e244b997..07f08ca7 100644 --- a/include/lttng/ust-ctl.h +++ b/include/lttng/ust-ctl.h @@ -660,6 +660,7 @@ int lttng_ust_ctl_counter_clear(struct lttng_ust_ctl_daemon_counter *counter, int lttng_ust_ctl_counter_create_event(int sock, struct lttng_ust_abi_counter_event *counter_event, + size_t counter_event_len, struct lttng_ust_abi_object_data *counter_data, struct lttng_ust_abi_object_data **counter_event_data); diff --git a/src/common/events.h b/src/common/events.h index bc085ffc..94e8038b 100644 --- a/src/common/events.h +++ b/src/common/events.h @@ -52,6 +52,9 @@ union lttng_ust_abi_args { struct { int shm_fd; } counter_shm; + struct { + uint32_t len; + } counter_event; }; struct lttng_ust_abi_objd_ops { @@ -71,7 +74,7 @@ enum lttng_key_token_type { LTTNG_KEY_TOKEN_PROVIDER_NAME = 2, }; -#define LTTNG_KEY_TOKEN_STRING_LEN_MAX LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX +#define LTTNG_KEY_TOKEN_STRING_LEN_MAX 4096 struct lttng_key_token { enum lttng_key_token_type type; union { @@ -79,13 +82,13 @@ struct lttng_key_token { } arg; }; -#define LTTNG_NR_KEY_TOKEN LTTNG_UST_ABI_NR_KEY_TOKEN +#define LTTNG_NR_KEY_TOKEN 8 struct lttng_counter_key_dimension { size_t nr_key_tokens; struct lttng_key_token key_tokens[LTTNG_NR_KEY_TOKEN]; }; -#define LTTNG_COUNTER_DIMENSION_MAX LTTNG_UST_ABI_COUNTER_DIMENSION_MAX +#define LTTNG_COUNTER_DIMENSION_MAX 4 struct lttng_counter_key { size_t nr_dimensions; struct lttng_counter_key_dimension key_dimensions[LTTNG_COUNTER_DIMENSION_MAX]; diff --git a/src/lib/lttng-ust-ctl/ustctl.c b/src/lib/lttng-ust-ctl/ustctl.c index 3a2e58f6..53d63c6d 100644 --- a/src/lib/lttng-ust-ctl/ustctl.c +++ b/src/lib/lttng-ust-ctl/ustctl.c @@ -3318,6 +3318,7 @@ int lttng_ust_ctl_counter_clear(struct lttng_ust_ctl_daemon_counter *counter, */ int lttng_ust_ctl_counter_create_event(int sock, struct lttng_ust_abi_counter_event *counter_event, + size_t counter_event_len, struct lttng_ust_abi_object_data *counter_data, struct lttng_ust_abi_object_data **_counter_event_data) { @@ -3337,15 +3338,15 @@ int lttng_ust_ctl_counter_create_event(int sock, memset(&lum, 0, sizeof(lum)); lum.handle = counter_data->handle; lum.cmd = LTTNG_UST_ABI_COUNTER_EVENT; - lum.u.counter_event.len = sizeof(*counter_event); + lum.u.counter_event.len = counter_event_len; ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) { free(counter_event_data); return ret; } /* Send struct lttng_ust_counter_event */ - len = ustcomm_send_unix_sock(sock, counter_event, sizeof(*counter_event)); - if (len != sizeof(*counter_event)) { + len = ustcomm_send_unix_sock(sock, counter_event, counter_event_len); + if (len != counter_event_len) { free(counter_event_data); if (len < 0) return len; diff --git a/src/lib/lttng-ust/events.h b/src/lib/lttng-ust/events.h index 093d8d09..3fd58aa4 100644 --- a/src/lib/lttng-ust/events.h +++ b/src/lib/lttng-ust/events.h @@ -29,8 +29,8 @@ struct lttng_event_recorder_enabler *lttng_event_recorder_enabler_create( */ struct lttng_event_counter_enabler *lttng_event_counter_enabler_create( enum lttng_enabler_format_type format_type, - const struct lttng_ust_abi_event *event_param, - const struct lttng_ust_abi_counter_key *key, + const struct lttng_ust_abi_counter_event *counter_event, + const struct lttng_counter_key *key, struct lttng_ust_channel_counter *chan) __attribute__((visibility("hidden"))); diff --git a/src/lib/lttng-ust/lttng-events.c b/src/lib/lttng-ust/lttng-events.c index 69a6c7b4..82da68f6 100644 --- a/src/lib/lttng-ust/lttng-events.c +++ b/src/lib/lttng-ust/lttng-events.c @@ -1692,59 +1692,6 @@ void lttng_ust_abi_events_exit(void) lttng_session_destroy(session_priv->pub); } -static -int copy_counter_key(struct lttng_counter_key *key, - const struct lttng_ust_abi_counter_key *key_param) -{ - size_t i, j, nr_dimensions; - - nr_dimensions = key_param->nr_dimensions; - if (nr_dimensions > LTTNG_UST_ABI_COUNTER_DIMENSION_MAX) - return -EINVAL; - key->nr_dimensions = nr_dimensions; - for (i = 0; i < nr_dimensions; i++) { - const struct lttng_ust_abi_counter_key_dimension *udim = - &key_param->key_dimensions[i]; - struct lttng_counter_key_dimension *dim = - &key->key_dimensions[i]; - size_t nr_key_tokens; - - nr_key_tokens = udim->nr_key_tokens; - if (!nr_key_tokens || nr_key_tokens > LTTNG_UST_ABI_NR_KEY_TOKEN) - return -EINVAL; - dim->nr_key_tokens = nr_key_tokens; - for (j = 0; j < nr_key_tokens; j++) { - const struct lttng_ust_abi_key_token *utoken = - &udim->key_tokens[j]; - struct lttng_key_token *token = - &dim->key_tokens[j]; - - switch (utoken->type) { - case LTTNG_UST_ABI_KEY_TOKEN_STRING: - { - size_t len; - - token->type = LTTNG_UST_ABI_KEY_TOKEN_STRING; - len = strnlen(utoken->arg.string, LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX); - if (!len || len >= LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX) - return -EINVAL; - strcpy(token->arg.string, utoken->arg.string); - break; - } - case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME: - token->type = LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME; - break; - case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME: - token->type = LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME; - break; - default: - return -EINVAL; - } - } - } - return 0; -} - /* * Enabler management. */ @@ -1777,8 +1724,8 @@ struct lttng_event_recorder_enabler *lttng_event_recorder_enabler_create( struct lttng_event_counter_enabler *lttng_event_counter_enabler_create( enum lttng_enabler_format_type format_type, - const struct lttng_ust_abi_event *event_param, - const struct lttng_ust_abi_counter_key *key, + const struct lttng_ust_abi_counter_event *counter_event, + const struct lttng_counter_key *key, struct lttng_ust_channel_counter *chan) { struct lttng_event_counter_enabler *event_enabler; @@ -1790,18 +1737,13 @@ struct lttng_event_counter_enabler *lttng_event_counter_enabler_create( event_enabler->parent.parent.format_type = format_type; CDS_INIT_LIST_HEAD(&event_enabler->parent.parent.filter_bytecode_head); CDS_INIT_LIST_HEAD(&event_enabler->parent.parent.excluder_head); - memcpy(&event_enabler->parent.parent.event_param, event_param, + memcpy(&event_enabler->parent.parent.event_param, &counter_event->event, sizeof(event_enabler->parent.parent.event_param)); event_enabler->chan = chan; - if (key) { - if (copy_counter_key(&event_enabler->key, key)) { - free(event_enabler); - return NULL; - } - } + memcpy(&event_enabler->key, key, sizeof(struct lttng_counter_key)); /* ctx left NULL */ event_enabler->parent.parent.enabled = 0; - event_enabler->parent.parent.user_token = event_param->token; + event_enabler->parent.parent.user_token = counter_event->event.token; event_enabler->parent.chan = chan->parent; cds_list_add(&event_enabler->parent.node, &event_enabler->chan->parent->session->priv->enablers_head); lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session); diff --git a/src/lib/lttng-ust/lttng-ust-abi.c b/src/lib/lttng-ust/lttng-ust-abi.c index d71a818d..f9bddd01 100644 --- a/src/lib/lttng-ust/lttng-ust-abi.c +++ b/src/lib/lttng-ust/lttng-ust-abi.c @@ -1367,18 +1367,118 @@ objd_error: return ret; } +static +int copy_counter_key(struct lttng_counter_key *internal_key, + unsigned long arg, size_t arg_len, + const struct lttng_ust_abi_counter_event *counter_event) +{ + size_t i, j, nr_dimensions, offset = 0; + char *addr = (char *)arg; + int ret; + + nr_dimensions = counter_event->number_key_dimensions; + if (nr_dimensions != 1) + return -EINVAL; + internal_key->nr_dimensions = nr_dimensions; + offset += counter_event->len; + for (i = 0; i < nr_dimensions; i++) { + const struct lttng_ust_abi_counter_key_dimension *abi_dim; + struct lttng_ust_abi_counter_key_dimension dim; + struct lttng_counter_key_dimension *internal_dim = &internal_key->key_dimensions[i]; + size_t nr_key_tokens; + + abi_dim = (const struct lttng_ust_abi_counter_key_dimension *)(addr + offset); + offset += abi_dim->len; + if (offset > arg_len || abi_dim->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_key_dimension, nr_key_tokens)) + return -EINVAL; + ret = copy_abi_struct(&dim, sizeof(dim), abi_dim, abi_dim->len); + if (ret) + return ret; + nr_key_tokens = dim.nr_key_tokens; + if (!nr_key_tokens || nr_key_tokens > LTTNG_NR_KEY_TOKEN) + return -EINVAL; + internal_dim->nr_key_tokens = nr_key_tokens; + for (j = 0; j < nr_key_tokens; j++) { + const struct lttng_ust_abi_key_token *abi_token; + struct lttng_ust_abi_key_token token; + struct lttng_key_token *internal_token = &internal_dim->key_tokens[j]; + + abi_token = (const struct lttng_ust_abi_key_token *)(addr + offset); + offset += abi_token->len; + if (offset > arg_len || abi_token->len < lttng_ust_offsetofend(struct lttng_ust_abi_key_token, type)) + return -EINVAL; + ret = copy_abi_struct(&token, sizeof(token), abi_token, abi_token->len); + if (ret) + return ret; + switch (token.type) { + case LTTNG_UST_ABI_KEY_TOKEN_STRING: + { + const struct lttng_ust_abi_counter_key_string *abi_key_string; + + abi_key_string = (const struct lttng_ust_abi_counter_key_string *)(addr + offset); + offset += sizeof(struct lttng_ust_abi_counter_key_string); + if (offset > arg_len) + return -EINVAL; + internal_token->type = LTTNG_KEY_TOKEN_STRING; + if (!abi_key_string->string_len || abi_key_string->string_len > LTTNG_KEY_TOKEN_STRING_LEN_MAX) + return -EINVAL; + offset += abi_key_string->string_len; + if (offset > arg_len) + return -EINVAL; + if (abi_key_string->str[abi_key_string->string_len - 1] != '\0' || + strlen(abi_key_string->str) + 1 != abi_key_string->string_len) + return -EINVAL; + memcpy(internal_token->arg.string, abi_key_string->str, abi_key_string->string_len); + break; + } + case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME: + internal_token->type = LTTNG_KEY_TOKEN_EVENT_NAME; + break; + case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME: + internal_token->type = LTTNG_KEY_TOKEN_PROVIDER_NAME; + break; + default: + return -EINVAL; + } + } + } + return 0; +} + static int lttng_abi_create_event_counter_enabler(int channel_objd, struct lttng_ust_channel_counter *channel, - struct lttng_ust_abi_event *event_param, - const struct lttng_ust_abi_counter_key *key_param, - void *owner, - enum lttng_enabler_format_type format_type) + unsigned long arg, size_t arg_len, void *owner) { + struct lttng_ust_abi_counter_event *abi_counter_event = (struct lttng_ust_abi_counter_event *)arg; + struct lttng_ust_abi_counter_event counter_event = {}; + struct lttng_counter_key counter_key = {}; struct lttng_event_counter_enabler *enabler; + enum lttng_enabler_format_type format_type; int event_objd, ret; - event_param->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0'; + if (arg_len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_event, number_key_dimensions)) { + return -EINVAL; + } + if (arg_len < abi_counter_event->len || + abi_counter_event->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_event, number_key_dimensions)) { + return -EINVAL; + } + ret = copy_abi_struct(&counter_event, sizeof(counter_event), + abi_counter_event, abi_counter_event->len); + if (ret) { + return ret; + } + counter_event.event.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0'; + if (strutils_is_star_glob_pattern(counter_event.event.name)) { + format_type = LTTNG_ENABLER_FORMAT_STAR_GLOB; + } else { + format_type = LTTNG_ENABLER_FORMAT_EVENT; + } + ret = copy_counter_key(&counter_key, arg, arg_len, &counter_event); + if (ret) { + return ret; + } event_objd = objd_alloc(NULL, <tng_event_enabler_ops, owner, "event enabler"); if (event_objd < 0) { @@ -1389,8 +1489,7 @@ int lttng_abi_create_event_counter_enabler(int channel_objd, * We tolerate no failure path after event creation. It will stay * invariant for the rest of the session. */ - enabler = lttng_event_counter_enabler_create(format_type, event_param, - key_param, channel); + enabler = lttng_event_counter_enabler_create(format_type, &counter_event, &counter_key, channel); if (!enabler) { ret = -ENOMEM; goto event_error; @@ -1595,24 +1694,8 @@ long lttng_counter_cmd(int objd, unsigned int cmd, unsigned long arg, } case LTTNG_UST_ABI_COUNTER_EVENT: { - struct lttng_ust_abi_counter_event *counter_event_param = - (struct lttng_ust_abi_counter_event *) arg; - struct lttng_ust_abi_event *event_param = &counter_event_param->event; - struct lttng_ust_abi_counter_key *key_param = &counter_event_param->key; - - if (strutils_is_star_glob_pattern(event_param->name)) { - /* - * If the event name is a star globbing pattern, - * we create the special star globbing enabler. - */ - return lttng_abi_create_event_counter_enabler(objd, counter, - event_param, key_param, owner, - LTTNG_ENABLER_FORMAT_STAR_GLOB); - } else { - return lttng_abi_create_event_counter_enabler(objd, counter, - event_param, key_param, owner, - LTTNG_ENABLER_FORMAT_EVENT); - } + return lttng_abi_create_event_counter_enabler(objd, counter, + arg, uargs->counter_event.len, owner); } case LTTNG_UST_ABI_ENABLE: return lttng_channel_enable(counter->parent); diff --git a/src/lib/lttng-ust/lttng-ust-comm.c b/src/lib/lttng-ust/lttng-ust-comm.c index 423cedbc..fe2437b8 100644 --- a/src/lib/lttng-ust/lttng-ust-comm.c +++ b/src/lib/lttng-ust/lttng-ust-comm.c @@ -1058,6 +1058,7 @@ int handle_message(struct sock_info *sock_info, union lttng_ust_abi_args args; char ctxstr[LTTNG_UST_ABI_SYM_NAME_LEN]; /* App context string. */ ssize_t len; + struct lttng_ust_abi_counter_event *counter_event = NULL; memset(&lur, 0, sizeof(lur)); @@ -1486,20 +1487,24 @@ int handle_message(struct sock_info *sock_info, case LTTNG_UST_ABI_COUNTER_EVENT: { /* Receive struct lttng_ust_abi_counter_event */ - struct lttng_ust_abi_counter_event counter_event; - - if (sizeof(counter_event) != lum->u.counter_event.len) { - DBG("incorrect counter event data message size: %u", lum->u.counter_event.len); + if (lum->u.counter_event.len > LTTNG_UST_ABI_COUNTER_EVENT_MAX_LEN) { + DBG("counter event data message too large: %u", lum->u.counter_event.len); ret = -EINVAL; goto error; } - len = ustcomm_recv_unix_sock(sock, &counter_event, sizeof(counter_event)); + args.counter_event.len = lum->u.counter_event.len; + counter_event = zmalloc(lum->u.counter_event.len); + if (!counter_event) { + ret = -ENOMEM; + goto error; + } + len = ustcomm_recv_unix_sock(sock, counter_event, lum->u.counter_event.len); switch (len) { case 0: /* orderly shutdown */ ret = 0; goto error; default: - if (len == sizeof(counter_event)) { + if (len == lum->u.counter_event.len) { DBG("counter event data received"); break; } else if (len < 0) { @@ -1519,7 +1524,7 @@ int handle_message(struct sock_info *sock_info, } if (ops->cmd) ret = ops->cmd(lum->handle, lum->cmd, - (unsigned long) &counter_event, + (unsigned long) counter_event, &args, sock_info); else ret = -ENOSYS; @@ -1636,6 +1641,7 @@ int handle_message(struct sock_info *sock_info, error: ust_unlock(); + free(counter_event); return ret; }