Filtering: add support for star-only globbing patterns
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sun, 19 Feb 2017 01:04:11 +0000 (20:04 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 10 Mar 2017 16:23:20 +0000 (11:23 -0500)
This patch adds the support for "full" star-only globbing patterns to be
used in filter literal strings. A star-only globbing pattern is a
globbing pattern with the star (`*`) being the only special character.
This means `?` and character sets (`[abc-k]`) are not supported here. We
cannot support them without a strategy to differentiate the globbing
pattern because `?` and `[` are not special characters in filter literal
strings right now. The eventual strategy to support them would probably
look like this:

    filename =* "?sys*.[ch]"

The filter bytecode generator in LTTng-tools's session daemon creates
the new FILTER_OP_LOAD_STAR_GLOB_STRING operation when the interpreter
should load a star globbing pattern literal string. Even if both
"plain", or legacy strings and star globbing pattern strings are literal
strings, they do not represent the same thing, that is, the == and !=
operators act differently.

The validation process checks that:

1. There's no binary operator between two
   FILTER_OP_LOAD_STAR_GLOB_STRING operations. It is illegal to compare
   two star globbing patterns, as this is not trivial to implement, and
   completely useless as far as I know.

2. Only the == and != binary operators are allowed between a
   star globbing pattern and a string.

For the special case of star globbing patterns with a star at the end
only, the current behaviour is not changed to preserve a maximum of
backward compatibility. This is also why the ABI version is changed from
2.2 to 2.3, not to 3.0.

== or != operations between REG_STRING and REG_STAR_GLOB_STRING
registers is specialized to FILTER_OP_EQ_STAR_GLOB_STRING and
FILTER_OP_NE_STAR_GLOB_STRING. Which side is the actual globbing pattern
(the one with the REG_STAR_GLOB_STRING type) is checked at execution
time. The strutils_star_glob_match() function is used to perform the
match operation. See the implementation for more details.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
filter-bytecode.h
lttng-filter-interpreter.c
lttng-filter-specialize.c
lttng-filter-validator.c
lttng-filter.h

index 376c75184ff84b937e2680077c2258b91b20d9f6..2c14e223df31b6e1600047a43c83a99d55a103ba 100644 (file)
@@ -49,110 +49,120 @@ struct literal_string {
 } __attribute__((packed));
 
 enum filter_op {
-       FILTER_OP_UNKNOWN = 0,
+       FILTER_OP_UNKNOWN                       = 0,
 
-       FILTER_OP_RETURN,
+       FILTER_OP_RETURN                        = 1,
 
        /* binary */
-       FILTER_OP_MUL,
-       FILTER_OP_DIV,
-       FILTER_OP_MOD,
-       FILTER_OP_PLUS,
-       FILTER_OP_MINUS,
-       FILTER_OP_RSHIFT,
-       FILTER_OP_LSHIFT,
-       FILTER_OP_BIN_AND,
-       FILTER_OP_BIN_OR,
-       FILTER_OP_BIN_XOR,
+       FILTER_OP_MUL                           = 2,
+       FILTER_OP_DIV                           = 3,
+       FILTER_OP_MOD                           = 4,
+       FILTER_OP_PLUS                          = 5,
+       FILTER_OP_MINUS                         = 6,
+       FILTER_OP_RSHIFT                        = 7,
+       FILTER_OP_LSHIFT                        = 8,
+       FILTER_OP_BIN_AND                       = 9,
+       FILTER_OP_BIN_OR                        = 10,
+       FILTER_OP_BIN_XOR                       = 11,
 
        /* binary comparators */
-       FILTER_OP_EQ,
-       FILTER_OP_NE,
-       FILTER_OP_GT,
-       FILTER_OP_LT,
-       FILTER_OP_GE,
-       FILTER_OP_LE,
-
-       /* string binary comparator */
-       FILTER_OP_EQ_STRING,
-       FILTER_OP_NE_STRING,
-       FILTER_OP_GT_STRING,
-       FILTER_OP_LT_STRING,
-       FILTER_OP_GE_STRING,
-       FILTER_OP_LE_STRING,
+       FILTER_OP_EQ                            = 12,
+       FILTER_OP_NE                            = 13,
+       FILTER_OP_GT                            = 14,
+       FILTER_OP_LT                            = 15,
+       FILTER_OP_GE                            = 16,
+       FILTER_OP_LE                            = 17,
+
+       /* string binary comparator: apply to  */
+       FILTER_OP_EQ_STRING                     = 18,
+       FILTER_OP_NE_STRING                     = 19,
+       FILTER_OP_GT_STRING                     = 20,
+       FILTER_OP_LT_STRING                     = 21,
+       FILTER_OP_GE_STRING                     = 22,
+       FILTER_OP_LE_STRING                     = 23,
 
        /* s64 binary comparator */
-       FILTER_OP_EQ_S64,
-       FILTER_OP_NE_S64,
-       FILTER_OP_GT_S64,
-       FILTER_OP_LT_S64,
-       FILTER_OP_GE_S64,
-       FILTER_OP_LE_S64,
+       FILTER_OP_EQ_S64                        = 24,
+       FILTER_OP_NE_S64                        = 25,
+       FILTER_OP_GT_S64                        = 26,
+       FILTER_OP_LT_S64                        = 27,
+       FILTER_OP_GE_S64                        = 28,
+       FILTER_OP_LE_S64                        = 29,
 
        /* double binary comparator */
-       FILTER_OP_EQ_DOUBLE,
-       FILTER_OP_NE_DOUBLE,
-       FILTER_OP_GT_DOUBLE,
-       FILTER_OP_LT_DOUBLE,
-       FILTER_OP_GE_DOUBLE,
-       FILTER_OP_LE_DOUBLE,
+       FILTER_OP_EQ_DOUBLE                     = 30,
+       FILTER_OP_NE_DOUBLE                     = 31,
+       FILTER_OP_GT_DOUBLE                     = 32,
+       FILTER_OP_LT_DOUBLE                     = 33,
+       FILTER_OP_GE_DOUBLE                     = 34,
+       FILTER_OP_LE_DOUBLE                     = 35,
 
        /* Mixed S64-double binary comparators */
-       FILTER_OP_EQ_DOUBLE_S64,
-       FILTER_OP_NE_DOUBLE_S64,
-       FILTER_OP_GT_DOUBLE_S64,
-       FILTER_OP_LT_DOUBLE_S64,
-       FILTER_OP_GE_DOUBLE_S64,
-       FILTER_OP_LE_DOUBLE_S64,
-
-       FILTER_OP_EQ_S64_DOUBLE,
-       FILTER_OP_NE_S64_DOUBLE,
-       FILTER_OP_GT_S64_DOUBLE,
-       FILTER_OP_LT_S64_DOUBLE,
-       FILTER_OP_GE_S64_DOUBLE,
-       FILTER_OP_LE_S64_DOUBLE,
+       FILTER_OP_EQ_DOUBLE_S64                 = 36,
+       FILTER_OP_NE_DOUBLE_S64                 = 37,
+       FILTER_OP_GT_DOUBLE_S64                 = 38,
+       FILTER_OP_LT_DOUBLE_S64                 = 39,
+       FILTER_OP_GE_DOUBLE_S64                 = 40,
+       FILTER_OP_LE_DOUBLE_S64                 = 41,
+
+       FILTER_OP_EQ_S64_DOUBLE                 = 42,
+       FILTER_OP_NE_S64_DOUBLE                 = 43,
+       FILTER_OP_GT_S64_DOUBLE                 = 44,
+       FILTER_OP_LT_S64_DOUBLE                 = 45,
+       FILTER_OP_GE_S64_DOUBLE                 = 46,
+       FILTER_OP_LE_S64_DOUBLE                 = 47,
 
        /* unary */
-       FILTER_OP_UNARY_PLUS,
-       FILTER_OP_UNARY_MINUS,
-       FILTER_OP_UNARY_NOT,
-       FILTER_OP_UNARY_PLUS_S64,
-       FILTER_OP_UNARY_MINUS_S64,
-       FILTER_OP_UNARY_NOT_S64,
-       FILTER_OP_UNARY_PLUS_DOUBLE,
-       FILTER_OP_UNARY_MINUS_DOUBLE,
-       FILTER_OP_UNARY_NOT_DOUBLE,
+       FILTER_OP_UNARY_PLUS                    = 48,
+       FILTER_OP_UNARY_MINUS                   = 49,
+       FILTER_OP_UNARY_NOT                     = 50,
+       FILTER_OP_UNARY_PLUS_S64                = 51,
+       FILTER_OP_UNARY_MINUS_S64               = 52,
+       FILTER_OP_UNARY_NOT_S64                 = 53,
+       FILTER_OP_UNARY_PLUS_DOUBLE             = 54,
+       FILTER_OP_UNARY_MINUS_DOUBLE            = 55,
+       FILTER_OP_UNARY_NOT_DOUBLE              = 56,
 
        /* logical */
-       FILTER_OP_AND,
-       FILTER_OP_OR,
+       FILTER_OP_AND                           = 57,
+       FILTER_OP_OR                            = 58,
 
        /* load field ref */
-       FILTER_OP_LOAD_FIELD_REF,
-       FILTER_OP_LOAD_FIELD_REF_STRING,
-       FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
-       FILTER_OP_LOAD_FIELD_REF_S64,
-       FILTER_OP_LOAD_FIELD_REF_DOUBLE,
+       FILTER_OP_LOAD_FIELD_REF                = 59,
+       FILTER_OP_LOAD_FIELD_REF_STRING         = 60,
+       FILTER_OP_LOAD_FIELD_REF_SEQUENCE       = 61,
+       FILTER_OP_LOAD_FIELD_REF_S64            = 62,
+       FILTER_OP_LOAD_FIELD_REF_DOUBLE         = 63,
 
        /* load immediate from operand */
-       FILTER_OP_LOAD_STRING,
-       FILTER_OP_LOAD_S64,
-       FILTER_OP_LOAD_DOUBLE,
+       FILTER_OP_LOAD_STRING                   = 64,
+       FILTER_OP_LOAD_S64                      = 65,
+       FILTER_OP_LOAD_DOUBLE                   = 66,
 
        /* cast */
-       FILTER_OP_CAST_TO_S64,
-       FILTER_OP_CAST_DOUBLE_TO_S64,
-       FILTER_OP_CAST_NOP,
+       FILTER_OP_CAST_TO_S64                   = 67,
+       FILTER_OP_CAST_DOUBLE_TO_S64            = 68,
+       FILTER_OP_CAST_NOP                      = 69,
 
        /* get context ref */
-       FILTER_OP_GET_CONTEXT_REF,
-       FILTER_OP_GET_CONTEXT_REF_STRING,
-       FILTER_OP_GET_CONTEXT_REF_S64,
-       FILTER_OP_GET_CONTEXT_REF_DOUBLE,
+       FILTER_OP_GET_CONTEXT_REF               = 70,
+       FILTER_OP_GET_CONTEXT_REF_STRING        = 71,
+       FILTER_OP_GET_CONTEXT_REF_S64           = 72,
+       FILTER_OP_GET_CONTEXT_REF_DOUBLE        = 73,
 
        /* load userspace field ref */
-       FILTER_OP_LOAD_FIELD_REF_USER_STRING,
-       FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE,
+       FILTER_OP_LOAD_FIELD_REF_USER_STRING    = 74,
+       FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE  = 75,
+
+       /*
+        * load immediate star globbing pattern (literal string)
+        * from immediate
+        */
+       FILTER_OP_LOAD_STAR_GLOB_STRING         = 76,
+
+       /* globbing pattern binary operator: apply to */
+       FILTER_OP_EQ_STAR_GLOB_STRING           = 77,
+       FILTER_OP_NE_STAR_GLOB_STRING           = 78,
 
        NR_FILTER_OPS,
 };
index 761926f748457e09752eec3b5160dccf0fe2d66a..a09b04175af0c6dc996d297c7bf0af5d93392858 100644 (file)
@@ -28,6 +28,7 @@
 #include <wrapper/frame.h>
 
 #include <lttng-filter.h>
+#include <lttng-string-utils.h>
 
 LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode);
 
