From: Mathieu Desnoyers Date: Tue, 9 Sep 2014 22:56:13 +0000 (-0400) Subject: Implement support for lttng-modules syscall filtering X-Git-Tag: v2.6.0-rc1~43 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=6e911cad03751b6814fddd65b19a592acdc2b7b7 Implement support for lttng-modules syscall filtering Signed-off-by: Mathieu Desnoyers Signed-off-by: David Goulet --- diff --git a/include/lttng/event.h b/include/lttng/event.h index 40673a4d8..b3bb21507 100644 --- a/include/lttng/event.h +++ b/include/lttng/event.h @@ -343,6 +343,23 @@ extern int lttng_enable_event_with_exclusions(struct lttng_handle *handle, extern int lttng_disable_event(struct lttng_handle *handle, const char *name, const char *channel_name); +/* + * Disable event(s) of a channel and domain. + * + * Takes a struct lttng_event as parameter. + * If channel_name is NULL, the default channel is used (channel0). + * + * Currently, @filter_expression must be NULL. (disabling specific + * filter expressions not implemented) + * Currently, only LTTNG_EVENT_ALL and LTTNG_EVENT_SYSCALL event types + * are implemented for field @ev. + * + * Return 0 on success else a negative LTTng error code. + */ +int lttng_disable_event_ext(struct lttng_handle *handle, + struct lttng_event *ev, const char *channel_name, + const char *filter_expression); + #ifdef __cplusplus } #endif diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index d2673a901..872a6cea1 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -1000,9 +1000,18 @@ error: * Command LTTNG_DISABLE_EVENT processed by the client thread. */ int cmd_disable_event(struct ltt_session *session, int domain, - char *channel_name, char *event_name) + char *channel_name, + struct lttng_event *event) { int ret; + char *event_name; + + event_name = event->name; + + if (event->loglevel_type || event->loglevel || event->enabled + || event->pid || event->filter || event->exclusion) { + return LTTNG_ERR_UNK; + } rcu_read_lock(); @@ -1030,8 +1039,19 @@ int cmd_disable_event(struct ltt_session *session, int domain, goto error; } - ret = event_kernel_disable_tracepoint(kchan, event_name); - if (ret != LTTNG_OK) { + switch (event->type) { + case LTTNG_EVENT_ALL: + case LTTNG_EVENT_TRACEPOINT: + ret = event_kernel_disable_tracepoint(kchan, event_name); + if (ret != LTTNG_OK) { + goto error; + } + break; + case LTTNG_EVENT_SYSCALL: + ret = event_kernel_disable_syscall(kchan, event_name); + break; + default: + ret = LTTNG_ERR_UNK; goto error; } @@ -1062,8 +1082,15 @@ int cmd_disable_event(struct ltt_session *session, int domain, goto error; } - ret = event_ust_disable_tracepoint(usess, uchan, event_name); - if (ret != LTTNG_OK) { + switch (event->type) { + case LTTNG_EVENT_ALL: + ret = event_ust_disable_tracepoint(usess, uchan, event_name); + if (ret != LTTNG_OK) { + goto error; + } + break; + default: + ret = LTTNG_ERR_UNK; goto error; } @@ -1079,6 +1106,14 @@ int cmd_disable_event(struct ltt_session *session, int domain, assert(usess); + switch (event->type) { + case LTTNG_EVENT_ALL: + break; + default: + ret = LTTNG_ERR_UNK; + goto error; + } + agt = trace_ust_find_agent(usess, domain); if (!agt) { ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND; @@ -1113,9 +1148,13 @@ error: * Command LTTNG_DISABLE_ALL_EVENT processed by the client thread. */ int cmd_disable_event_all(struct ltt_session *session, int domain, - char *channel_name) + char *channel_name, + struct lttng_event *event) { int ret; + char *event_name; + + event_name = event->name; rcu_read_lock(); @@ -1143,8 +1182,18 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, goto error; } - ret = event_kernel_disable_all(kchan); - if (ret != LTTNG_OK) { + switch (event->type) { + case LTTNG_EVENT_ALL: + ret = event_kernel_disable_all(kchan); + if (ret != LTTNG_OK) { + goto error; + } + break; + case LTTNG_EVENT_SYSCALL: + ret = event_kernel_disable_syscall(kchan, event_name); + break; + default: + ret = LTTNG_ERR_UNK; goto error; } @@ -1175,8 +1224,15 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, goto error; } - ret = event_ust_disable_all_tracepoints(usess, uchan); - if (ret != 0) { + switch (event->type) { + case LTTNG_EVENT_ALL: + ret = event_ust_disable_all_tracepoints(usess, uchan); + if (ret != 0) { + goto error; + } + break; + default: + ret = LTTNG_ERR_UNK; goto error; } @@ -1192,6 +1248,14 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, assert(usess); + switch (event->type) { + case LTTNG_EVENT_ALL: + break; + default: + ret = LTTNG_ERR_UNK; + goto error; + } + agt = trace_ust_find_agent(usess, domain); if (!agt) { ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND; @@ -1419,12 +1483,23 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, goto error; } - ret = event_kernel_enable_tracepoint(kchan, event); - if (ret != LTTNG_OK) { - if (channel_created) { - /* Let's not leak a useless channel. */ - kernel_destroy_channel(kchan); + switch (event->type) { + case LTTNG_EVENT_ALL: + case LTTNG_EVENT_TRACEPOINT: + ret = event_kernel_enable_tracepoint(kchan, event); + if (ret != LTTNG_OK) { + if (channel_created) { + /* Let's not leak a useless channel. */ + kernel_destroy_channel(kchan); + } + goto error; } + break; + case LTTNG_EVENT_SYSCALL: + ret = event_kernel_enable_syscall(kchan, event->name); + break; + default: + ret = LTTNG_ERR_UNK; goto error; } @@ -1625,7 +1700,7 @@ int cmd_enable_event_all(struct ltt_session *session, switch (event_type) { case LTTNG_EVENT_SYSCALL: - ret = event_kernel_enable_all_syscalls(kchan, kernel_tracer_fd); + ret = event_kernel_enable_syscall(kchan, ""); break; case LTTNG_EVENT_TRACEPOINT: /* diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 5de3590ab..5312eca61 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -43,9 +43,11 @@ int cmd_enable_channel(struct ltt_session *session, /* Event commands */ int cmd_disable_event(struct ltt_session *session, int domain, - char *channel_name, char *event_name); + char *channel_name, + struct lttng_event *event); int cmd_disable_event_all(struct ltt_session *session, int domain, - char *channel_name); + char *channel_name, + struct lttng_event *event); int cmd_add_context(struct ltt_session *session, int domain, char *channel_name, struct lttng_event_context *ctx, int kwpipe); int cmd_set_filter(struct ltt_session *session, int domain, diff --git a/src/bin/lttng-sessiond/event.c b/src/bin/lttng-sessiond/event.c index cdfc1a864..099cbd18d 100644 --- a/src/bin/lttng-sessiond/event.c +++ b/src/bin/lttng-sessiond/event.c @@ -57,21 +57,6 @@ static void add_unique_ust_event(struct lttng_ht *ht, assert(node_ptr == &event->node.node); } -/* - * Setup a lttng_event used to enable *all* syscall tracing. - */ -static void init_syscalls_kernel_event(struct lttng_event *event) -{ - assert(event); - - event->name[0] = '\0'; - /* - * We use LTTNG_EVENT* here since the trace kernel creation will make the - * right changes for the kernel. - */ - event->type = LTTNG_EVENT_SYSCALL; -} - /* * Disable kernel tracepoint event for a channel from the kernel session. */ @@ -104,6 +89,57 @@ error: return ret; } +/* + * Enable kernel system call for a channel from the kernel session. + */ +int event_kernel_enable_syscall(struct ltt_kernel_channel *kchan, + char *syscall_name) +{ + int ret; + + assert(kchan); + + ret = kernel_enable_syscall(syscall_name, kchan); + if (ret < 0) { + ret = LTTNG_ERR_KERN_ENABLE_FAIL; + goto error; + } + + DBG("Kernel event %s enable for channel %s.", + syscall_name, kchan->channel->name); + + ret = LTTNG_OK; + +error: + return ret; +} + +/* + * Disable kernel system call for a channel from the kernel session. + */ +int event_kernel_disable_syscall(struct ltt_kernel_channel *kchan, + char *syscall_name) +{ + int ret; + + assert(kchan); + + ret = kernel_disable_syscall(syscall_name, kchan); + if (ret < 0) { + ret = LTTNG_ERR_KERN_DISABLE_FAIL; + goto error; + } + + DBG("Kernel syscall %s disable for channel %s.", + syscall_name[0] == '\0' ? "" : syscall_name, + kchan->channel->name); + + ret = LTTNG_OK; + +error: + return ret; +} + /* * Disable kernel tracepoint events for a channel from the kernel session. */ @@ -126,15 +162,6 @@ int event_kernel_disable_all_tracepoints(struct ltt_kernel_channel *kchan) return ret; } -/* - * Disable kernel syscall events for a channel from the kernel session. - */ -int event_kernel_disable_all_syscalls(struct ltt_kernel_channel *kchan) -{ - ERR("Cannot disable syscall tracing for existing session. Please destroy session instead."); - return LTTNG_OK; /* Return OK so disable all succeeds */ -} - /* * Disable all kernel event for a channel from the kernel session. */ @@ -147,7 +174,7 @@ int event_kernel_disable_all(struct ltt_kernel_channel *kchan) ret = event_kernel_disable_all_tracepoints(kchan); if (ret != LTTNG_OK) return ret; - ret = event_kernel_disable_all_syscalls(kchan); + ret = event_kernel_disable_syscall(kchan, ""); return ret; } @@ -245,36 +272,6 @@ end: return ret; } -/* - * Enable all kernel sycalls events of a channel of the kernel session. - */ -int event_kernel_enable_all_syscalls(struct ltt_kernel_channel *kchan, - int kernel_tracer_fd) -{ - int ret; - struct lttng_event event; - - assert(kchan); - - init_syscalls_kernel_event(&event); - - DBG("Enabling all syscall tracing"); - - ret = kernel_create_event(&event, kchan); - if (ret < 0) { - if (ret == -EEXIST) { - ret = LTTNG_ERR_KERN_EVENT_EXIST; - } else { - ret = LTTNG_ERR_KERN_ENABLE_FAIL; - } - goto end; - } - - ret = LTTNG_OK; -end: - return ret; -} - /* * Enable all kernel events of a channel of the kernel session. */ @@ -299,7 +296,7 @@ int event_kernel_enable_all(struct ltt_kernel_channel *kchan, * tracepoints did not fail. Future work will allow us to send back * multiple errors to the client in one API call. */ - (void) event_kernel_enable_all_syscalls(kchan, kernel_tracer_fd); + (void) event_kernel_enable_syscall(kchan, ""); end: return tp_ret; diff --git a/src/bin/lttng-sessiond/event.h b/src/bin/lttng-sessiond/event.h index a82a3bbb8..501ee02d1 100644 --- a/src/bin/lttng-sessiond/event.h +++ b/src/bin/lttng-sessiond/event.h @@ -23,16 +23,17 @@ int event_kernel_disable_tracepoint(struct ltt_kernel_channel *kchan, char *event_name); -int event_kernel_disable_all_syscalls(struct ltt_kernel_channel *kchan); +int event_kernel_disable_syscall(struct ltt_kernel_channel *kchan, + char *syscall_name); int event_kernel_disable_all_tracepoints(struct ltt_kernel_channel *kchan); int event_kernel_disable_all(struct ltt_kernel_channel *kchan); int event_kernel_enable_tracepoint(struct ltt_kernel_channel *kchan, struct lttng_event *event); +int event_kernel_enable_syscall(struct ltt_kernel_channel *kchan, + char *syscall_name); int event_kernel_enable_all_tracepoints(struct ltt_kernel_channel *kchan, int kernel_tracer_fd); -int event_kernel_enable_all_syscalls(struct ltt_kernel_channel *kchan, - int kernel_tracer_fd); int event_kernel_enable_all(struct ltt_kernel_channel *kchan, int kernel_tracer_fd); @@ -43,6 +44,7 @@ int event_ust_enable_tracepoint(struct ltt_ust_session *usess, struct lttng_event_exclusion *exclusion); int event_ust_disable_tracepoint(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan, char *event_name); + int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan, char *filter_expression, diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 1fae30f0a..44e9539cb 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -351,6 +351,18 @@ error: return ret; } +int kernel_enable_syscall(const char *syscall_name, + struct ltt_kernel_channel *channel) +{ + return kernctl_enable_syscall(channel->fd, syscall_name); +} + +int kernel_disable_syscall(const char *syscall_name, + struct ltt_kernel_channel *channel) +{ + return kernctl_disable_syscall(channel->fd, syscall_name); +} + /* * Create kernel metadata, open from the kernel tracer and add it to the * kernel session. diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index 681301fc2..291a66c78 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -41,6 +41,10 @@ int kernel_disable_channel(struct ltt_kernel_channel *chan); int kernel_disable_event(struct ltt_kernel_event *event); int kernel_enable_event(struct ltt_kernel_event *event); int kernel_enable_channel(struct ltt_kernel_channel *chan); +int kernel_enable_syscall(const char *syscall_name, + struct ltt_kernel_channel *channel); +int kernel_disable_syscall(const char *syscall_name, + struct ltt_kernel_channel *channel); int kernel_open_metadata(struct ltt_kernel_session *session); int kernel_open_metadata_stream(struct ltt_kernel_session *session); int kernel_open_channel_stream(struct ltt_kernel_channel *channel); diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 2a97c37f6..22dd28e1e 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -3122,17 +3122,21 @@ skip_domain: } case LTTNG_DISABLE_EVENT: { + /* FIXME: passing packed structure to non-packed pointer */ + /* TODO: handle filter */ ret = cmd_disable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type, cmd_ctx->lsm->u.disable.channel_name, - cmd_ctx->lsm->u.disable.name); + &cmd_ctx->lsm->u.disable.event); break; } case LTTNG_DISABLE_ALL_EVENT: { DBG("Disabling all events"); + /* FIXME: passing packed structure to non-packed pointer */ ret = cmd_disable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type, - cmd_ctx->lsm->u.disable.channel_name); + cmd_ctx->lsm->u.disable.channel_name, + &cmd_ctx->lsm->u.disable.event); break; } case LTTNG_ENABLE_CHANNEL: diff --git a/src/bin/lttng/commands/disable_events.c b/src/bin/lttng/commands/disable_events.c index 7972d90a0..1ce687aa4 100644 --- a/src/bin/lttng/commands/disable_events.c +++ b/src/bin/lttng/commands/disable_events.c @@ -37,6 +37,7 @@ static int opt_userspace; static int opt_disable_all; static int opt_jul; static int opt_log4j; +static int opt_event_type; #if 0 /* Not implemented yet */ static char *opt_cmd_name; @@ -46,6 +47,7 @@ static pid_t opt_pid; enum { OPT_HELP = 1, OPT_USERSPACE, + OPT_SYSCALL, OPT_LIST_OPTIONS, }; @@ -61,6 +63,7 @@ static struct poptOption long_options[] = { {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0}, {"log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0}, {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0}, + {"syscall", 0, POPT_ARG_NONE, 0, OPT_SYSCALL, 0, 0}, #if 0 /* Not implemented yet */ {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_cmd_name, OPT_USERSPACE, 0, 0}, @@ -90,6 +93,9 @@ static void usage(FILE *ofp) fprintf(ofp, " -j, --jul Apply for Java application using JUL\n"); fprintf(ofp, " -l, --log4j Apply to Java application using LOG4j\n"); fprintf(ofp, "\n"); + fprintf(ofp, "Event options:\n"); + fprintf(ofp, " --syscall System call event\n"); + fprintf(ofp, "\n"); } static @@ -159,6 +165,7 @@ static int disable_events(char *session_name) int enabled = 1, success = 1; char *event_name, *channel_name = NULL; struct lttng_domain dom; + struct lttng_event event; memset(&dom, 0, sizeof(dom)); @@ -208,8 +215,18 @@ static int disable_events(char *session_name) } } + memset(&event, 0, sizeof(event)); + switch (opt_event_type) { + case LTTNG_EVENT_SYSCALL: + event.type = LTTNG_EVENT_SYSCALL; + break; + default: + event.type = LTTNG_EVENT_ALL; + break; + } + if (opt_disable_all) { - command_ret = lttng_disable_event(handle, NULL, channel_name); + command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL); if (command_ret < 0) { ERR("%s", lttng_strerror(command_ret)); enabled = 1; @@ -218,8 +235,10 @@ static int disable_events(char *session_name) } else { enabled = 0; success = 1; - MSG("All %s events are disabled in channel %s", - get_domain_str(dom.type), print_channel_name(channel_name)); + MSG("All %s %s are disabled in channel %s", + get_domain_str(dom.type), + opt_event_type == LTTNG_EVENT_SYSCALL ? "system calls" : "events", + print_channel_name(channel_name)); } if (lttng_opt_mi) { @@ -235,9 +254,13 @@ static int disable_events(char *session_name) while (event_name != NULL) { DBG("Disabling event %s", event_name); - command_ret = lttng_disable_event(handle, event_name, channel_name); + strncpy(event.name, event_name, sizeof(event.name)); + event.name[sizeof(event.name) - 1] = '\0'; + command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL); if (command_ret < 0) { - ERR("Event %s: %s (channel %s, session %s)", event_name, + ERR("%s %s: %s (channel %s, session %s)", + opt_event_type == LTTNG_EVENT_SYSCALL ? "System call" : "Event", + event_name, lttng_strerror(command_ret), command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ? print_raw_channel_name(channel_name) @@ -246,13 +269,15 @@ static int disable_events(char *session_name) warn = 1; success = 0; /* - * If an error occurred we assume that - * the event is still enabled. + * If an error occurred we assume that the event is still + * enabled. */ enabled = 1; } else { - MSG("%s event %s disabled in channel %s for session %s", - get_domain_str(dom.type), event_name, + MSG("%s %s %s disabled in channel %s for session %s", + get_domain_str(dom.type), + opt_event_type == LTTNG_EVENT_SYSCALL ? "system call" : "event", + event_name, print_channel_name(channel_name), session_name); success = 1; @@ -303,10 +328,14 @@ int cmd_disable_events(int argc, const char **argv) int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1; static poptContext pc; char *session_name = NULL; + int event_type = -1; pc = poptGetContext(NULL, argc, argv, long_options, 0); poptReadDefaultConfig(pc, 0); + /* Default event type */ + opt_event_type = LTTNG_EVENT_ALL; + while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_HELP: @@ -315,6 +344,9 @@ int cmd_disable_events(int argc, const char **argv) case OPT_USERSPACE: opt_userspace = 1; break; + case OPT_SYSCALL: + opt_event_type = LTTNG_EVENT_SYSCALL; + break; case OPT_LIST_OPTIONS: list_cmd_options(stdout, long_options); goto end; @@ -323,6 +355,17 @@ int cmd_disable_events(int argc, const char **argv) ret = CMD_UNDEFINED; goto end; } + + /* Validate event type. Multiple event type are not supported. */ + if (event_type == -1) { + event_type = opt_event_type; + } else { + if (event_type != opt_event_type) { + ERR("Multiple event type not supported."); + ret = CMD_ERROR; + goto end; + } + } } opt_event_list = (char*) poptGetArg(pc); diff --git a/src/bin/lttng/commands/enable_events.c b/src/bin/lttng/commands/enable_events.c index a06dbb760..dc5f51deb 100644 --- a/src/bin/lttng/commands/enable_events.c +++ b/src/bin/lttng/commands/enable_events.c @@ -777,7 +777,8 @@ static int enable_events(char *session_name) break; case LTTNG_EVENT_SYSCALL: if (opt_kernel) { - MSG("All kernel system calls are enabled in channel %s", + MSG("All %s system calls are enabled in channel %s", + get_domain_str(dom.type), print_channel_name(channel_name)); } break; diff --git a/src/common/kernel-ctl/kernel-ctl.c b/src/common/kernel-ctl/kernel-ctl.c index d153a1cff..ce8d8a0eb 100644 --- a/src/common/kernel-ctl/kernel-ctl.c +++ b/src/common/kernel-ctl/kernel-ctl.c @@ -139,6 +139,30 @@ int kernctl_create_channel(int fd, struct lttng_channel_attr *chops) return ioctl(fd, LTTNG_KERNEL_CHANNEL, &channel); } +int kernctl_enable_syscall(int fd, const char *syscall_name) +{ + struct lttng_kernel_event event; + + memset(&event, 0, sizeof(event)); + strncpy(event.name, syscall_name, sizeof(event.name)); + event.name[sizeof(event.name) - 1] = '\0'; + event.instrumentation = LTTNG_KERNEL_SYSCALL; + event.u.syscall.disable = 0; + return ioctl(fd, LTTNG_KERNEL_EVENT, &event); +} + +int kernctl_disable_syscall(int fd, const char *syscall_name) +{ + struct lttng_kernel_event event; + + memset(&event, 0, sizeof(event)); + strncpy(event.name, syscall_name, sizeof(event.name)); + event.name[sizeof(event.name) - 1] = '\0'; + event.instrumentation = LTTNG_KERNEL_SYSCALL; + event.u.syscall.disable = 1; + return ioctl(fd, LTTNG_KERNEL_EVENT, &event); +} + int kernctl_create_stream(int fd) { return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_STREAM, diff --git a/src/common/kernel-ctl/kernel-ctl.h b/src/common/kernel-ctl/kernel-ctl.h index 7c5f8bebe..b67e8e356 100644 --- a/src/common/kernel-ctl/kernel-ctl.h +++ b/src/common/kernel-ctl/kernel-ctl.h @@ -40,6 +40,8 @@ int kernctl_tracer_version(int fd, struct lttng_kernel_tracer_version *v); int kernctl_wait_quiescent(int fd); int kernctl_calibrate(int fd, struct lttng_kernel_calibrate *calibrate); +int kernctl_enable_syscall(int fd, const char *syscall_name); +int kernctl_disable_syscall(int fd, const char *syscall_name); /* Buffer operations */ diff --git a/src/common/lttng-kernel.h b/src/common/lttng-kernel.h index b24225190..a7c9258a7 100644 --- a/src/common/lttng-kernel.h +++ b/src/common/lttng-kernel.h @@ -97,6 +97,10 @@ struct lttng_kernel_function { char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN]; } LTTNG_PACKED; +struct lttng_kernel_syscall { + char disable; +} __attribute__((packed)); + #define LTTNG_KERNEL_EVENT_PADDING1 16 #define LTTNG_KERNEL_EVENT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32 struct lttng_kernel_event { @@ -109,6 +113,7 @@ struct lttng_kernel_event { struct lttng_kernel_kretprobe kretprobe; struct lttng_kernel_kprobe kprobe; struct lttng_kernel_function ftrace; + struct lttng_kernel_syscall syscall; char padding[LTTNG_KERNEL_EVENT_PADDING2]; } u; } LTTNG_PACKED; diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index bae083dd8..ee3f99253 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -227,10 +227,6 @@ struct lttcomm_session_msg { struct lttng_session session; struct lttng_domain domain; union { - struct { - char channel_name[LTTNG_SYMBOL_NAME_LEN]; - char name[NAME_MAX]; - } LTTNG_PACKED disable; /* Event data */ struct { char channel_name[LTTNG_SYMBOL_NAME_LEN]; @@ -249,6 +245,20 @@ struct lttcomm_session_msg { * - unsigned char filter_bytecode[bytecode_len] */ } LTTNG_PACKED enable; + struct { + char channel_name[LTTNG_SYMBOL_NAME_LEN]; + struct lttng_event event LTTNG_PACKED; + /* Length of following filter expression. */ + uint32_t expression_len; + /* Length of following bytecode for filter. */ + uint32_t bytecode_len; + /* + * After this structure, the following variable-length + * items are transmitted: + * - unsigned char filter_expression[expression_len] + * - unsigned char filter_bytecode[bytecode_len] + */ + } LTTNG_PACKED disable; /* Create channel */ struct { struct lttng_channel chan LTTNG_PACKED; diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index cacae13bb..c5aada5be 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -926,6 +926,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, } lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); + /* FIXME: copying non-packed struct to packed struct. */ memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event)); lttng_ctl_copy_string(lsm.session.name, handle->session_name, @@ -1039,19 +1040,34 @@ ask_sessiond: return ret; } -/* - * Disable event(s) of a channel and domain. - * If no event name is specified, all events are disabled. - * If no channel name is specified, the default 'channel0' is used. - * Returns size of returned session payload data or a negative error code. - */ -int lttng_disable_event(struct lttng_handle *handle, const char *name, - const char *channel_name) +int lttng_disable_event_ext(struct lttng_handle *handle, + struct lttng_event *ev, const char *channel_name, + const char *original_filter_expression) { struct lttcomm_session_msg lsm; + char *varlen_data; + int ret = 0; + unsigned int free_filter_expression = 0; + struct filter_parser_ctx *ctx = NULL; + /* + * Cast as non-const since we may replace the filter expression + * by a dynamically allocated string. Otherwise, the original + * string is not modified. + */ + char *filter_expression = (char *) original_filter_expression; - if (handle == NULL) { - return -LTTNG_ERR_INVALID; + if (handle == NULL || ev == NULL) { + ret = -LTTNG_ERR_INVALID; + goto error; + } + + /* Empty filter string will always be rejected by the parser + * anyway, so treat this corner-case early to eliminate + * lttng_fmemopen error for 0-byte allocation. + */ + if (filter_expression && filter_expression[0] == '\0') { + ret = -LTTNG_ERR_INVALID; + goto error; } memset(&lsm, 0, sizeof(lsm)); @@ -1065,20 +1081,132 @@ int lttng_disable_event(struct lttng_handle *handle, const char *name, sizeof(lsm.u.disable.channel_name)); } - lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); - - if (name != NULL && *name != '*') { - lttng_ctl_copy_string(lsm.u.disable.name, name, - sizeof(lsm.u.disable.name)); + if (ev->name[0] != '\0') { lsm.cmd_type = LTTNG_DISABLE_EVENT; } else { lsm.cmd_type = LTTNG_DISABLE_ALL_EVENT; } + lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); + /* FIXME: copying non-packed struct to packed struct. */ + memcpy(&lsm.u.disable.event, ev, sizeof(lsm.u.disable.event)); + lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); + lsm.u.disable.bytecode_len = 0; - return lttng_ctl_ask_sessiond(&lsm, NULL); + /* + * For the JUL domain, a filter is enforced except for the + * disable all event. This is done to avoid having the event in + * all sessions thus filtering by logger name. + */ + if (filter_expression == NULL && + (handle->domain.type != LTTNG_DOMAIN_JUL && + handle->domain.type != LTTNG_DOMAIN_LOG4J)) { + goto ask_sessiond; + } + + /* + * We have a filter, so we need to set up a variable-length + * memory block from where to send the data. + */ + + /* Parse filter expression */ + if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL + || handle->domain.type == LTTNG_DOMAIN_LOG4J) { + if (handle->domain.type == LTTNG_DOMAIN_JUL || + handle->domain.type == LTTNG_DOMAIN_LOG4J) { + char *jul_filter; + + /* Setup JUL filter if needed. */ + jul_filter = set_jul_filter(filter_expression, ev); + if (!jul_filter) { + if (!filter_expression) { + /* No JUL and no filter, just skip everything below. */ + goto ask_sessiond; + } + } else { + /* + * With a JUL filter, the original filter has been added to it + * thus replace the filter expression. + */ + filter_expression = jul_filter; + free_filter_expression = 1; + } + } + + ret = generate_filter(filter_expression, &lsm, &ctx); + if (ret) { + goto filter_error; + } + } + + varlen_data = zmalloc(lsm.u.disable.bytecode_len + + lsm.u.disable.expression_len); + if (!varlen_data) { + ret = -LTTNG_ERR_EXCLUSION_NOMEM; + goto mem_error; + } + + /* Add filter expression */ + if (lsm.u.disable.expression_len != 0) { + memcpy(varlen_data, + filter_expression, + lsm.u.disable.expression_len); + } + /* Add filter bytecode next */ + if (ctx && lsm.u.disable.bytecode_len != 0) { + memcpy(varlen_data + + lsm.u.disable.expression_len, + &ctx->bytecode->b, + lsm.u.disable.bytecode_len); + } + + ret = lttng_ctl_ask_sessiond_varlen(&lsm, varlen_data, + lsm.u.disable.bytecode_len + lsm.u.disable.expression_len, NULL); + free(varlen_data); + +mem_error: + if (filter_expression && ctx) { + filter_bytecode_free(ctx); + filter_ir_free(ctx); + filter_parser_ctx_free(ctx); + } +filter_error: + if (free_filter_expression) { + /* + * The filter expression has been replaced and must be freed as it is + * not the original filter expression received as a parameter. + */ + free(filter_expression); + } +error: + /* + * Return directly to the caller and don't ask the sessiond since something + * went wrong in the parsing of data above. + */ + return ret; + +ask_sessiond: + ret = lttng_ctl_ask_sessiond(&lsm, NULL); + return ret; +} + +/* + * Disable event(s) of a channel and domain. + * If no event name is specified, all events are disabled. + * If no channel name is specified, the default 'channel0' is used. + * Returns size of returned session payload data or a negative error code. + */ +int lttng_disable_event(struct lttng_handle *handle, const char *name, + const char *channel_name) +{ + struct lttng_event ev; + + memset(&ev, 0, sizeof(ev)); + ev.type = LTTNG_EVENT_ALL; + lttng_ctl_copy_string(ev.name, name, sizeof(ev.name)); + return lttng_disable_event_ext(handle, &ev, channel_name, NULL); } /*