X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttng-filter-validator.c;h=c9094547fa47bef52d0b00e53b609f635d4b87b5;hb=e3888df8ef6dcbc48e13d348b05e40a4f3acf639;hp=cc8f45962c73f51c7a0c944579df6675a447aba0;hpb=3834b99f4341209754c4955ec853dc250b33ed4b;p=lttng-modules.git diff --git a/lttng-filter-validator.c b/lttng-filter-validator.c index cc8f4596..c9094547 100644 --- a/lttng-filter-validator.c +++ b/lttng-filter-validator.c @@ -1,34 +1,16 @@ -/* +/* SPDX-License-Identifier: MIT + * * lttng-filter-validator.c * * LTTng modules filter bytecode validator. * * Copyright (C) 2010-2016 Mathieu Desnoyers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #include #include #include -#include #include #define MERGE_POINT_TABLE_BITS 7 @@ -92,7 +74,7 @@ int merge_point_add_check(struct mp_table *mp_table, unsigned long target_pc, memcpy(&mp_node->stack, stack, sizeof(mp_node->stack)); head = &mp_table->mp_head[hash & (MERGE_POINT_TABLE_SIZE - 1)]; - lttng_hlist_for_each_entry(lookup_node, head, node) { + hlist_for_each_entry(lookup_node, head, node) { if (lttng_hash_match(lookup_node, target_pc)) { found = 1; break; @@ -303,6 +285,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, } case FILTER_OP_RETURN: + case FILTER_OP_RETURN_S64: { if (unlikely(pc + sizeof(struct return_op) > start_pc + bytecode->len)) { @@ -317,8 +300,6 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, case FILTER_OP_MOD: case FILTER_OP_PLUS: case FILTER_OP_MINUS: - case FILTER_OP_RSHIFT: - case FILTER_OP_LSHIFT: case FILTER_OP_EQ_DOUBLE: case FILTER_OP_NE_DOUBLE: case FILTER_OP_GT_DOUBLE: @@ -372,6 +353,8 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, case FILTER_OP_LT_S64: case FILTER_OP_GE_S64: case FILTER_OP_LE_S64: + case FILTER_OP_BIT_RSHIFT: + case FILTER_OP_BIT_LSHIFT: case FILTER_OP_BIT_AND: case FILTER_OP_BIT_OR: case FILTER_OP_BIT_XOR: @@ -390,6 +373,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, case FILTER_OP_UNARY_PLUS_S64: case FILTER_OP_UNARY_MINUS_S64: case FILTER_OP_UNARY_NOT_S64: + case FILTER_OP_UNARY_BIT_NOT: { if (unlikely(pc + sizeof(struct unary_op) > start_pc + bytecode->len)) { @@ -512,6 +496,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_symbol) > start_pc + bytecode->len)) { ret = -ERANGE; + break; } ret = validate_get_symbol(bytecode, sym); break; @@ -552,7 +537,7 @@ unsigned long delete_all_nodes(struct mp_table *mp_table) struct hlist_head *head; head = &mp_table->mp_head[i]; - lttng_hlist_for_each_entry_safe(mp_node, tmp, head, node) { + hlist_for_each_entry_safe(mp_node, tmp, head, node) { kfree(mp_node); nr_nodes++; } @@ -585,6 +570,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, } case FILTER_OP_RETURN: + case FILTER_OP_RETURN_S64: { goto end; } @@ -595,8 +581,6 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, case FILTER_OP_MOD: case FILTER_OP_PLUS: case FILTER_OP_MINUS: - case FILTER_OP_RSHIFT: - case FILTER_OP_LSHIFT: /* Floating point */ case FILTER_OP_EQ_DOUBLE: case FILTER_OP_NE_DOUBLE: @@ -733,6 +717,16 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, break; } + case FILTER_OP_BIT_RSHIFT: + ret = bin_op_bitwise_check(stack, opcode, ">>"); + if (ret < 0) + goto end; + break; + case FILTER_OP_BIT_LSHIFT: + ret = bin_op_bitwise_check(stack, opcode, "<<"); + if (ret < 0) + goto end; + break; case FILTER_OP_BIT_AND: ret = bin_op_bitwise_check(stack, opcode, "&"); if (ret < 0) @@ -777,6 +771,32 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, } break; } + case FILTER_OP_UNARY_BIT_NOT: + { + if (!vstack_ax(stack)) { + printk(KERN_WARNING "Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + default: + printk(KERN_WARNING "unknown register type\n"); + ret = -EINVAL; + goto end; + + case REG_STRING: + case REG_STAR_GLOB_STRING: + case REG_DOUBLE: + printk(KERN_WARNING "Unary bitwise op can only be applied to numeric registers\n"); + ret = -EINVAL; + goto end; + case REG_S64: + break; + case REG_TYPE_UNKNOWN: + break; + } + break; + } case FILTER_OP_UNARY_PLUS_S64: case FILTER_OP_UNARY_MINUS_S64: @@ -1078,7 +1098,7 @@ int validate_instruction_all_contexts(struct bytecode_runtime *bytecode, /* Validate merge points */ hash = jhash_1word(target_pc, 0); head = &mp_table->mp_head[hash & (MERGE_POINT_TABLE_SIZE - 1)]; - lttng_hlist_for_each_entry(mp_node, head, node) { + hlist_for_each_entry(mp_node, head, node) { if (lttng_hash_match(mp_node, target_pc)) { found = 1; break; @@ -1148,14 +1168,34 @@ int exec_insn(struct bytecode_runtime *bytecode, goto end; } + case FILTER_OP_RETURN_S64: + { + if (!vstack_ax(stack)) { + printk(KERN_WARNING "Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + case REG_S64: + break; + default: + case REG_TYPE_UNKNOWN: + printk(KERN_WARNING "Unexpected register type %d at end of bytecode\n", + (int) vstack_ax(stack)->type); + ret = -EINVAL; + goto end; + } + + ret = 0; + goto end; + } + /* binary */ case FILTER_OP_MUL: case FILTER_OP_DIV: case FILTER_OP_MOD: case FILTER_OP_PLUS: case FILTER_OP_MINUS: - case FILTER_OP_RSHIFT: - case FILTER_OP_LSHIFT: /* Floating point */ case FILTER_OP_EQ_DOUBLE: case FILTER_OP_NE_DOUBLE: @@ -1209,6 +1249,8 @@ int exec_insn(struct bytecode_runtime *bytecode, case FILTER_OP_LT_S64: case FILTER_OP_GE_S64: case FILTER_OP_LE_S64: + case FILTER_OP_BIT_RSHIFT: + case FILTER_OP_BIT_LSHIFT: case FILTER_OP_BIT_AND: case FILTER_OP_BIT_OR: case FILTER_OP_BIT_XOR: @@ -1317,6 +1359,31 @@ int exec_insn(struct bytecode_runtime *bytecode, break; } + case FILTER_OP_UNARY_BIT_NOT: + { + /* Pop 1, push 1 */ + if (!vstack_ax(stack)) { + printk(KERN_WARNING "Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + case REG_S64: + case REG_TYPE_UNKNOWN: + break; + case REG_DOUBLE: + default: + printk(KERN_WARNING "Unexpected register type %d for operation\n", + (int) vstack_ax(stack)->type); + ret = -EINVAL; + goto end; + } + + vstack_ax(stack)->type = REG_S64; + next_pc += sizeof(struct unary_op); + break; + } + /* logical */ case FILTER_OP_AND: case FILTER_OP_OR: