Introduce emission site for syscall event rule
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 16 Apr 2021 21:24:20 +0000 (17:24 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 22 Apr 2021 05:42:49 +0000 (01:42 -0400)
The tracer support multiple emission site configuration: entry, exit,
both.

On the CLI, the emission site is exposed directly on the event rule type
with the following syntax:

 --type=syscall:entry
 --type=syscall:exit
 --type=syscall:entry+exit

`--type=syscall` is equivalent to `--type=syscall:entry+exit`.

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I65faea6872f121b98b781d931b6cc7301f20a0b6

include/lttng/event-rule/syscall-internal.h
include/lttng/event-rule/syscall.h
src/bin/lttng-sessiond/trace-kernel.c
src/bin/lttng/commands/add_trigger.c
src/bin/lttng/commands/list_triggers.c
src/common/event-rule/syscall.c
tests/regression/tools/notification/notification.c
tests/regression/tools/trigger/test_add_trigger_cli
tests/regression/tools/trigger/test_list_triggers_cli
tests/unit/test_event_rule.c

index b72274f5b15841c1955d6e5ca6e77b7d88800603..bd0c1114add8d8adfb3ce62527457967aaed17b0 100644 (file)
@@ -15,6 +15,7 @@
 
 struct lttng_event_rule_syscall {
        struct lttng_event_rule parent;
+       enum lttng_event_rule_syscall_emission_site_type emission_site_type;
        char *pattern;
        char *filter_expression;
 
@@ -26,6 +27,7 @@ struct lttng_event_rule_syscall {
 };
 
 struct lttng_event_rule_syscall_comm {
+       uint32_t emission_site_type;
        /* Includes terminator `\0`. */
        uint32_t pattern_len;
        /* Includes terminator `\0`. */
@@ -43,4 +45,7 @@ ssize_t lttng_event_rule_syscall_create_from_payload(
                struct lttng_payload_view *view,
                struct lttng_event_rule **rule);
 
+LTTNG_HIDDEN
+const char *lttng_event_rule_syscall_emission_site_str(
+               enum lttng_event_rule_syscall_emission_site_type type);
 #endif /* LTTNG_EVENT_RULE_SYSCALL_INTERNAL_H */
index c581b809cf18a5a67993c11043e748525424aa1a..28766ecba3662f6472d837dfbff3352e4f4c168e 100644 (file)
 extern "C" {
 #endif
 
+enum lttng_event_rule_syscall_emission_site_type {
+       LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY_EXIT = 0,
+       LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY = 1,
+       LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_EXIT = 2,
+       LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_UNKNOWN = -1,
+};
+
 /*
  * Create a newly allocated syscall event rule.
  *
  * The default pattern is '*'.
+ * The default emission site type is LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY_EXIT.
  *
  * Returns a new event rule on success, NULL on failure. This event rule must be
  * destroyed using lttng_event_rule_destroy().
  */
-extern struct lttng_event_rule *lttng_event_rule_syscall_create(void);
+extern struct lttng_event_rule *lttng_event_rule_syscall_create(enum
+               lttng_event_rule_syscall_emission_site_type emission_site_type);
 
 /*
  * Set the pattern of a syscall event rule.
@@ -78,6 +87,15 @@ extern enum lttng_event_rule_status lttng_event_rule_syscall_set_filter(
 extern enum lttng_event_rule_status lttng_event_rule_syscall_get_filter(
                const struct lttng_event_rule *rule, const char **expression);
 
+/*
+ * Get the emission site type of a syscall event rule.
+ *
+ * Returns a enum lttng_event_rule_syscall_emission_site_type.
+ */
+extern enum lttng_event_rule_syscall_emission_site_type
+lttng_event_rule_syscall_get_emission_site_type(
+               const struct lttng_event_rule *rule);
+
 #ifdef __cplusplus
 }
 #endif
index dc15829ba5c6488424327404922c665f4bc08f4f..382902a901ee321e5f7ec6d01ce547fe91f7d156 100644 (file)
@@ -676,15 +676,35 @@ enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule(
                const enum lttng_event_rule_status status =
                                lttng_event_rule_syscall_get_pattern(
                                                rule, &name);
+               const enum lttng_event_rule_syscall_emission_site_type
+                       emission_site_type =
+                       lttng_event_rule_syscall_get_emission_site_type(rule);
+               enum lttng_kernel_syscall_entryexit entryexit;
 
                assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+               assert(emission_site_type != LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_UNKNOWN);
+
+               switch(emission_site_type) {
+               case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY:
+                       entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
+                       break;
+               case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_EXIT:
+                       entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
+                       break;
+               case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY_EXIT:
+                       entryexit = LTTNG_KERNEL_SYSCALL_ENTRYEXIT;
+                       break;
+               default:
+                       abort();
+                       break;
+               }
 
                kernel_event_notifier->event.instrumentation =
                                LTTNG_KERNEL_SYSCALL;
                kernel_event_notifier->event.u.syscall.abi =
                                LTTNG_KERNEL_SYSCALL_ABI_ALL;
                kernel_event_notifier->event.u.syscall.entryexit =
-                               LTTNG_KERNEL_SYSCALL_ENTRY;
+                               entryexit;
                kernel_event_notifier->event.u.syscall.match =
                                LTTNG_KERNEL_SYSCALL_MATCH_NAME;
                ret_code = LTTNG_OK;
index 570ba4cf6de2da4e478c7aa49201558cc0da59b2..9e70df107dccd97defadd720881f4b386f3d7796 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <ctype.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "../command.h"
 #include "../loglevel.h"
@@ -126,13 +127,25 @@ bool assign_event_rule_type(enum lttng_event_rule_type *dest, const char *arg)
 
        if (strcmp(arg, "tracepoint") == 0 || strcmp(arg, "logging") == 0) {
                *dest = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
-       } else if (strcmp (arg, "kprobe") == 0 || strcmp(arg, "kernel-probe") == 0) {
+       } else if (strcmp(arg, "kprobe") == 0 ||
+                       strcmp(arg, "kernel-probe") == 0) {
                *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE;
-       } else if (strcmp (arg, "uprobe") == 0 || strcmp(arg, "userspace-probe") == 0) {
+       } else if (strcmp(arg, "uprobe") == 0 ||
+                       strcmp(arg, "userspace-probe") == 0) {
                *dest = LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE;
-       } else if (strcmp (arg, "function") == 0) {
+       } else if (strcmp(arg, "function") == 0) {
                *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION;
-       } else if (strcmp (arg, "syscall") == 0) {
+       } else if (strncmp(arg, "syscall", strlen("syscall")) == 0) {
+               /*
+                * Matches the following:
+                *   - syscall
+                *   - syscall:entry
+                *   - syscall:exit
+                *   - syscall:entry+exit
+                *   - syscall:*
+                *
+                * Validation for the right side is left to further usage sites.
+                */
                *dest = LTTNG_EVENT_RULE_TYPE_SYSCALL;
        } else {
                ERR("Invalid `--type` value: %s", arg);
@@ -175,6 +188,27 @@ end:
        return ret;
 }
 
+static bool parse_syscall_emission_site_from_type(const char *str,
+               enum lttng_event_rule_syscall_emission_site_type *type)
+{
+       bool ret = false;
+       if (strcmp(str, "syscall") == 0 ||
+                       strcmp(str, "syscall:entry+exit") == 0) {
+               *type = LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY_EXIT;
+       } else if (strcmp(str, "syscall:entry") == 0) {
+               *type = LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY;
+       } else if (strcmp(str, "syscall:exit") == 0) {
+               *type = LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_EXIT;
+       } else {
+               goto error;
+       }
+
+       ret = true;
+
+error:
+       return ret;
+}
+
 /* This is defined in enable_events.c. */
 LTTNG_HIDDEN
 int create_exclusion_list_and_validate(const char *event_name,
@@ -622,6 +656,9 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
        struct filter_parser_ctx *parser_ctx = NULL;
        struct lttng_log_level_rule *log_level_rule = NULL;
 
+       /* Event rule type option */
+       char *event_rule_type_str = NULL;
+
        /* Tracepoint and syscall options. */
        char *name = NULL;
        char *exclude_names = NULL;
@@ -681,6 +718,13 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
                                        goto error;
                                }
 
+                               /* Save the string for later use. */
+                               if (!assign_string(&event_rule_type_str,
+                                                   item_opt->arg,
+                                                   "--type/-t")) {
+                                       goto error;
+                               }
+
                                break;
                        case OPT_LOCATION:
                                if (!assign_string(&location,
@@ -1077,8 +1121,15 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
        case LTTNG_EVENT_RULE_TYPE_SYSCALL:
        {
                enum lttng_event_rule_status event_rule_status;
+               enum lttng_event_rule_syscall_emission_site_type emission_site_type;
+
+               if (!parse_syscall_emission_site_from_type(
+                                   event_rule_type_str, &emission_site_type)) {
+                       ERR("Failed to parse syscall type '%s'.", event_rule_type_str);
+                       goto error;
+               }
 
-               res.er = lttng_event_rule_syscall_create();
+               res.er = lttng_event_rule_syscall_create(emission_site_type);
                if (!res.er) {
                        ERR("Failed to create syscall event rule.");
                        goto error;
@@ -1131,6 +1182,7 @@ end:
        free(log_level_str);
        free(location);
        free(event_name);
+       free(event_rule_type_str);
 
        strutils_free_null_terminated_array_of_strings(exclusion_list);
        lttng_kernel_probe_location_destroy(kernel_probe_location);
index bb118e56a217f48c70aeb78a309d28f8c84259ea..8be31933629a27ba8f92bd79f72d3b66da2f4c08 100644 (file)
@@ -18,6 +18,8 @@
 #include "lttng/condition/on-event-internal.h"
 /* For lttng_domain_type_str(). */
 #include "lttng/domain-internal.h"
+/* For lttng_event_rule_syscall_emission_site_str() */
+#include "lttng/event-rule/syscall-internal.h"
 #include "../loglevel.h"
 #include <lttng/lttng.h>
 
@@ -387,14 +389,20 @@ void print_event_rule_syscall(const struct lttng_event_rule *event_rule)
 {
        const char *pattern, *filter;
        enum lttng_event_rule_status event_rule_status;
+       enum lttng_event_rule_syscall_emission_site_type emission_site_type;
 
        assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL);
 
+       emission_site_type =
+               lttng_event_rule_syscall_get_emission_site_type(event_rule);
+
        event_rule_status = lttng_event_rule_syscall_get_pattern(
                        event_rule, &pattern);
        assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
 
-       _MSG("    rule: %s (type: syscall", pattern);
+       _MSG("    rule: %s (type: syscall:%s", pattern,
+                       lttng_event_rule_syscall_emission_site_str(
+                                       emission_site_type));
 
        event_rule_status = lttng_event_rule_syscall_get_filter(
                        event_rule, &filter);
index fbaa65310a6966548690bbb7db65c9c6ca91712b..12aeacfcff9a88fbe4f4904a14b9502c692123d1 100644 (file)
@@ -88,6 +88,7 @@ static int lttng_event_rule_syscall_serialize(
 
        syscall_comm.pattern_len = pattern_len;
        syscall_comm.filter_expression_len = filter_expression_len;
+       syscall_comm.emission_site_type = syscall->emission_site_type;
 
        ret = lttng_dynamic_buffer_append(
                        &payload->buffer, &syscall_comm, sizeof(syscall_comm));
@@ -246,12 +247,25 @@ lttng_event_rule_syscall_hash(
        return hash;
 }
 
-struct lttng_event_rule *lttng_event_rule_syscall_create(void)
+struct lttng_event_rule *lttng_event_rule_syscall_create(
+               enum lttng_event_rule_syscall_emission_site_type
+                               emission_site_type)
 {
        struct lttng_event_rule *rule = NULL;
        struct lttng_event_rule_syscall *syscall_rule;
        enum lttng_event_rule_status status;
 
+       /* Validate the emission site type */
+       switch (emission_site_type) {
+       case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY_EXIT:
+       case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY:
+       case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_EXIT:
+               break;
+       default:
+               /* Invalid emission type */
+               goto end;
+       }
+
        syscall_rule = zmalloc(sizeof(struct lttng_event_rule_syscall));
        if (!syscall_rule) {
                goto end;
@@ -281,6 +295,9 @@ struct lttng_event_rule *lttng_event_rule_syscall_create(void)
                rule = NULL;
        }
 
+       /* Emission site type */
+       syscall_rule->emission_site_type = emission_site_type;
+
 end:
        return rule;
 }
@@ -317,7 +334,7 @@ ssize_t lttng_event_rule_syscall_create_from_payload(
        }
 
        syscall_comm = (typeof(syscall_comm)) current_buffer_view.data;
-       rule = lttng_event_rule_syscall_create();
+       rule = lttng_event_rule_syscall_create(syscall_comm->emission_site_type);
        if (!rule) {
                ERR("Failed to create event rule syscall");
                ret = -1;
@@ -500,3 +517,37 @@ enum lttng_event_rule_status lttng_event_rule_syscall_get_filter(
 end:
        return status;
 }
+extern enum lttng_event_rule_syscall_emission_site_type
+lttng_event_rule_syscall_get_emission_site_type(
+               const struct lttng_event_rule *rule)
+{
+       enum lttng_event_rule_syscall_emission_site_type emission_site_type =
+               LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_UNKNOWN;
+       struct lttng_event_rule_syscall *syscall;
+
+       if (!rule || !IS_SYSCALL_EVENT_RULE(rule)) {
+               goto end;
+       }
+
+       syscall = container_of(rule, struct lttng_event_rule_syscall, parent);
+       emission_site_type = syscall->emission_site_type;
+
+end:
+       return emission_site_type;
+}
+
+LTTNG_HIDDEN
+const char *lttng_event_rule_syscall_emission_site_str(
+               enum lttng_event_rule_syscall_emission_site_type type)
+{
+       switch (type) {
+       case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY:
+               return "entry";
+       case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY_EXIT:
+               return "entry+exit";
+       case LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_EXIT:
+               return "exit";
+       default:
+               return "???";
+       }
+}
index e26c99d033129940128584bca9bcb7b9d18a597f..7e11bc280116360542940bc812575e930e1a0dbf 100644 (file)
@@ -2056,7 +2056,7 @@ static void test_syscall_event_rule_notification(
                        lttng_session_daemon_notification_endpoint);
        ok(notification_channel, "Notification channel object creation");
 
-       event_rule = lttng_event_rule_syscall_create();
+       event_rule = lttng_event_rule_syscall_create(LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY);
        ok(event_rule, "syscall event rule object creation");
 
        event_rule_status = lttng_event_rule_syscall_set_pattern(
@@ -2146,7 +2146,7 @@ static void test_syscall_event_rule_notification_filter(
                        lttng_session_daemon_notification_endpoint);
        ok(notification_channel, "Notification channel object creation");
 
-       event_rule = lttng_event_rule_syscall_create();
+       event_rule = lttng_event_rule_syscall_create(LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY);
        ok(event_rule, "syscall event rule object creation");
 
        event_rule_status = lttng_event_rule_syscall_set_pattern(
index 06bd2d3deecafd5c0577a552251e74980d5b677c..de50c9f0fe25ed5277c71e4ee4e8018d0b865a61 100755 (executable)
@@ -23,7 +23,7 @@ TESTDIR="$CURDIR/../../.."
 # shellcheck source=../../../utils/utils.sh
 source "$TESTDIR/utils/utils.sh"
 
-plan_tests 264
+plan_tests 276
 
 FULL_LTTNG_BIN="${TESTDIR}/../src/bin/lttng/${LTTNG_BIN}"
 
@@ -182,7 +182,7 @@ skip $ist_root "non-root user: skipping uprobe tests" 12 || {
        done
 }
 
-skip $ist_root "non-root user: skipping syscall tests" 9 || {
+skip $ist_root "non-root user: skipping syscall tests" 18 || {
        test_success "--condition event-rule-matches one syscall" \
                --condition event-rule-matches --domain=kernel --type=syscall --name=open \
                --action notify
@@ -194,6 +194,15 @@ skip $ist_root "non-root user: skipping syscall tests" 9 || {
        test_success "--condition event-rule-matches one syscall with filter" \
                --condition event-rule-matches --domain=kernel --type=syscall --filter 'a > 2' --name=open \
                --action notify
+       test_success "--condition event-rule-matches one syscall:entry" \
+               --condition event-rule-matches --domain=kernel --type=syscall:entry --name=open \
+               --action notify
+       test_success "--condition event-rule-matches one syscall:exit" \
+               --condition event-rule-matches --domain=kernel --type=syscall:exit --name=open \
+               --action notify
+       test_success "--condition event-rule-matches one syscall:entry-exit" \
+               --condition event-rule-matches --domain=kernel --type=syscall:entry+exit --name=open \
+               --action notify
 }
 
 # `--action notify` successes
@@ -357,6 +366,11 @@ test_failure "--condition event-rule-matches: extra argument with --type=syscall
        "Error: Unexpected argument 'open'" \
        --condition event-rule-matches --domain=kernel --type=syscall open
 
+test_failure "--condition event-rule-matches: --type=syscall:nope" \
+       "Error: Failed to parse syscall type 'syscall:nope'." \
+       --condition event-rule-matches --domain=kernel --type=syscall:nope \
+       --name=open
+
 test_failure "--condition event-rule-matches --capture: missing argument (end of arg list)" \
        'Error: While parsing argument #2 (`--capture`): Missing required argument for option `--capture`' \
        --action notify \
index 89c77eb54d41b20c1405441c96229a9b16dad21c..4b4b07c43ce6c4479555b1925298555349140b9a 100755 (executable)
@@ -23,7 +23,7 @@ TESTDIR="$CURDIR/../../.."
 # shellcheck source=../../../utils/utils.sh
 source "$TESTDIR/utils/utils.sh"
 
-NUM_TESTS=100
+NUM_TESTS=106
 
 FULL_LTTNG_BIN="${TESTDIR}/../src/bin/lttng/${LTTNG_BIN}"
 
@@ -324,13 +324,16 @@ test_on_event_syscall ()
        diag "Listing on-event syscall"
 
        lttng_add_trigger_ok "T0" --condition event-rule-matches --domain=kernel --type=syscall --name=open --action notify
-       lttng_add_trigger_ok "T1" --condition event-rule-matches --domain=kernel --type=syscall --name=ptrace --filter 'a > 2' --action notify
+       lttng_add_trigger_ok "T1" --condition event-rule-matches --domain=kernel --type=syscall:entry --name=open --action notify       
+       lttng_add_trigger_ok "T2" --condition event-rule-matches --domain=kernel --type=syscall:exit --name=open --action notify
+       lttng_add_trigger_ok "T3" --condition event-rule-matches --domain=kernel --type=syscall:entry+exit --name=open --action notify
+       lttng_add_trigger_ok "T4" --condition event-rule-matches --domain=kernel --type=syscall --name=ptrace --filter 'a > 2' --action notify
 
        cat > "${tmp_expected_stdout}" <<- EOF
        - name: T0
          owner uid: ${uid}
          condition: event rule hit
-           rule: open (type: syscall)
+           rule: open (type: syscall:entry+exit)
          actions:
            notify
              errors: none
@@ -338,7 +341,31 @@ test_on_event_syscall ()
        - name: T1
          owner uid: ${uid}
          condition: event rule hit
-           rule: ptrace (type: syscall, filter: a > 2)
+           rule: open (type: syscall:entry)
+         actions:
+           notify
+             errors: none
+         errors: none
+       - name: T2
+         owner uid: ${uid}
+         condition: event rule hit
+           rule: open (type: syscall:exit)
+         actions:
+           notify
+             errors: none
+         errors: none
+       - name: T3
+         owner uid: ${uid}
+         condition: event rule hit
+           rule: open (type: syscall:entry+exit)
+         actions:
+           notify
+             errors: none
+         errors: none
+       - name: T4
+         owner uid: ${uid}
+         condition: event rule hit
+           rule: ptrace (type: syscall:entry+exit, filter: a > 2)
          actions:
            notify
              errors: none
@@ -349,6 +376,9 @@ test_on_event_syscall ()
 
        lttng_remove_trigger_ok "T0"
        lttng_remove_trigger_ok "T1"
+       lttng_remove_trigger_ok "T2"
+       lttng_remove_trigger_ok "T3"
+       lttng_remove_trigger_ok "T4"
 }
 
 test_session_consumed_size_condition ()
@@ -612,7 +642,7 @@ test_on_event_tracepoint
 skip $ist_root "non-root user: skipping kprobe tests" 9 || test_on_event_probe
 skip $ist_root "non-root user: skipping uprobe tests" 5 || test_on_event_userspace_probe_elf
 skip $(($ist_root && $hast_sdt_binary)) "skipping userspace probe SDT tests" 5 || test_on_event_userspace_probe_sdt
-skip $ist_root "non-root user: skipping syscall tests" 7 || test_on_event_syscall
+skip $ist_root "non-root user: skipping syscall tests" 13 || test_on_event_syscall
 test_session_consumed_size_condition
 test_buffer_usage_conditions
 test_session_rotation_conditions
index 6c56bdbdb0867f1cc7122f5a0541fabfea8c96ae..59e37e9662edfeed08d8e71d75658f1871c9d730 100644 (file)
@@ -184,7 +184,7 @@ static void test_event_rule_syscall(void)
 
        lttng_payload_init(&payload);
 
-       syscall = lttng_event_rule_syscall_create();
+       syscall = lttng_event_rule_syscall_create(LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY);
        ok(syscall, "syscall object.");
 
        status = lttng_event_rule_syscall_set_pattern(syscall, pattern);
This page took 0.03309 seconds and 4 git commands to generate.