From 9897fbc95aea23f996b7543d86363a3dd72a0c53 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Tue, 8 Mar 2016 12:08:12 -0500 Subject: [PATCH] Fix: Only save kernel enablers in session configuration MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The session configuration serialization currently saves the kernel enablers along with all enabled syscalls. In the case where a syscall would be enabled with a given filter, this would result in two events being enabled: 1) the syscall with its filter expression (the enabler) 2) the syscall on its own (an enabled syscall) The observable effect of this is that the syscall ends up being traced regardless of the filter's evaluation. Signed-off-by: Jérémie Galarneau --- src/bin/lttng-sessiond/save.c | 57 ---------------- src/bin/lttng-sessiond/syscall.c | 110 ------------------------------- src/bin/lttng-sessiond/syscall.h | 2 - 3 files changed, 169 deletions(-) diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index b33287855..1a98515fa 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -502,57 +502,6 @@ end: return ret; } -static -int save_kernel_syscall(struct config_writer *writer, - struct ltt_kernel_channel *kchan) -{ - int ret, i; - ssize_t count; - struct lttng_event *events = NULL; - - assert(writer); - assert(kchan); - - count = syscall_list_channel(kchan, &events, 0); - if (!count) { - /* No syscalls, just gracefully return. */ - ret = 0; - goto end; - } - - for (i = 0; i < count; i++) { - struct ltt_kernel_event *kevent; - - /* Create a temporary kevent in order to save it. */ - /* - * TODO: struct lttng_event does not really work for a filter, - * but unfortunately, it is exposed as external API (and used as - * internal representation. Using NULL meanwhile. - */ - kevent = trace_kernel_create_event(&events[i], - NULL, NULL); - if (!kevent) { - ret = -ENOMEM; - goto end; - } - /* Init list in order so the destroy call can del the node. */ - CDS_INIT_LIST_HEAD(&kevent->list); - - ret = save_kernel_event(writer, kevent); - trace_kernel_destroy_event(kevent); - if (ret) { - goto end; - } - } - - /* Everything went well */ - ret = 0; - -end: - free(events); - return ret; -} - static int save_kernel_events(struct config_writer *writer, struct ltt_kernel_channel *kchan) @@ -573,12 +522,6 @@ int save_kernel_events(struct config_writer *writer, } } - /* Save syscalls if any. */ - ret = save_kernel_syscall(writer, kchan); - if (ret) { - goto end; - } - /* /events */ ret = config_writer_close_element(writer); if (ret) { diff --git a/src/bin/lttng-sessiond/syscall.c b/src/bin/lttng-sessiond/syscall.c index 4c491995a..7ae6682bb 100644 --- a/src/bin/lttng-sessiond/syscall.c +++ b/src/bin/lttng-sessiond/syscall.c @@ -333,113 +333,3 @@ error: rcu_read_unlock(); return ret; } - -/* - * Add enabled syscall to the events list using the given kernel channel. - * - * Return the number of entry of the events array that is different from size - * if the array grows. On error, return negative value and events is untouched. - */ -ssize_t syscall_list_channel(struct ltt_kernel_channel *kchan, - struct lttng_event **_events, size_t size) -{ - int err, i; - size_t new_size; - ssize_t ret, count; - char *mask = NULL; - uint32_t len; - struct lttng_event *events = NULL; - /* Hash table used to filter duplicate out. */ - struct lttng_ht *syscalls_ht = NULL; - - assert(kchan); - - /* Get syscall mask from the kernel tracer. */ - err = kernel_syscall_mask(kchan->fd, &mask, &len); - if (err < 0) { - ret = err; - goto error; - } - - ret = init_syscall_ht(&syscalls_ht); - if (ret < 0) { - goto error; - } - - count = new_size = size; - events = *_events; - - for (i = 0; i < len; i++) { - unsigned char val; - struct syscall *ksyscall; - - bitfield_read_be(mask, unsigned char, i, 1, &val); - if (!val) { - /* Syscall is disabled, continue the loop. */ - continue; - } - - /* Skip empty syscall. */ - if (*syscall_table[i].name == '\0') { - continue; - } - - /* Syscall is enabled thus add it to the events list. */ - - if (count >= new_size) { - struct lttng_event *new_events; - - /* Get the maximum here since count can be 0. */ - new_size = max(count << 1, 1); - DBG3("Listing syscall realloc events array from %zu to %zu", count, - new_size); - new_events = realloc(events, new_size * sizeof(*new_events)); - if (!new_events) { - PERROR("realloc kernel events list"); - ret = -ENOMEM; - goto error; - } - memset(new_events + count, 0, - (new_size - count) * sizeof(*new_events)); - events = new_events; - } - - rcu_read_lock(); - ksyscall = lookup_syscall(syscalls_ht, syscall_table[i].name); - if (ksyscall) { - update_event_syscall_bitness(events, i, ksyscall->index); - rcu_read_unlock(); - continue; - } - ksyscall = NULL; - rcu_read_unlock(); - - ret = add_syscall_to_ht(syscalls_ht, i, count); - if (ret < 0) { - goto error; - } - - update_event_syscall_bitness(events, i, count); - strncpy(events[count].name, syscall_table[i].name, - sizeof(events[count].name)); - events[count].enabled = 1; - events[count].type = LTTNG_EVENT_SYSCALL; - count++; - } - - rcu_read_lock(); - destroy_syscall_ht(syscalls_ht); - rcu_read_unlock(); - - *_events = events; - - return count; - -error: - rcu_read_lock(); - destroy_syscall_ht(syscalls_ht); - rcu_read_unlock(); - - free(events); - return ret; -} diff --git a/src/bin/lttng-sessiond/syscall.h b/src/bin/lttng-sessiond/syscall.h index 97fb66960..5f065cdbe 100644 --- a/src/bin/lttng-sessiond/syscall.h +++ b/src/bin/lttng-sessiond/syscall.h @@ -53,7 +53,5 @@ extern struct syscall *syscall_table; /* Use to list kernel system calls. */ int syscall_init_table(void); ssize_t syscall_table_list(struct lttng_event **events); -ssize_t syscall_list_channel(struct ltt_kernel_channel *kchan, - struct lttng_event **_events, size_t size); #endif /* SYSCALL_H */ -- 2.34.1