} __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,
};
#include <wrapper/frame.h>
#include <lttng-filter.h>
+#include <lttng-string-utils.h>
LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode);
}
}
+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)
{
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) {
}
}
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) {
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) {
}
/* 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) {
[ 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,
/* 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,
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;
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);
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;
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;
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);
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);
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;
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)
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)
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;
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;
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;
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;
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:
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)) {
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;
* 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;
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;
}
goto error_unknown;
case REG_STRING:
+ case REG_STAR_GLOB_STRING:
goto error_mismatch;
case REG_S64:
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:
/* 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;
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:
{
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;
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:
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;
/* load from immediate operand */
case FILTER_OP_LOAD_STRING:
+ case FILTER_OP_LOAD_STAR_GLOB_STRING:
{
break;
}
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;
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:
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)) {
REG_S64,
REG_DOUBLE,
REG_STRING,
+ REG_STAR_GLOB_STRING,
REG_TYPE_UNKNOWN,
};
}
/* 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;
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;