X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Flttng-syscalls.c;h=bd836c001d658257e5bf529d61a3cbeabc84a168;hb=HEAD;hp=d618bd33ae02474338608cc429dcb06dd461c004;hpb=7f52f0d4228ee23b783e907258835d2f818350d7;p=lttng-modules.git diff --git a/src/lttng-syscalls.c b/src/lttng-syscalls.c index d618bd33..827ca1d3 100644 --- a/src/lttng-syscalls.c +++ b/src/lttng-syscalls.c @@ -25,12 +25,13 @@ #include #include -#include #include #include +#include #include #include #include +#include #include "lttng-syscalls.h" @@ -42,7 +43,14 @@ /* in_compat_syscall appears in kernel 4.6. */ #ifndef in_compat_syscall - #define in_compat_syscall() is_compat_task() +# define in_compat_syscall() is_compat_task() +#endif + +/* in_x32_syscall appears in kernel 4.7. */ +#if (LTTNG_LINUX_VERSION_CODE < LTTNG_KERNEL_VERSION(4,7,0)) +# ifdef CONFIG_X86_X32_ABI +# define in_x32_syscall() is_x32_task() +# endif #endif enum sc_type { @@ -65,30 +73,6 @@ enum sc_type { void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id); void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret); -/* - * Forward declarations for old kernels. - */ -struct mmsghdr; -struct rlimit64; -struct oldold_utsname; -struct old_utsname; -struct sel_arg_struct; -struct mmap_arg_struct; -struct file_handle; -struct user_msghdr; - -/* - * Forward declaration for kernels >= 5.6 - */ -struct timex; -struct timeval; -struct itimerval; -struct itimerspec; - -#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,6,0)) -typedef __kernel_old_time_t time_t; -#endif - #ifdef IA32_NR_syscalls #define NR_compat_syscalls IA32_NR_syscalls #else @@ -101,14 +85,14 @@ typedef __kernel_old_time_t time_t; #define LTTNG_PACKAGE_BUILD #define CREATE_TRACE_POINTS #define TP_MODULE_NOINIT -#define TRACE_INCLUDE_PATH instrumentation/syscalls/headers +#define TRACE_INCLUDE_PATH instrumentation/syscalls #define PARAMS(args...) args /* Handle unknown syscalls */ #undef TRACE_SYSTEM #define TRACE_SYSTEM syscalls_unknown -#include +#include #undef TRACE_SYSTEM #undef TP_PROBE_CB @@ -265,6 +249,12 @@ void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id) const struct trace_syscall_entry *table, *entry; size_t table_len; +#ifdef CONFIG_X86_X32_ABI + if (in_x32_syscall()) { + /* x32 system calls are not supported. */ + return; + } +#endif if (unlikely(in_compat_syscall())) { struct lttng_syscall_filter *filter = syscall_table->sc_filter; @@ -443,6 +433,12 @@ void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret) size_t table_len; long id; +#ifdef CONFIG_X86_X32_ABI + if (in_x32_syscall()) { + /* x32 system calls are not supported. */ + return; + } +#endif id = syscall_get_nr(current, regs); if (unlikely(in_compat_syscall())) { @@ -535,8 +531,7 @@ struct lttng_kernel_syscall_table *get_syscall_table_from_event(struct lttng_ker static void lttng_syscall_event_enabler_create_event(struct lttng_event_enabler_common *syscall_event_enabler, - const struct lttng_kernel_event_desc *desc, struct hlist_head *dispatch_table, - enum sc_type type, unsigned int syscall_nr) + const struct lttng_kernel_event_desc *desc, enum sc_type type, unsigned int syscall_nr) { struct lttng_kernel_event_common *event; @@ -584,8 +579,6 @@ void lttng_syscall_event_enabler_create_event(struct lttng_event_enabler_common return; } event->priv->u.syscall.syscall_id = syscall_nr; - if (dispatch_table) - hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_table); break; } case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER: @@ -634,8 +627,6 @@ void lttng_syscall_event_enabler_create_event(struct lttng_event_enabler_common return; } event->priv->u.syscall.syscall_id = syscall_nr; - if (dispatch_table) - hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_table); break; } default: @@ -683,7 +674,7 @@ void lttng_syscall_event_enabler_create_matching_syscall_table_events(struct ltt if (found) continue; - lttng_syscall_event_enabler_create_event(syscall_event_enabler_common, desc, NULL, type, i); + lttng_syscall_event_enabler_create_event(syscall_event_enabler_common, desc, type, i); } } @@ -704,11 +695,9 @@ bool lttng_syscall_event_enabler_is_wildcard_all(struct lttng_event_enabler_comm static void create_unknown_syscall_event(struct lttng_event_enabler_common *event_enabler, enum sc_type type) { - struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(event_enabler); struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(event_enabler); struct lttng_kernel_event_common_private *event_priv; const struct lttng_kernel_event_desc *desc; - struct hlist_head *unknown_dispatch_list; bool found = false; struct hlist_head *head; @@ -731,19 +720,15 @@ void create_unknown_syscall_event(struct lttng_event_enabler_common *event_enabl switch (type) { case SC_TYPE_ENTRY: desc = &__event_desc___syscall_entry_unknown; - unknown_dispatch_list = &syscall_table->unknown_syscall_dispatch; break; case SC_TYPE_EXIT: desc = &__event_desc___syscall_exit_unknown; - unknown_dispatch_list = &syscall_table->unknown_syscall_exit_dispatch; break; case SC_TYPE_COMPAT_ENTRY: desc = &__event_desc___compat_syscall_entry_unknown; - unknown_dispatch_list = &syscall_table->compat_unknown_syscall_dispatch; break; case SC_TYPE_COMPAT_EXIT: desc = &__event_desc___compat_syscall_exit_unknown; - unknown_dispatch_list = &syscall_table->compat_unknown_syscall_exit_dispatch; break; default: WARN_ON_ONCE(1); @@ -760,7 +745,7 @@ void create_unknown_syscall_event(struct lttng_event_enabler_common *event_enabl } } if (!found) - lttng_syscall_event_enabler_create_event(event_enabler, desc, unknown_dispatch_list, type, -1U); + lttng_syscall_event_enabler_create_event(event_enabler, desc, type, -1U); } static @@ -831,17 +816,17 @@ int lttng_event_enabler_create_syscall_events_if_missing(struct lttng_event_enab } if (!syscall_table->sys_enter_registered) { - ret = lttng_wrapper_tracepoint_probe_register("sys_enter", + ret = lttng_tracepoint_probe_register("sys_enter", (void *) syscall_entry_event_probe, syscall_table); if (ret) return ret; syscall_table->sys_enter_registered = 1; } if (!syscall_table->sys_exit_registered) { - ret = lttng_wrapper_tracepoint_probe_register("sys_exit", + ret = lttng_tracepoint_probe_register("sys_exit", (void *) syscall_exit_event_probe, syscall_table); if (ret) { - WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter", + WARN_ON_ONCE(lttng_tracepoint_probe_unregister("sys_enter", (void *) syscall_entry_event_probe, syscall_table)); return ret; } @@ -850,7 +835,7 @@ int lttng_event_enabler_create_syscall_events_if_missing(struct lttng_event_enab lttng_syscall_event_enabler_create_matching_events(syscall_event_enabler); - return ret; + return 0; } int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table) @@ -860,14 +845,14 @@ int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *s if (!syscall_table->syscall_dispatch) return 0; if (syscall_table->sys_enter_registered) { - ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter", + ret = lttng_tracepoint_probe_unregister("sys_enter", (void *) syscall_entry_event_probe, syscall_table); if (ret) return ret; syscall_table->sys_enter_registered = 0; } if (syscall_table->sys_exit_registered) { - ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit", + ret = lttng_tracepoint_probe_unregister("sys_exit", (void *) syscall_exit_event_probe, syscall_table); if (ret) return ret; @@ -888,52 +873,6 @@ int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *sysc return 0; } -static -int get_syscall_nr(const char *syscall_name) -{ - int syscall_nr = -1; - int i; - - for (i = 0; i < sc_table.len; i++) { - const struct trace_syscall_entry *entry; - const char *it_name; - - entry = &sc_table.table[i]; - if (!entry->desc) - continue; - it_name = entry->desc->event_name; - it_name += strlen(SYSCALL_ENTRY_STR); - if (!strcmp(syscall_name, it_name)) { - syscall_nr = i; - break; - } - } - return syscall_nr; -} - -static -int get_compat_syscall_nr(const char *syscall_name) -{ - int syscall_nr = -1; - int i; - - for (i = 0; i < compat_sc_table.len; i++) { - const struct trace_syscall_entry *entry; - const char *it_name; - - entry = &compat_sc_table.table[i]; - if (!entry->desc) - continue; - it_name = entry->desc->event_name; - it_name += strlen(COMPAT_SYSCALL_ENTRY_STR); - if (!strcmp(syscall_name, it_name)) { - syscall_nr = i; - break; - } - } - return syscall_nr; -} - static uint32_t get_sc_tables_len(void) { @@ -978,28 +917,15 @@ static int lttng_syscall_filter_enable( struct lttng_syscall_filter *filter, const char *desc_name, enum lttng_syscall_abi abi, - enum lttng_syscall_entryexit entryexit) + enum lttng_syscall_entryexit entryexit, + unsigned int syscall_id) { const char *syscall_name; unsigned long *bitmap; u32 *refcount_map; - int syscall_nr; syscall_name = get_syscall_name(desc_name, abi, entryexit); - switch (abi) { - case LTTNG_SYSCALL_ABI_NATIVE: - syscall_nr = get_syscall_nr(syscall_name); - break; - case LTTNG_SYSCALL_ABI_COMPAT: - syscall_nr = get_compat_syscall_nr(syscall_name); - break; - default: - return -EINVAL; - } - if (syscall_nr < 0) - return -ENOENT; - switch (entryexit) { case LTTNG_SYSCALL_ENTRY: switch (abi) { @@ -1032,10 +958,10 @@ int lttng_syscall_filter_enable( default: return -EINVAL; } - if (refcount_map[syscall_nr] == U32_MAX) + if (refcount_map[syscall_id] == U32_MAX) return -EOVERFLOW; - if (refcount_map[syscall_nr]++ == 0) - bitmap_set(bitmap, syscall_nr, 1); + if (refcount_map[syscall_id]++ == 0) + bitmap_set(bitmap, syscall_id, 1); return 0; } @@ -1044,50 +970,81 @@ int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event) struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event); unsigned int syscall_id = event->priv->u.syscall.syscall_id; struct hlist_head *dispatch_list; - int ret; + int ret = 0; WARN_ON_ONCE(event->priv->instrumentation != LTTNG_KERNEL_ABI_SYSCALL); - /* Skip unknown syscall */ - if (syscall_id == -1U) - return 0; - - ret = lttng_syscall_filter_enable(syscall_table->sc_filter, - event->priv->desc->event_name, event->priv->u.syscall.abi, - event->priv->u.syscall.entryexit); - if (ret) - return ret; - - switch (event->priv->u.syscall.entryexit) { - case LTTNG_SYSCALL_ENTRY: - switch (event->priv->u.syscall.abi) { - case LTTNG_SYSCALL_ABI_NATIVE: - dispatch_list = &syscall_table->syscall_dispatch[syscall_id]; + /* Unknown syscall */ + if (syscall_id == -1U) { + switch (event->priv->u.syscall.entryexit) { + case LTTNG_SYSCALL_ENTRY: + switch (event->priv->u.syscall.abi) { + case LTTNG_SYSCALL_ABI_NATIVE: + dispatch_list = &syscall_table->unknown_syscall_dispatch; + break; + case LTTNG_SYSCALL_ABI_COMPAT: + dispatch_list = &syscall_table->compat_unknown_syscall_dispatch; + break; + default: + ret = -EINVAL; + goto end; + } break; - case LTTNG_SYSCALL_ABI_COMPAT: - dispatch_list = &syscall_table->compat_syscall_dispatch[syscall_id]; + case LTTNG_SYSCALL_EXIT: + switch (event->priv->u.syscall.abi) { + case LTTNG_SYSCALL_ABI_NATIVE: + dispatch_list = &syscall_table->unknown_syscall_exit_dispatch; + break; + case LTTNG_SYSCALL_ABI_COMPAT: + dispatch_list = &syscall_table->compat_unknown_syscall_exit_dispatch; + break; + default: + ret = -EINVAL; + goto end; + } break; default: ret = -EINVAL; goto end; } - break; - case LTTNG_SYSCALL_EXIT: - switch (event->priv->u.syscall.abi) { - case LTTNG_SYSCALL_ABI_NATIVE: - dispatch_list = &syscall_table->syscall_exit_dispatch[syscall_id]; + } else { + ret = lttng_syscall_filter_enable(syscall_table->sc_filter, + event->priv->desc->event_name, event->priv->u.syscall.abi, + event->priv->u.syscall.entryexit, syscall_id); + if (ret) + return ret; + + switch (event->priv->u.syscall.entryexit) { + case LTTNG_SYSCALL_ENTRY: + switch (event->priv->u.syscall.abi) { + case LTTNG_SYSCALL_ABI_NATIVE: + dispatch_list = &syscall_table->syscall_dispatch[syscall_id]; + break; + case LTTNG_SYSCALL_ABI_COMPAT: + dispatch_list = &syscall_table->compat_syscall_dispatch[syscall_id]; + break; + default: + ret = -EINVAL; + goto end; + } break; - case LTTNG_SYSCALL_ABI_COMPAT: - dispatch_list = &syscall_table->compat_syscall_exit_dispatch[syscall_id]; + case LTTNG_SYSCALL_EXIT: + switch (event->priv->u.syscall.abi) { + case LTTNG_SYSCALL_ABI_NATIVE: + dispatch_list = &syscall_table->syscall_exit_dispatch[syscall_id]; + break; + case LTTNG_SYSCALL_ABI_COMPAT: + dispatch_list = &syscall_table->compat_syscall_exit_dispatch[syscall_id]; + break; + default: + ret = -EINVAL; + goto end; + } break; default: ret = -EINVAL; goto end; } - break; - default: - ret = -EINVAL; - goto end; } hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_list); @@ -1098,28 +1055,15 @@ end: static int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter, const char *desc_name, enum lttng_syscall_abi abi, - enum lttng_syscall_entryexit entryexit) + enum lttng_syscall_entryexit entryexit, + unsigned int syscall_id) { const char *syscall_name; unsigned long *bitmap; u32 *refcount_map; - int syscall_nr; syscall_name = get_syscall_name(desc_name, abi, entryexit); - switch (abi) { - case LTTNG_SYSCALL_ABI_NATIVE: - syscall_nr = get_syscall_nr(syscall_name); - break; - case LTTNG_SYSCALL_ABI_COMPAT: - syscall_nr = get_compat_syscall_nr(syscall_name); - break; - default: - return -EINVAL; - } - if (syscall_nr < 0) - return -ENOENT; - switch (entryexit) { case LTTNG_SYSCALL_ENTRY: switch (abi) { @@ -1152,10 +1096,10 @@ int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter, default: return -EINVAL; } - if (refcount_map[syscall_nr] == 0) + if (refcount_map[syscall_id] == 0) return -ENOENT; - if (--refcount_map[syscall_nr] == 0) - bitmap_clear(bitmap, syscall_nr, 1); + if (--refcount_map[syscall_id] == 0) + bitmap_clear(bitmap, syscall_id, 1); return 0; } @@ -1165,15 +1109,14 @@ int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event) unsigned int syscall_id = event->priv->u.syscall.syscall_id; int ret; - /* Skip unknown syscall */ - if (syscall_id == -1U) - return 0; - - ret = lttng_syscall_filter_disable(syscall_table->sc_filter, - event->priv->desc->event_name, event->priv->u.syscall.abi, - event->priv->u.syscall.entryexit); - if (ret) - return ret; + /* Except for unknown syscall */ + if (syscall_id != -1U) { + ret = lttng_syscall_filter_disable(syscall_table->sc_filter, + event->priv->desc->event_name, event->priv->u.syscall.abi, + event->priv->u.syscall.entryexit, syscall_id); + if (ret) + return ret; + } hlist_del_rcu(&event->priv->u.syscall.node); return 0; } @@ -1367,35 +1310,3 @@ long lttng_syscall_table_get_active_mask(struct lttng_kernel_syscall_table *sysc kfree(tmp_mask); return ret; } - -int lttng_abi_syscall_list(void) -{ - struct file *syscall_list_file; - int file_fd, ret; - - file_fd = lttng_get_unused_fd(); - if (file_fd < 0) { - ret = file_fd; - goto fd_error; - } - - syscall_list_file = anon_inode_getfile("[lttng_syscall_list]", - <tng_syscall_list_fops, - NULL, O_RDWR); - if (IS_ERR(syscall_list_file)) { - ret = PTR_ERR(syscall_list_file); - goto file_error; - } - ret = lttng_syscall_list_fops.open(NULL, syscall_list_file); - if (ret < 0) - goto open_error; - fd_install(file_fd, syscall_list_file); - return file_fd; - -open_error: - fput(syscall_list_file); -file_error: - put_unused_fd(file_fd); -fd_error: - return ret; -}