2 * lttng-filter-validator.c
4 * LTTng UST filter bytecode validator.
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "lttng-filter.h"
26 int bin_op_compare_check(struct vreg reg
[NR_REG
], const char *str
)
28 switch (reg
[REG_R0
].type
) {
33 switch (reg
[REG_R1
].type
) {
46 switch (reg
[REG_R1
].type
) {
65 ERR("type mismatch for '%s' binary operator\n", str
);
70 * Validate bytecode range overflow within the validation pass.
71 * Called for each instruction encountered.
74 int bytecode_validate_overflow(struct bytecode_runtime
*bytecode
,
75 void *start_pc
, void *pc
)
79 switch (*(filter_opcode_t
*) pc
) {
80 case FILTER_OP_UNKNOWN
:
83 ERR("unknown bytecode op %u\n",
84 (unsigned int) *(filter_opcode_t
*) pc
);
89 case FILTER_OP_RETURN
:
91 if (unlikely(pc
+ sizeof(struct return_op
)
92 > start_pc
+ bytecode
->len
)) {
103 case FILTER_OP_MINUS
:
104 case FILTER_OP_RSHIFT
:
105 case FILTER_OP_LSHIFT
:
106 case FILTER_OP_BIN_AND
:
107 case FILTER_OP_BIN_OR
:
108 case FILTER_OP_BIN_XOR
:
110 ERR("unsupported bytecode op %u\n",
111 (unsigned int) *(filter_opcode_t
*) pc
);
122 case FILTER_OP_EQ_STRING
:
123 case FILTER_OP_NE_STRING
:
124 case FILTER_OP_GT_STRING
:
125 case FILTER_OP_LT_STRING
:
126 case FILTER_OP_GE_STRING
:
127 case FILTER_OP_LE_STRING
:
128 case FILTER_OP_EQ_S64
:
129 case FILTER_OP_NE_S64
:
130 case FILTER_OP_GT_S64
:
131 case FILTER_OP_LT_S64
:
132 case FILTER_OP_GE_S64
:
133 case FILTER_OP_LE_S64
:
134 case FILTER_OP_EQ_DOUBLE
:
135 case FILTER_OP_NE_DOUBLE
:
136 case FILTER_OP_GT_DOUBLE
:
137 case FILTER_OP_LT_DOUBLE
:
138 case FILTER_OP_GE_DOUBLE
:
139 case FILTER_OP_LE_DOUBLE
:
141 if (unlikely(pc
+ sizeof(struct binary_op
)
142 > start_pc
+ bytecode
->len
)) {
149 case FILTER_OP_UNARY_PLUS
:
150 case FILTER_OP_UNARY_MINUS
:
151 case FILTER_OP_UNARY_NOT
:
152 case FILTER_OP_UNARY_PLUS_S64
:
153 case FILTER_OP_UNARY_MINUS_S64
:
154 case FILTER_OP_UNARY_NOT_S64
:
155 case FILTER_OP_UNARY_PLUS_DOUBLE
:
156 case FILTER_OP_UNARY_MINUS_DOUBLE
:
157 case FILTER_OP_UNARY_NOT_DOUBLE
:
159 if (unlikely(pc
+ sizeof(struct unary_op
)
160 > start_pc
+ bytecode
->len
)) {
170 if (unlikely(pc
+ sizeof(struct logical_op
)
171 > start_pc
+ bytecode
->len
)) {
178 case FILTER_OP_LOAD_FIELD_REF
:
180 ERR("Unknown field ref type\n");
184 case FILTER_OP_LOAD_FIELD_REF_STRING
:
185 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
186 case FILTER_OP_LOAD_FIELD_REF_S64
:
187 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
189 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct field_ref
)
190 > start_pc
+ bytecode
->len
)) {
196 case FILTER_OP_LOAD_STRING
:
198 struct load_op
*insn
= (struct load_op
*) pc
;
199 uint32_t str_len
, maxlen
;
201 if (unlikely(pc
+ sizeof(struct load_op
)
202 > start_pc
+ bytecode
->len
)) {
207 maxlen
= start_pc
+ bytecode
->len
- pc
- sizeof(struct load_op
);
208 str_len
= strnlen(insn
->data
, maxlen
);
209 if (unlikely(str_len
>= maxlen
)) {
210 /* Final '\0' not found within range */
216 case FILTER_OP_LOAD_S64
:
218 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_numeric
)
219 > start_pc
+ bytecode
->len
)) {
225 case FILTER_OP_LOAD_DOUBLE
:
227 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_double
)
228 > start_pc
+ bytecode
->len
)) {
234 case FILTER_OP_CAST_TO_S64
:
235 case FILTER_OP_CAST_DOUBLE_TO_S64
:
236 case FILTER_OP_CAST_NOP
:
238 if (unlikely(pc
+ sizeof(struct cast_op
)
239 > start_pc
+ bytecode
->len
)) {
249 int lttng_filter_validate_bytecode(struct bytecode_runtime
*bytecode
)
251 void *pc
, *next_pc
, *start_pc
;
253 struct vreg reg
[NR_REG
];
256 for (i
= 0; i
< NR_REG
; i
++) {
257 reg
[i
].type
= REG_TYPE_UNKNOWN
;
261 start_pc
= &bytecode
->data
[0];
262 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
264 if (bytecode_validate_overflow(bytecode
, start_pc
, pc
) != 0) {
265 ERR("filter bytecode overflow\n");
269 dbg_printf("Validating op %s (%u)\n",
270 print_op((unsigned int) *(filter_opcode_t
*) pc
),
271 (unsigned int) *(filter_opcode_t
*) pc
);
272 switch (*(filter_opcode_t
*) pc
) {
273 case FILTER_OP_UNKNOWN
:
275 ERR("unknown bytecode op %u\n",
276 (unsigned int) *(filter_opcode_t
*) pc
);
280 case FILTER_OP_RETURN
:
289 case FILTER_OP_MINUS
:
290 case FILTER_OP_RSHIFT
:
291 case FILTER_OP_LSHIFT
:
292 case FILTER_OP_BIN_AND
:
293 case FILTER_OP_BIN_OR
:
294 case FILTER_OP_BIN_XOR
:
295 ERR("unsupported bytecode op %u\n",
296 (unsigned int) *(filter_opcode_t
*) pc
);
302 ret
= bin_op_compare_check(reg
, "==");
305 reg
[REG_R0
].type
= REG_S64
;
306 next_pc
+= sizeof(struct binary_op
);
311 ret
= bin_op_compare_check(reg
, "!=");
314 reg
[REG_R0
].type
= REG_S64
;
315 next_pc
+= sizeof(struct binary_op
);
320 ret
= bin_op_compare_check(reg
, ">");
323 reg
[REG_R0
].type
= REG_S64
;
324 next_pc
+= sizeof(struct binary_op
);
329 ret
= bin_op_compare_check(reg
, "<");
332 reg
[REG_R0
].type
= REG_S64
;
333 next_pc
+= sizeof(struct binary_op
);
338 ret
= bin_op_compare_check(reg
, ">=");
341 reg
[REG_R0
].type
= REG_S64
;
342 next_pc
+= sizeof(struct binary_op
);
347 ret
= bin_op_compare_check(reg
, "<=");
350 reg
[REG_R0
].type
= REG_S64
;
351 next_pc
+= sizeof(struct binary_op
);
355 case FILTER_OP_EQ_STRING
:
356 case FILTER_OP_NE_STRING
:
357 case FILTER_OP_GT_STRING
:
358 case FILTER_OP_LT_STRING
:
359 case FILTER_OP_GE_STRING
:
360 case FILTER_OP_LE_STRING
:
362 if (reg
[REG_R0
].type
!= REG_STRING
363 || reg
[REG_R1
].type
!= REG_STRING
) {
364 ERR("Unexpected register type for string comparator\n");
368 reg
[REG_R0
].type
= REG_S64
;
369 next_pc
+= sizeof(struct binary_op
);
373 case FILTER_OP_EQ_S64
:
374 case FILTER_OP_NE_S64
:
375 case FILTER_OP_GT_S64
:
376 case FILTER_OP_LT_S64
:
377 case FILTER_OP_GE_S64
:
378 case FILTER_OP_LE_S64
:
380 if (reg
[REG_R0
].type
!= REG_S64
381 || reg
[REG_R1
].type
!= REG_S64
) {
382 ERR("Unexpected register type for s64 comparator\n");
386 reg
[REG_R0
].type
= REG_S64
;
387 next_pc
+= sizeof(struct binary_op
);
391 case FILTER_OP_EQ_DOUBLE
:
392 case FILTER_OP_NE_DOUBLE
:
393 case FILTER_OP_GT_DOUBLE
:
394 case FILTER_OP_LT_DOUBLE
:
395 case FILTER_OP_GE_DOUBLE
:
396 case FILTER_OP_LE_DOUBLE
:
398 if ((reg
[REG_R0
].type
!= REG_DOUBLE
&& reg
[REG_R0
].type
!= REG_S64
)
399 || (reg
[REG_R1
].type
!= REG_DOUBLE
&& reg
[REG_R1
].type
!= REG_S64
)) {
400 ERR("Unexpected register type for double comparator\n");
404 if (reg
[REG_R0
].type
!= REG_DOUBLE
&& reg
[REG_R1
].type
!= REG_DOUBLE
) {
405 ERR("Double operator should have at least one double register\n");
409 reg
[REG_R0
].type
= REG_DOUBLE
;
410 next_pc
+= sizeof(struct binary_op
);
415 case FILTER_OP_UNARY_PLUS
:
416 case FILTER_OP_UNARY_MINUS
:
417 case FILTER_OP_UNARY_NOT
:
419 struct unary_op
*insn
= (struct unary_op
*) pc
;
421 if (unlikely(insn
->reg
>= REG_ERROR
)) {
422 ERR("invalid register %u\n",
423 (unsigned int) insn
->reg
);
427 switch (reg
[insn
->reg
].type
) {
429 ERR("unknown register type\n");
434 ERR("Unary op can only be applied to numeric or floating point registers\n");
442 next_pc
+= sizeof(struct unary_op
);
446 case FILTER_OP_UNARY_PLUS_S64
:
447 case FILTER_OP_UNARY_MINUS_S64
:
448 case FILTER_OP_UNARY_NOT_S64
:
450 struct unary_op
*insn
= (struct unary_op
*) pc
;
452 if (unlikely(insn
->reg
>= REG_ERROR
)) {
453 ERR("invalid register %u\n",
454 (unsigned int) insn
->reg
);
458 if (reg
[insn
->reg
].type
!= REG_S64
) {
459 ERR("Invalid register type\n");
463 next_pc
+= sizeof(struct unary_op
);
467 case FILTER_OP_UNARY_PLUS_DOUBLE
:
468 case FILTER_OP_UNARY_MINUS_DOUBLE
:
469 case FILTER_OP_UNARY_NOT_DOUBLE
:
471 struct unary_op
*insn
= (struct unary_op
*) pc
;
473 if (unlikely(insn
->reg
>= REG_ERROR
)) {
474 ERR("invalid register %u\n",
475 (unsigned int) insn
->reg
);
479 if (reg
[insn
->reg
].type
!= REG_DOUBLE
) {
480 ERR("Invalid register type\n");
484 next_pc
+= sizeof(struct unary_op
);
492 struct logical_op
*insn
= (struct logical_op
*) pc
;
494 if (reg
[REG_R0
].type
!= REG_S64
) {
495 ERR("Logical comparator expects S64 register\n");
500 dbg_printf("Validate jumping to bytecode offset %u\n",
501 (unsigned int) insn
->skip_offset
);
502 if (unlikely(start_pc
+ insn
->skip_offset
<= pc
)) {
503 ERR("Loops are not allowed in bytecode\n");
507 next_pc
+= sizeof(struct logical_op
);
512 case FILTER_OP_LOAD_FIELD_REF
:
514 ERR("Unknown field ref type\n");
518 case FILTER_OP_LOAD_FIELD_REF_STRING
:
519 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
521 struct load_op
*insn
= (struct load_op
*) pc
;
522 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
524 if (unlikely(insn
->reg
>= REG_ERROR
)) {
525 ERR("invalid register %u\n",
526 (unsigned int) insn
->reg
);
530 dbg_printf("Validate load field ref offset %u type string\n",
532 reg
[insn
->reg
].type
= REG_STRING
;
533 reg
[insn
->reg
].literal
= 0;
534 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
537 case FILTER_OP_LOAD_FIELD_REF_S64
:
539 struct load_op
*insn
= (struct load_op
*) pc
;
540 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
542 if (unlikely(insn
->reg
>= REG_ERROR
)) {
543 ERR("invalid register %u\n",
544 (unsigned int) insn
->reg
);
548 dbg_printf("Validate load field ref offset %u type s64\n",
550 reg
[insn
->reg
].type
= REG_S64
;
551 reg
[insn
->reg
].literal
= 0;
552 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
555 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
557 struct load_op
*insn
= (struct load_op
*) pc
;
558 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
560 if (unlikely(insn
->reg
>= REG_ERROR
)) {
561 ERR("invalid register %u\n",
562 (unsigned int) insn
->reg
);
566 dbg_printf("Validate load field ref offset %u type double\n",
568 reg
[insn
->reg
].type
= REG_DOUBLE
;
569 reg
[insn
->reg
].literal
= 0;
570 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
574 case FILTER_OP_LOAD_STRING
:
576 struct load_op
*insn
= (struct load_op
*) pc
;
578 if (unlikely(insn
->reg
>= REG_ERROR
)) {
579 ERR("invalid register %u\n",
580 (unsigned int) insn
->reg
);
584 reg
[insn
->reg
].type
= REG_STRING
;
585 reg
[insn
->reg
].literal
= 1;
586 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
590 case FILTER_OP_LOAD_S64
:
592 struct load_op
*insn
= (struct load_op
*) pc
;
594 if (unlikely(insn
->reg
>= REG_ERROR
)) {
595 ERR("invalid register %u\n",
596 (unsigned int) insn
->reg
);
600 reg
[insn
->reg
].type
= REG_S64
;
601 reg
[insn
->reg
].literal
= 1;
602 next_pc
+= sizeof(struct load_op
)
603 + sizeof(struct literal_numeric
);
607 case FILTER_OP_LOAD_DOUBLE
:
609 struct load_op
*insn
= (struct load_op
*) pc
;
611 if (unlikely(insn
->reg
>= REG_ERROR
)) {
612 ERR("invalid register %u\n",
613 (unsigned int) insn
->reg
);
617 reg
[insn
->reg
].type
= REG_DOUBLE
;
618 reg
[insn
->reg
].literal
= 1;
619 next_pc
+= sizeof(struct load_op
)
620 + sizeof(struct literal_double
);
624 case FILTER_OP_CAST_TO_S64
:
625 case FILTER_OP_CAST_DOUBLE_TO_S64
:
627 struct cast_op
*insn
= (struct cast_op
*) pc
;
629 if (unlikely(insn
->reg
>= REG_ERROR
)) {
630 ERR("invalid register %u\n",
631 (unsigned int) insn
->reg
);
635 switch (reg
[insn
->reg
].type
) {
637 ERR("unknown register type\n");
642 ERR("Cast op can only be applied to numeric or floating point registers\n");
650 if (insn
->op
== FILTER_OP_CAST_DOUBLE_TO_S64
) {
651 if (reg
[insn
->reg
].type
!= REG_DOUBLE
) {
652 ERR("Cast expects double\n");
657 reg
[insn
->reg
].type
= REG_S64
;
658 next_pc
+= sizeof(struct cast_op
);
661 case FILTER_OP_CAST_NOP
:
663 next_pc
+= sizeof(struct cast_op
);