From 345beadc701d20d577814d95f81b64c145d815c6 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 24 Mar 2022 14:38:20 -0400 Subject: [PATCH] Implement extensible LTTNG_KERNEL_ABI_COUNTER_MAP_DESCRIPTOR Signed-off-by: Mathieu Desnoyers Change-Id: Ibd16679a5e3354553a9b606a6f3a5f9f2692836d --- include/lttng/abi.h | 17 +++++------ include/lttng/events-internal.h | 3 +- src/lttng-abi.c | 51 ++++++++++++++++++++++----------- src/lttng-events.c | 2 +- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/include/lttng/abi.h b/include/lttng/abi.h index a512c54c..ac5469ed 100644 --- a/include/lttng/abi.h +++ b/include/lttng/abi.h @@ -212,18 +212,19 @@ enum lttng_kernel_abi_counter_bitness { //TODO: remove this define. #define LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX 4 -//TODO: new in 2.14, update. -#define LTTNG_KERNEL_ABI_COUNTER_KEY_LEN 256 -#define LTTNG_KERNEL_ABI_COUNTER_MAP_DESCRIPTOR_PADDING 32 +struct lttng_kernel_abi_counter_key_string { + uint32_t string_len; + char str[]; /* Null-terminated string. */ +} __attribute__((packed)); + struct lttng_kernel_abi_counter_map_descriptor { - uint64_t descriptor_index; /* input. [ 0 .. nr_descriptors - 1 ] */ + uint32_t len; /* length of this structure */ + uint64_t descriptor_index; /* input. [ 0 .. nr_descriptors - 1 ] */ uint32_t dimension; /* outputs */ uint64_t array_index; uint64_t user_token; - char key[LTTNG_KERNEL_ABI_COUNTER_KEY_LEN]; - - char padding[LTTNG_KERNEL_ABI_COUNTER_MAP_DESCRIPTOR_PADDING]; + uint64_t key_ptr; /* pointer to struct lttng_kernel_abi_counter_key_string */ } __attribute__((packed)); //TODO: new in 2.14, update. @@ -506,7 +507,7 @@ struct lttng_kernel_abi_tracker_args { #define LTTNG_KERNEL_ABI_ENABLE _IO(0xF6, 0x82) #define LTTNG_KERNEL_ABI_DISABLE _IO(0xF6, 0x83) -/* Trigger group and session ioctl */ +/* Event notifier group and session ioctl */ /* (0xF6, 0x84) is reserved for old ABI. */ diff --git a/include/lttng/events-internal.h b/include/lttng/events-internal.h index b4d2277b..21ab7926 100644 --- a/include/lttng/events-internal.h +++ b/include/lttng/events-internal.h @@ -261,10 +261,11 @@ struct lttng_kernel_channel_counter_ops_private { size_t *max_nr_elem); /* array of size nr_dimensions */ }; +#define LTTNG_KERNEL_COUNTER_KEY_LEN 256 struct lttng_counter_map_descriptor { uint64_t user_token; size_t array_index; - char key[LTTNG_KERNEL_ABI_COUNTER_KEY_LEN]; + char key[LTTNG_KERNEL_COUNTER_KEY_LEN]; }; struct lttng_counter_map { diff --git a/src/lttng-abi.c b/src/lttng-abi.c index ffe0f109..6471aa66 100644 --- a/src/lttng-abi.c +++ b/src/lttng-abi.c @@ -965,34 +965,53 @@ long lttng_counter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case LTTNG_KERNEL_ABI_COUNTER_MAP_DESCRIPTOR: { - struct lttng_kernel_abi_counter_map_descriptor __user *user_descriptor = + struct lttng_kernel_abi_counter_map_descriptor __user *udescriptor = (struct lttng_kernel_abi_counter_map_descriptor __user *) arg; - struct lttng_kernel_abi_counter_map_descriptor local_descriptor; - struct lttng_counter_map_descriptor *kernel_descriptor; + struct lttng_kernel_abi_counter_key_string __user *ukey_ptr; + struct lttng_kernel_abi_counter_map_descriptor kdescriptor = {}; + struct lttng_counter_map_descriptor *descriptor; + char key[LTTNG_KERNEL_COUNTER_KEY_LEN] = {}; + size_t key_strlen; + uint32_t len, ukey_string_len; int ret; - if (copy_from_user(&local_descriptor, user_descriptor, - sizeof(local_descriptor))) - return -EFAULT; - if (validate_zeroed_padding(local_descriptor.padding, - sizeof(local_descriptor.padding))) + ret = get_user(len, &udescriptor->len); + if (ret) + return ret; + if (len > PAGE_SIZE) + return -E2BIG; + if (!len || len < offsetofend(struct lttng_kernel_abi_counter_map_descriptor, key_ptr)) + return -EINVAL; + ret = lttng_copy_struct_from_user(&kdescriptor, sizeof(kdescriptor), udescriptor, len); + if (ret) + return ret; + ukey_ptr = (struct lttng_kernel_abi_counter_key_string __user *)(unsigned long)kdescriptor.key_ptr; + ret = get_user(ukey_string_len, &ukey_ptr->string_len); + if (ret) + return ret; + if (ukey_string_len > PAGE_SIZE) + return -E2BIG; + if (!ukey_string_len) return -EINVAL; mutex_lock(&counter->priv->map.lock); - if (local_descriptor.descriptor_index >= counter->priv->map.nr_descriptors) { + if (kdescriptor.descriptor_index >= counter->priv->map.nr_descriptors) { ret = -EOVERFLOW; goto map_descriptor_error_unlock; } - kernel_descriptor = &counter->priv->map.descriptors[local_descriptor.descriptor_index]; - local_descriptor.user_token = kernel_descriptor->user_token; - local_descriptor.array_index = kernel_descriptor->array_index; - memcpy(local_descriptor.key, kernel_descriptor->key, LTTNG_KERNEL_ABI_COUNTER_KEY_LEN); + descriptor = &counter->priv->map.descriptors[kdescriptor.descriptor_index]; + kdescriptor.user_token = descriptor->user_token; + kdescriptor.array_index = descriptor->array_index; + memcpy(&key, descriptor->key, LTTNG_KERNEL_COUNTER_KEY_LEN); mutex_unlock(&counter->priv->map.lock); - if (copy_to_user(user_descriptor, &local_descriptor, - sizeof(local_descriptor))) + key_strlen = strlen(key); + if (key_strlen >= ukey_string_len) + return -ENOSPC; + if (copy_to_user(udescriptor, &kdescriptor, min(sizeof(kdescriptor), (size_t)len))) + return -EFAULT; + if (copy_to_user(ukey_ptr->str, key, key_strlen + 1)) return -EFAULT; - return 0; map_descriptor_error_unlock: diff --git a/src/lttng-events.c b/src/lttng-events.c index 007fe80e..72dcbe40 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -1316,7 +1316,7 @@ int lttng_counter_append_descriptor(struct lttng_kernel_channel_counter *counter struct lttng_counter_map_descriptor *last; int ret = 0; - if (strlen(key) >= LTTNG_KERNEL_ABI_COUNTER_KEY_LEN) { + if (strlen(key) >= LTTNG_KERNEL_COUNTER_KEY_LEN) { WARN_ON_ONCE(1); return -EOVERFLOW; } -- 2.34.1