X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;ds=sidebyside;f=lttng-syscalls.c;h=4eae6747f692c1149adbb5d52fef45a5b8e19ea0;hb=f4855b46cb97a7ad649e97232719c50ab8688119;hp=5023c2f9dcc2ff8c588ad159303255dabab92ac6;hpb=cb3ef14c052adc12da2b9e26aebf9fc6e7d82fa3;p=lttng-modules.git diff --git a/lttng-syscalls.c b/lttng-syscalls.c index 5023c2f9..4eae6747 100644 --- a/lttng-syscalls.c +++ b/lttng-syscalls.c @@ -27,9 +27,11 @@ #include #include #include +#include #include #include +#include "lib/bitfield.h" #include "wrapper/tracepoint.h" #include "lttng-events.h" @@ -949,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) { @@ -1033,6 +1041,12 @@ int lttng_syscall_filter_disable(struct lttng_channel *chan, filter = chan->sc_filter; } + if (!name) { + /* Disable all system calls */ + bitmap_clear(filter->sc, 0, NR_syscalls); + bitmap_clear(filter->sc_compat, 0, NR_compat_syscalls); + goto apply_filter; + } syscall_nr = get_syscall_nr(name); compat_syscall_nr = get_compat_syscall_nr(name); if (syscall_nr < 0 && compat_syscall_nr < 0) { @@ -1053,6 +1067,7 @@ int lttng_syscall_filter_disable(struct lttng_channel *chan, } bitmap_clear(chan->sc_filter->sc_compat, compat_syscall_nr, 1); } +apply_filter: if (!chan->sc_filter) rcu_assign_pointer(chan->sc_filter, filter); chan->syscall_all = 0; @@ -1063,3 +1078,145 @@ error: kfree(filter); return ret; } + +static +const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos) +{ + const struct trace_syscall_entry *entry; + int iter = 0; + + for (entry = sc_table; + entry < sc_table + ARRAY_SIZE(sc_table); + entry++) { + if (iter++ >= *pos) + return entry; + } + for (entry = compat_sc_table; + entry < compat_sc_table + ARRAY_SIZE(compat_sc_table); + entry++) { + if (iter++ >= *pos) + return entry; + } + /* End of list */ + return NULL; +} + +static +void *syscall_list_start(struct seq_file *m, loff_t *pos) +{ + return (void *) syscall_list_get_entry(pos); +} + +static +void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos) +{ + (*ppos)++; + return (void *) syscall_list_get_entry(ppos); +} + +static +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; + + ret = get_sc_table(entry, &table, &bitness); + if (ret) + return ret; + if (!entry->desc) + return 0; + seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n", + table == sc_table ? entry - table : + (entry - table) + ARRAY_SIZE(sc_table), + entry->desc->name, + bitness); + return 0; +} + +static +const struct seq_operations lttng_syscall_list_seq_ops = { + .start = syscall_list_start, + .next = syscall_list_next, + .stop = syscall_list_stop, + .show = syscall_list_show, +}; + +static +int lttng_syscall_list_open(struct inode *inode, struct file *file) +{ + return seq_open(file, <tng_syscall_list_seq_ops); +} + +const struct file_operations lttng_syscall_list_fops = { + .owner = THIS_MODULE, + .open = lttng_syscall_list_open, + .read = seq_read, + .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; +}