@@ -85,6 +86,49 @@ int parse_char(struct estack_entry *reg, char *c, size_t *offset)
        }
 }
 
+static
+char get_char_at_cb(size_t at, void *data)
+{
+       return get_char(data, at);
+}
+
+static
+int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
+{
+       bool has_user = false;
+       mm_segment_t old_fs;
+       int result;
+       struct estack_entry *pattern_reg;
+       struct estack_entry *candidate_reg;
+
+       if (estack_bx(stack, top)->u.s.user
+                       || estack_ax(stack, top)->u.s.user) {
+               has_user = true;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+               pagefault_disable();
+       }
+
+       /* Find out which side is the pattern vs. the candidate. */
+       if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
+               pattern_reg = estack_ax(stack, top);
+               candidate_reg = estack_bx(stack, top);
+       } else {
+               pattern_reg = estack_bx(stack, top);
+               candidate_reg = estack_ax(stack, top);
+       }
+
+       /* Perform the match operation. */
+       result = !strutils_star_glob_match_char_cb(get_char_at_cb,
+               pattern_reg, get_char_at_cb, candidate_reg);
+       if (has_user) {
+               pagefault_enable();
+               set_fs(old_fs);
+       }
+
+       return result;
+}
+
 static
 int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
 {
@@ -113,7 +157,8 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
                                diff = 0;
                                break;
                        } else {
-                               if (estack_ax(stack, top)->u.s.literal) {
+                               if (estack_ax(stack, top)->u.s.literal_type ==
+                                               ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                                        ret = parse_char(estack_ax(stack, top),
                                                &char_ax, &offset_ax);
                                        if (ret == -1) {
@@ -126,7 +171,8 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
                        }
                }
                if (unlikely(char_ax == '\0')) {
-                       if (estack_bx(stack, top)->u.s.literal) {
+                       if (estack_bx(stack, top)->u.s.literal_type ==
+                                       ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                                ret = parse_char(estack_bx(stack, top),
                                        &char_bx, &offset_bx);
                                if (ret == -1) {
@@ -137,7 +183,8 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
                        diff = 1;
                        break;
                }
-               if (estack_bx(stack, top)->u.s.literal) {
+               if (estack_bx(stack, top)->u.s.literal_type ==
+                               ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                        ret = parse_char(estack_bx(stack, top),
                                &char_bx, &offset_bx);
                        if (ret == -1) {
@@ -148,7 +195,8 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
                        }
                        /* else compare both char */
                }
-               if (estack_ax(stack, top)->u.s.literal) {
+               if (estack_ax(stack, top)->u.s.literal_type ==
+                               ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                        ret = parse_char(estack_ax(stack, top),
                                &char_ax, &offset_ax);
                        if (ret == -1) {
@@ -288,6 +336,10 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
                [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
 
+               /* globbing pattern binary comparator */
+               [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
+               [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
+
                /* s64 binary comparator */
                [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
                [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
@@ -343,6 +395,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
 
                /* load from immediate operand */
                [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
+               [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
                [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
                [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
 
@@ -470,6 +523,27 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        PO;
                }
 
+               OP(FILTER_OP_EQ_STAR_GLOB_STRING):
+               {
+                       int res;
+
+                       res = (stack_star_glob_match(stack, top, "==") == 0);
+                       estack_pop(stack, top, ax, bx);
+                       estack_ax_v = res;
+                       next_pc += sizeof(struct binary_op);
+                       PO;
+               }
+               OP(FILTER_OP_NE_STAR_GLOB_STRING):
+               {
+                       int res;
+
+                       res = (stack_star_glob_match(stack, top, "!=") != 0);
+                       estack_pop(stack, top, ax, bx);
+                       estack_ax_v = res;
+                       next_pc += sizeof(struct binary_op);
+                       PO;
+               }
+
                OP(FILTER_OP_EQ_S64):
                {
                        int res;
@@ -653,7 +727,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                goto end;
                        }
                        estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        estack_ax(stack, top)->u.s.user = 0;
                        dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
@@ -678,7 +753,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                ret = -EINVAL;
                                goto end;
                        }
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        estack_ax(stack, top)->u.s.user = 0;
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
                        PO;
@@ -715,7 +791,23 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        estack_push(stack, top, ax, bx);
                        estack_ax(stack, top)->u.s.str = insn->data;
                        estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                       estack_ax(stack, top)->u.s.literal = 1;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_PLAIN;
+                       estack_ax(stack, top)->u.s.user = 0;
+                       next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
+                       PO;
+               }
+
+               OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
+               {
+                       struct load_op *insn = (struct load_op *) pc;
+
+                       dbg_printk("load globbing pattern %s\n", insn->data);
+                       estack_push(stack, top, ax, bx);
+                       estack_ax(stack, top)->u.s.str = insn->data;
+                       estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
                        estack_ax(stack, top)->u.s.user = 0;
                        next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
                        PO;
@@ -779,7 +871,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                goto end;
                        }
                        estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        estack_ax(stack, top)->u.s.user = 0;
                        dbg_printk("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
@@ -828,7 +921,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                goto end;
                        }
                        estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        estack_ax(stack, top)->u.s.user = 1;
                        dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
@@ -853,7 +947,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                ret = -EINVAL;
                                goto end;
                        }
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        estack_ax(stack, top)->u.s.user = 1;
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
                        PO;
index 667689552bbcb5697ee47bd174260f293395f90b..318d051abc1bd2871683bd0b1bf03864b56be774 100644 (file)
@@ -77,7 +77,13 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                                goto end;
 
                        case REG_STRING:
-                               insn->op = FILTER_OP_EQ_STRING;
+                               if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING)
+                                       insn->op = FILTER_OP_EQ_STAR_GLOB_STRING;
+                               else
+                                       insn->op = FILTER_OP_EQ_STRING;
+                               break;
+                       case REG_STAR_GLOB_STRING:
+                               insn->op = FILTER_OP_EQ_STAR_GLOB_STRING;
                                break;
                        case REG_S64:
                                if (vstack_bx(stack)->type == REG_S64)
@@ -113,7 +119,13 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                                goto end;
 
                        case REG_STRING:
-                               insn->op = FILTER_OP_NE_STRING;
+                               if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING)
+                                       insn->op = FILTER_OP_NE_STAR_GLOB_STRING;
+                               else
+                                       insn->op = FILTER_OP_NE_STRING;
+                               break;
+                       case REG_STAR_GLOB_STRING:
+                               insn->op = FILTER_OP_NE_STAR_GLOB_STRING;
                                break;
                        case REG_S64:
                                if (vstack_bx(stack)->type == REG_S64)
@@ -148,6 +160,10 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                                ret = -EINVAL;
                                goto end;
 
+                       case REG_STAR_GLOB_STRING:
+                               printk(KERN_WARNING "invalid register type for > binary operator\n");
+                               ret = -EINVAL;
+                               goto end;
                        case REG_STRING:
                                insn->op = FILTER_OP_GT_STRING;
                                break;
@@ -184,6 +200,10 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                                ret = -EINVAL;
                                goto end;
 
+                       case REG_STAR_GLOB_STRING:
+                               printk(KERN_WARNING "invalid register type for < binary operator\n");
+                               ret = -EINVAL;
+                               goto end;
                        case REG_STRING:
                                insn->op = FILTER_OP_LT_STRING;
                                break;
@@ -220,6 +240,10 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                                ret = -EINVAL;
                                goto end;
 
+                       case REG_STAR_GLOB_STRING:
+                               printk(KERN_WARNING "invalid register type for >= binary operator\n");
+                               ret = -EINVAL;
+                               goto end;
                        case REG_STRING:
                                insn->op = FILTER_OP_GE_STRING;
                                break;
@@ -255,6 +279,10 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                                ret = -EINVAL;
                                goto end;
 
+                       case REG_STAR_GLOB_STRING:
+                               printk(KERN_WARNING "invalid register type for <= binary operator\n");
+                               ret = -EINVAL;
+                               goto end;
                        case REG_STRING:
                                insn->op = FILTER_OP_LE_STRING;
                                break;
@@ -282,6 +310,8 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                case FILTER_OP_LT_STRING:
                case FILTER_OP_GE_STRING:
                case FILTER_OP_LE_STRING:
+               case FILTER_OP_EQ_STAR_GLOB_STRING:
+               case FILTER_OP_NE_STAR_GLOB_STRING:
                case FILTER_OP_EQ_S64:
                case FILTER_OP_NE_S64:
                case FILTER_OP_GT_S64:
@@ -475,6 +505,19 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                        break;
                }
 
+               case FILTER_OP_LOAD_STAR_GLOB_STRING:
+               {
+                       struct load_op *insn = (struct load_op *) pc;
+
+                       if (vstack_push(stack)) {
+                               ret = -EINVAL;
+                               goto end;
+                       }
+                       vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
+                       next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
+                       break;
+               }
+
                case FILTER_OP_LOAD_S64:
                {
                        if (vstack_push(stack)) {
@@ -511,6 +554,7 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                                goto end;
 
                        case REG_STRING:
+                       case REG_STAR_GLOB_STRING:
                                printk(KERN_WARNING "Cast op can only be applied to numeric or floating point registers\n");
                                ret = -EINVAL;
                                goto end;
index 123a13084f92ea5c7b535f67a3c0aecbda9bd4a2..1c30a529a15654553f1cfd09ec81fdf7cfdc0588 100644 (file)
@@ -118,7 +118,8 @@ int merge_point_add_check(struct mp_table *mp_table, unsigned long target_pc,
  * Binary comparators use top of stack and top of stack -1.
  */
 static
-int bin_op_compare_check(struct vstack *stack, const char *str)
+int bin_op_compare_check(struct vstack *stack, const filter_opcode_t opcode,
+               const char *str)
 {
        if (unlikely(!vstack_ax(stack) || !vstack_bx(stack)))
                goto error_unknown;
@@ -136,6 +137,27 @@ int bin_op_compare_check(struct vstack *stack, const char *str)
 
                case REG_STRING:
                        break;
+               case REG_STAR_GLOB_STRING:
+                       if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
+                               goto error_mismatch;
+                       }
+                       break;
+               case REG_S64:
+                       goto error_mismatch;
+               }
+               break;
+       case REG_STAR_GLOB_STRING:
+               switch (vstack_bx(stack)->type) {
+               default:
+               case REG_DOUBLE:
+                       goto error_unknown;
+
+               case REG_STRING:
+                       if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
+                               goto error_mismatch;
+                       }
+                       break;
+               case REG_STAR_GLOB_STRING:
                case REG_S64:
                        goto error_mismatch;
                }
@@ -147,6 +169,7 @@ int bin_op_compare_check(struct vstack *stack, const char *str)
                        goto error_unknown;
 
                case REG_STRING:
+               case REG_STAR_GLOB_STRING:
                        goto error_mismatch;
 
                case REG_S64:
@@ -249,6 +272,8 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
        case FILTER_OP_LT_STRING:
        case FILTER_OP_GE_STRING:
        case FILTER_OP_LE_STRING:
+       case FILTER_OP_EQ_STAR_GLOB_STRING:
+       case FILTER_OP_NE_STAR_GLOB_STRING:
        case FILTER_OP_EQ_S64:
        case FILTER_OP_NE_S64:
        case FILTER_OP_GT_S64:
@@ -320,6 +345,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
 
        /* load from immediate operand */
        case FILTER_OP_LOAD_STRING:
+       case FILTER_OP_LOAD_STAR_GLOB_STRING:
        {
                struct load_op *insn = (struct load_op *) pc;
                uint32_t str_len, maxlen;
@@ -395,8 +421,9 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                char *pc)
 {
        int ret = 0;
+       const filter_opcode_t opcode = *(filter_opcode_t *) pc;
 
-       switch (*(filter_opcode_t *) pc) {
+       switch (opcode) {
        case FILTER_OP_UNKNOWN:
        default:
        {
@@ -457,42 +484,42 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
 
        case FILTER_OP_EQ:
        {
-               ret = bin_op_compare_check(stack, "==");
+               ret = bin_op_compare_check(stack, opcode, "==");
                if (ret)
                        goto end;
                break;
        }
        case FILTER_OP_NE:
        {
-               ret = bin_op_compare_check(stack, "!=");
+               ret = bin_op_compare_check(stack, opcode, "!=");
                if (ret)
                        goto end;
                break;
        }
        case FILTER_OP_GT:
        {
-               ret = bin_op_compare_check(stack, ">");
+               ret = bin_op_compare_check(stack, opcode, ">");
                if (ret)
                        goto end;
                break;
        }
        case FILTER_OP_LT:
        {
-               ret = bin_op_compare_check(stack, "<");
+               ret = bin_op_compare_check(stack, opcode, "<");
                if (ret)
                        goto end;
                break;
        }
        case FILTER_OP_GE:
        {
-               ret = bin_op_compare_check(stack, ">=");
+               ret = bin_op_compare_check(stack, opcode, ">=");
                if (ret)
                        goto end;
                break;
        }
        case FILTER_OP_LE:
        {
-               ret = bin_op_compare_check(stack, "<=");
+               ret = bin_op_compare_check(stack, opcode, "<=");
                if (ret)
                        goto end;
                break;
@@ -519,6 +546,24 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                break;
        }
 
+
+       case FILTER_OP_EQ_STAR_GLOB_STRING:
+       case FILTER_OP_NE_STAR_GLOB_STRING:
+       {
+               if (!vstack_ax(stack) || !vstack_bx(stack)) {
+                       printk(KERN_WARNING "Empty stack\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               if (vstack_ax(stack)->type != REG_STAR_GLOB_STRING
+                               && vstack_bx(stack)->type != REG_STAR_GLOB_STRING) {
+                       printk(KERN_WARNING "Unexpected register type for globbing pattern comparator\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               break;
+       }
+
        case FILTER_OP_EQ_S64:
        case FILTER_OP_NE_S64:
        case FILTER_OP_GT_S64:
@@ -558,6 +603,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        goto end;
 
                case REG_STRING:
+               case REG_STAR_GLOB_STRING:
                        printk(KERN_WARNING "Unary op can only be applied to numeric or floating point registers\n");
                        ret = -EINVAL;
                        goto end;
@@ -642,6 +688,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
 
        /* load from immediate operand */
        case FILTER_OP_LOAD_STRING:
+       case FILTER_OP_LOAD_STAR_GLOB_STRING:
        {
                break;
        }
@@ -668,6 +715,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        goto end;
 
                case REG_STRING:
+               case REG_STAR_GLOB_STRING:
                        printk(KERN_WARNING "Cast op can only be applied to numeric or floating point registers\n");
                        ret = -EINVAL;
                        goto end;
@@ -860,6 +908,8 @@ int exec_insn(struct bytecode_runtime *bytecode,
        case FILTER_OP_LT_STRING:
        case FILTER_OP_GE_STRING:
        case FILTER_OP_LE_STRING:
+       case FILTER_OP_EQ_STAR_GLOB_STRING:
+       case FILTER_OP_NE_STAR_GLOB_STRING:
        case FILTER_OP_EQ_S64:
        case FILTER_OP_NE_S64:
        case FILTER_OP_GT_S64:
@@ -979,6 +1029,19 @@ int exec_insn(struct bytecode_runtime *bytecode,
                break;
        }
 
+       case FILTER_OP_LOAD_STAR_GLOB_STRING:
+       {
+               struct load_op *insn = (struct load_op *) pc;
+
+               if (vstack_push(stack)) {
+                       ret = -EINVAL;
+                       goto end;
+               }
+               vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
+               next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
+               break;
+       }
+
        case FILTER_OP_LOAD_S64:
        {
                if (vstack_push(stack)) {
index 6ce78ac49b2d138e84dcf1f57832caeb29eb8f52..01bafa05f645aa10fbb8d768eadf28cc748ee1a4 100644 (file)
@@ -61,6 +61,7 @@ enum entry_type {
        REG_S64,
        REG_DOUBLE,
        REG_STRING,
+       REG_STAR_GLOB_STRING,
        REG_TYPE_UNKNOWN,
 };
 
@@ -119,6 +120,12 @@ int vstack_pop(struct vstack *stack)
 }
 
 /* Execution stack */
+enum estack_string_literal_type {
+       ESTACK_STRING_LITERAL_TYPE_NONE,
+       ESTACK_STRING_LITERAL_TYPE_PLAIN,
+       ESTACK_STRING_LITERAL_TYPE_STAR_GLOB,
+};
+
 struct estack_entry {
        union {
                int64_t v;
@@ -127,7 +134,7 @@ struct estack_entry {
                        const char *str;
                        const char __user *user_str;
                        size_t seq_len;
-                       int literal;            /* is string literal ? */
+                       enum estack_string_literal_type literal_type;
                        int user;               /* is string from userspace ? */
                } s;
        } u;
This page took 0.038378 seconds and 4 git commands to generate.