X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Flttng-syscalls.c;h=d618bd33ae02474338608cc429dcb06dd461c004;hb=7f52f0d4228ee23b783e907258835d2f818350d7;hp=2e8324133d53ed069ec325bd29fd958ca6360d28;hpb=c3fb484e598a4c08aa096901b611af7311ad77ca;p=lttng-modules.git diff --git a/src/lttng-syscalls.c b/src/lttng-syscalls.c index 2e832413..d618bd33 100644 --- a/src/lttng-syscalls.c +++ b/src/lttng-syscalls.c @@ -130,6 +130,15 @@ struct lttng_syscall_filter { DECLARE_BITMAP(sc_exit, NR_syscalls); DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls); DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls); + + /* + * Reference counters keeping track of number of events enabled + * for each bit. + */ + u32 sc_entry_refcount_map[NR_syscalls]; + u32 sc_exit_refcount_map[NR_syscalls]; + u32 sc_compat_entry_refcount_map[NR_compat_syscalls]; + u32 sc_compat_exit_refcount_map[NR_compat_syscalls]; }; static void syscall_entry_event_unknown(struct hlist_head *unknown_action_list_head, @@ -642,14 +651,15 @@ void lttng_syscall_event_enabler_create_matching_syscall_table_events(struct ltt const struct lttng_kernel_event_desc *desc; unsigned int i; - if (!IS_ENABLED(CONFIG_COMPAT) && (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)) +#ifndef CONFIG_COMPAT + if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT) return; - +#endif /* iterate over all syscall and create event that match */ for (i = 0; i < table_len; i++) { struct lttng_kernel_event_common_private *event_priv; struct hlist_head *head; - int found = 0; + bool found = false; desc = table[i].desc; if (!desc) { @@ -665,8 +675,10 @@ void lttng_syscall_event_enabler_create_matching_syscall_table_events(struct ltt */ head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name); lttng_hlist_for_each_entry(event_priv, head, hlist_node) { - if (lttng_event_enabler_desc_match_event(syscall_event_enabler_common, desc, event_priv->pub)) - found = 1; + if (lttng_event_enabler_desc_match_event(syscall_event_enabler_common, desc, event_priv->pub)) { + found = true; + break; + } } if (found) continue; @@ -700,9 +712,10 @@ void create_unknown_syscall_event(struct lttng_event_enabler_common *event_enabl bool found = false; struct hlist_head *head; - if (!IS_ENABLED(CONFIG_COMPAT) && (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)) +#ifndef CONFIG_COMPAT + if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT) return; - +#endif /* * Considering that currently system calls can only be enabled on a per * name basis (or wildcard based on a name), unknown syscall events are @@ -741,8 +754,10 @@ void create_unknown_syscall_event(struct lttng_event_enabler_common *event_enabl */ head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name); lttng_hlist_for_each_entry(event_priv, head, hlist_node) { - if (lttng_event_enabler_desc_match_event(event_enabler, desc, event_priv->pub)) + if (lttng_event_enabler_desc_match_event(event_enabler, desc, event_priv->pub)) { found = true; + break; + } } if (!found) lttng_syscall_event_enabler_create_event(event_enabler, desc, unknown_dispatch_list, type, -1U); @@ -967,6 +982,7 @@ int lttng_syscall_filter_enable( { const char *syscall_name; unsigned long *bitmap; + u32 *refcount_map; int syscall_nr; syscall_name = get_syscall_name(desc_name, abi, entryexit); @@ -989,9 +1005,11 @@ int lttng_syscall_filter_enable( switch (abi) { case LTTNG_SYSCALL_ABI_NATIVE: bitmap = filter->sc_entry; + refcount_map = filter->sc_entry_refcount_map; break; case LTTNG_SYSCALL_ABI_COMPAT: bitmap = filter->sc_compat_entry; + refcount_map = filter->sc_compat_entry_refcount_map; break; default: return -EINVAL; @@ -1001,9 +1019,11 @@ int lttng_syscall_filter_enable( switch (abi) { case LTTNG_SYSCALL_ABI_NATIVE: bitmap = filter->sc_exit; + refcount_map = filter->sc_exit_refcount_map; break; case LTTNG_SYSCALL_ABI_COMPAT: bitmap = filter->sc_compat_exit; + refcount_map = filter->sc_compat_exit_refcount_map; break; default: return -EINVAL; @@ -1012,9 +1032,10 @@ int lttng_syscall_filter_enable( default: return -EINVAL; } - if (test_bit(syscall_nr, bitmap)) - return -EEXIST; - bitmap_set(bitmap, syscall_nr, 1); + if (refcount_map[syscall_nr] == U32_MAX) + return -EOVERFLOW; + if (refcount_map[syscall_nr]++ == 0) + bitmap_set(bitmap, syscall_nr, 1); return 0; } @@ -1027,6 +1048,10 @@ int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event) 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); @@ -1077,6 +1102,7 @@ int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter, { const char *syscall_name; unsigned long *bitmap; + u32 *refcount_map; int syscall_nr; syscall_name = get_syscall_name(desc_name, abi, entryexit); @@ -1099,9 +1125,11 @@ int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter, switch (abi) { case LTTNG_SYSCALL_ABI_NATIVE: bitmap = filter->sc_entry; + refcount_map = filter->sc_entry_refcount_map; break; case LTTNG_SYSCALL_ABI_COMPAT: bitmap = filter->sc_compat_entry; + refcount_map = filter->sc_compat_entry_refcount_map; break; default: return -EINVAL; @@ -1111,9 +1139,11 @@ int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter, switch (abi) { case LTTNG_SYSCALL_ABI_NATIVE: bitmap = filter->sc_exit; + refcount_map = filter->sc_exit_refcount_map; break; case LTTNG_SYSCALL_ABI_COMPAT: bitmap = filter->sc_compat_exit; + refcount_map = filter->sc_compat_exit_refcount_map; break; default: return -EINVAL; @@ -1122,18 +1152,23 @@ int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter, default: return -EINVAL; } - if (!test_bit(syscall_nr, bitmap)) - return -EEXIST; - bitmap_clear(bitmap, syscall_nr, 1); - + if (refcount_map[syscall_nr] == 0) + return -ENOENT; + if (--refcount_map[syscall_nr] == 0) + bitmap_clear(bitmap, syscall_nr, 1); return 0; } int lttng_syscall_filter_disable_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; 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);