From 12e579dbcb23fab949879ed03a1757d22bd8a6b2 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 15 Sep 2014 13:15:02 -0400 Subject: [PATCH] implement syscall mask getter Signed-off-by: Mathieu Desnoyers --- lttng-abi.c | 3 ++ lttng-abi.h | 7 +++++ lttng-events.h | 11 +++++++ lttng-syscalls.c | 82 ++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 93 insertions(+), 10 deletions(-) diff --git a/lttng-abi.c b/lttng-abi.c index 41e5e450..8073e988 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -1170,6 +1170,9 @@ old_ctx_end: case LTTNG_KERNEL_OLD_DISABLE: case LTTNG_KERNEL_DISABLE: return lttng_channel_disable(channel); + case LTTNG_KERNEL_SYSCALL_MASK: + return lttng_channel_syscall_mask(channel, + (struct lttng_kernel_syscall_mask __user *) arg); default: return -ENOIOCTLCMD; } diff --git a/lttng-abi.h b/lttng-abi.h index 7a09fa24..322989a3 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -117,6 +117,11 @@ struct lttng_kernel_calibrate { enum lttng_kernel_calibrate_type type; /* type (input) */ } __attribute__((packed)); +struct lttng_kernel_syscall_mask { + uint32_t len; /* in bits */ + char mask[]; +} __attribute__((packed)); + enum lttng_kernel_context_type { LTTNG_KERNEL_CONTEXT_PID = 0, LTTNG_KERNEL_CONTEXT_PERF_COUNTER = 1, @@ -171,6 +176,8 @@ struct lttng_kernel_context { #define LTTNG_KERNEL_STREAM _IO(0xF6, 0x62) #define LTTNG_KERNEL_EVENT \ _IOW(0xF6, 0x63, struct lttng_kernel_event) +#define LTTNG_KERNEL_SYSCALL_MASK \ + _IOWR(0xF6, 0x64, struct lttng_kernel_syscall_mask) /* Event and Channel FD ioctl */ #define LTTNG_KERNEL_CONTEXT \ diff --git a/lttng-events.h b/lttng-events.h index 92a61789..a537673a 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -405,6 +405,8 @@ int lttng_syscall_filter_enable(struct lttng_channel *chan, const char *name); int lttng_syscall_filter_disable(struct lttng_channel *chan, const char *name); +long lttng_channel_syscall_mask(struct lttng_channel *channel, + struct lttng_kernel_syscall_mask __user *usyscall_mask); #else static inline int lttng_syscalls_register(struct lttng_channel *chan, void *filter) { @@ -416,17 +418,26 @@ static inline int lttng_syscalls_unregister(struct lttng_channel *chan) return 0; } +static int lttng_syscall_filter_enable(struct lttng_channel *chan, const char *name) { return -ENOSYS; } +static int lttng_syscall_filter_disable(struct lttng_channel *chan, const char *name) { return -ENOSYS; } + +static +long lttng_channel_syscall_mask(struct lttng_channel *channel, + struct lttng_kernel_syscall_mask __user *usyscall_mask) +{ + return -ENOSYS; +} #endif struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx); diff --git a/lttng-syscalls.c b/lttng-syscalls.c index 0a8074f8..96d90c58 100644 --- a/lttng-syscalls.c +++ b/lttng-syscalls.c @@ -31,6 +31,7 @@ #include #include +#include "lib/bitfield.h" #include "wrapper/tracepoint.h" #include "lttng-events.h" @@ -950,6 +951,12 @@ int get_compat_syscall_nr(const char *syscall_name) return syscall_nr; } +static +uint32_t get_sc_tables_len(void) +{ + return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table); +} + int lttng_syscall_filter_enable(struct lttng_channel *chan, const char *name) { @@ -1112,22 +1119,40 @@ void syscall_list_stop(struct seq_file *m, void *p) { } +static +int get_sc_table(const struct trace_syscall_entry *entry, + const struct trace_syscall_entry **table, + unsigned int *bitness) +{ + if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) { + if (bitness) + *bitness = BITS_PER_LONG; + if (table) + *table = sc_table; + return 0; + } + if (!(entry >= compat_sc_table + && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) { + return -EINVAL; + } + if (bitness) + *bitness = 32; + if (table) + *table = compat_sc_table; + return 0; +} + static int syscall_list_show(struct seq_file *m, void *p) { const struct trace_syscall_entry *table, *entry = p; unsigned int bitness; + int ret; - if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) { - bitness = BITS_PER_LONG; - table = sc_table; - } else { - bitness = 32; - table = compat_sc_table; - WARN_ON_ONCE(!(entry >= compat_sc_table - && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))); - } - seq_printf(m, "syscall { id = %u; name = %s; bitness = %u; };\n", + ret = get_sc_table(entry, &table, &bitness); + if (ret) + return ret; + seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n", entry - table, entry->desc->name, bitness); @@ -1155,3 +1180,40 @@ const struct file_operations lttng_syscall_list_fops = { .llseek = seq_lseek, .release = seq_release, }; + +long lttng_channel_syscall_mask(struct lttng_channel *channel, + struct lttng_kernel_syscall_mask __user *usyscall_mask) +{ + uint32_t len, sc_tables_len, bitmask_len; + int ret = 0, bit; + char *tmp_mask; + struct lttng_syscall_filter *filter; + + ret = get_user(len, &usyscall_mask->len); + if (ret) + return ret; + sc_tables_len = get_sc_tables_len(); + bitmask_len = ALIGN(sc_tables_len, 8) >> 3; + if (len < sc_tables_len) { + return put_user(sc_tables_len, &usyscall_mask->len); + } + /* Array is large enough, we can copy array to user-space. */ + tmp_mask = kzalloc(bitmask_len, GFP_KERNEL); + if (!tmp_mask) + return -ENOMEM; + filter = channel->sc_filter; + + for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) { + bt_bitfield_write_be(tmp_mask, char, bit, 1, + test_bit(bit, filter->sc)); + } + for (; bit < sc_tables_len; bit++) { + bt_bitfield_write_be(tmp_mask, char, bit, 1, + test_bit(bit - ARRAY_SIZE(sc_table), + filter->sc_compat)); + } + if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len)) + ret = -EFAULT; + kfree(tmp_mask); + return ret; +} -- 2.34.1