Filter: split passes into separate components
[lttng-ust.git] / liblttng-ust / lttng-filter-validator.c
1 /*
2 * lttng-filter-validator.c
3 *
4 * LTTng UST filter bytecode validator.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include "lttng-filter.h"
24
25 static
26 int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
27 {
28 switch (reg[REG_R0].type) {
29 default:
30 goto error_unknown;
31
32 case REG_STRING:
33 switch (reg[REG_R1].type) {
34 default:
35 goto error_unknown;
36
37 case REG_STRING:
38 break;
39 case REG_S64:
40 case REG_DOUBLE:
41 goto error_mismatch;
42 }
43 break;
44 case REG_S64:
45 case REG_DOUBLE:
46 switch (reg[REG_R1].type) {
47 default:
48 goto error_unknown;
49
50 case REG_STRING:
51 goto error_mismatch;
52
53 case REG_S64:
54 case REG_DOUBLE:
55 break;
56 }
57 break;
58 }
59 return 0;
60
61 error_unknown:
62
63 return -EINVAL;
64 error_mismatch:
65 ERR("type mismatch for '%s' binary operator\n", str);
66 return -EINVAL;
67 }
68
69 /*
70 * Validate bytecode range overflow within the validation pass.
71 * Called for each instruction encountered.
72 */
73 static
74 int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
75 void *start_pc, void *pc)
76 {
77 int ret = 0;
78
79 switch (*(filter_opcode_t *) pc) {
80 case FILTER_OP_UNKNOWN:
81 default:
82 {
83 ERR("unknown bytecode op %u\n",
84 (unsigned int) *(filter_opcode_t *) pc);
85 ret = -EINVAL;
86 break;
87 }
88
89 case FILTER_OP_RETURN:
90 {
91 if (unlikely(pc + sizeof(struct return_op)
92 > start_pc + bytecode->len)) {
93 ret = -EINVAL;
94 }
95 break;
96 }
97
98 /* binary */
99 case FILTER_OP_MUL:
100 case FILTER_OP_DIV:
101 case FILTER_OP_MOD:
102 case FILTER_OP_PLUS:
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:
109 {
110 ERR("unsupported bytecode op %u\n",
111 (unsigned int) *(filter_opcode_t *) pc);
112 ret = -EINVAL;
113 break;
114 }
115
116 case FILTER_OP_EQ:
117 case FILTER_OP_NE:
118 case FILTER_OP_GT:
119 case FILTER_OP_LT:
120 case FILTER_OP_GE:
121 case FILTER_OP_LE:
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:
140 {
141 if (unlikely(pc + sizeof(struct binary_op)
142 > start_pc + bytecode->len)) {
143 ret = -EINVAL;
144 }
145 break;
146 }
147
148 /* unary */
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:
158 {
159 if (unlikely(pc + sizeof(struct unary_op)
160 > start_pc + bytecode->len)) {
161 ret = -EINVAL;
162 }
163 break;
164 }
165
166 /* logical */
167 case FILTER_OP_AND:
168 case FILTER_OP_OR:
169 {
170 if (unlikely(pc + sizeof(struct logical_op)
171 > start_pc + bytecode->len)) {
172 ret = -EINVAL;
173 }
174 break;
175 }
176
177 /* load */
178 case FILTER_OP_LOAD_FIELD_REF:
179 {
180 ERR("Unknown field ref type\n");
181 ret = -EINVAL;
182 break;
183 }
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:
188 {
189 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct field_ref)
190 > start_pc + bytecode->len)) {
191 ret = -EINVAL;
192 }
193 break;
194 }
195
196 case FILTER_OP_LOAD_STRING:
197 {
198 struct load_op *insn = (struct load_op *) pc;
199 uint32_t str_len, maxlen;
200
201 if (unlikely(pc + sizeof(struct load_op)
202 > start_pc + bytecode->len)) {
203 ret = -EINVAL;
204 break;
205 }
206
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 */
211 ret = -EINVAL;
212 }
213 break;
214 }
215
216 case FILTER_OP_LOAD_S64:
217 {
218 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_numeric)
219 > start_pc + bytecode->len)) {
220 ret = -EINVAL;
221 }
222 break;
223 }
224
225 case FILTER_OP_LOAD_DOUBLE:
226 {
227 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_double)
228 > start_pc + bytecode->len)) {
229 ret = -EINVAL;
230 }
231 break;
232 }
233
234 case FILTER_OP_CAST_TO_S64:
235 case FILTER_OP_CAST_DOUBLE_TO_S64:
236 case FILTER_OP_CAST_NOP:
237 {
238 if (unlikely(pc + sizeof(struct cast_op)
239 > start_pc + bytecode->len)) {
240 ret = -EINVAL;
241 }
242 break;
243 }
244 }
245
246 return ret;
247 }
248
249 int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
250 {
251 void *pc, *next_pc, *start_pc;
252 int ret = -EINVAL;
253 struct vreg reg[NR_REG];
254 int i;
255
256 for (i = 0; i < NR_REG; i++) {
257 reg[i].type = REG_TYPE_UNKNOWN;
258 reg[i].literal = 0;
259 }
260
261 start_pc = &bytecode->data[0];
262 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
263 pc = next_pc) {
264 if (bytecode_validate_overflow(bytecode, start_pc, pc) != 0) {
265 ERR("filter bytecode overflow\n");
266 ret = -EINVAL;
267 goto end;
268 }
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:
274 default:
275 ERR("unknown bytecode op %u\n",
276 (unsigned int) *(filter_opcode_t *) pc);
277 ret = -EINVAL;
278 goto end;
279
280 case FILTER_OP_RETURN:
281 ret = 0;
282 goto end;
283
284 /* binary */
285 case FILTER_OP_MUL:
286 case FILTER_OP_DIV:
287 case FILTER_OP_MOD:
288 case FILTER_OP_PLUS:
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);
297 ret = -EINVAL;
298 goto end;
299
300 case FILTER_OP_EQ:
301 {
302 ret = bin_op_compare_check(reg, "==");
303 if (ret)
304 goto end;
305 reg[REG_R0].type = REG_S64;
306 next_pc += sizeof(struct binary_op);
307 break;
308 }
309 case FILTER_OP_NE:
310 {
311 ret = bin_op_compare_check(reg, "!=");
312 if (ret)
313 goto end;
314 reg[REG_R0].type = REG_S64;
315 next_pc += sizeof(struct binary_op);
316 break;
317 }
318 case FILTER_OP_GT:
319 {
320 ret = bin_op_compare_check(reg, ">");
321 if (ret)
322 goto end;
323 reg[REG_R0].type = REG_S64;
324 next_pc += sizeof(struct binary_op);
325 break;
326 }
327 case FILTER_OP_LT:
328 {
329 ret = bin_op_compare_check(reg, "<");
330 if (ret)
331 goto end;
332 reg[REG_R0].type = REG_S64;
333 next_pc += sizeof(struct binary_op);
334 break;
335 }
336 case FILTER_OP_GE:
337 {
338 ret = bin_op_compare_check(reg, ">=");
339 if (ret)
340 goto end;
341 reg[REG_R0].type = REG_S64;
342 next_pc += sizeof(struct binary_op);
343 break;
344 }
345 case FILTER_OP_LE:
346 {
347 ret = bin_op_compare_check(reg, "<=");
348 if (ret)
349 goto end;
350 reg[REG_R0].type = REG_S64;
351 next_pc += sizeof(struct binary_op);
352 break;
353 }
354
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:
361 {
362 if (reg[REG_R0].type != REG_STRING
363 || reg[REG_R1].type != REG_STRING) {
364 ERR("Unexpected register type for string comparator\n");
365 ret = -EINVAL;
366 goto end;
367 }
368 reg[REG_R0].type = REG_S64;
369 next_pc += sizeof(struct binary_op);
370 break;
371 }
372
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:
379 {
380 if (reg[REG_R0].type != REG_S64
381 || reg[REG_R1].type != REG_S64) {
382 ERR("Unexpected register type for s64 comparator\n");
383 ret = -EINVAL;
384 goto end;
385 }
386 reg[REG_R0].type = REG_S64;
387 next_pc += sizeof(struct binary_op);
388 break;
389 }
390
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:
397 {
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");
401 ret = -EINVAL;
402 goto end;
403 }
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");
406 ret = -EINVAL;
407 goto end;
408 }
409 reg[REG_R0].type = REG_DOUBLE;
410 next_pc += sizeof(struct binary_op);
411 break;
412 }
413
414 /* unary */
415 case FILTER_OP_UNARY_PLUS:
416 case FILTER_OP_UNARY_MINUS:
417 case FILTER_OP_UNARY_NOT:
418 {
419 struct unary_op *insn = (struct unary_op *) pc;
420
421 if (unlikely(insn->reg >= REG_ERROR)) {
422 ERR("invalid register %u\n",
423 (unsigned int) insn->reg);
424 ret = -EINVAL;
425 goto end;
426 }
427 switch (reg[insn->reg].type) {
428 default:
429 ERR("unknown register type\n");
430 ret = -EINVAL;
431 goto end;
432
433 case REG_STRING:
434 ERR("Unary op can only be applied to numeric or floating point registers\n");
435 ret = -EINVAL;
436 goto end;
437 case REG_S64:
438 break;
439 case REG_DOUBLE:
440 break;
441 }
442 next_pc += sizeof(struct unary_op);
443 break;
444 }
445
446 case FILTER_OP_UNARY_PLUS_S64:
447 case FILTER_OP_UNARY_MINUS_S64:
448 case FILTER_OP_UNARY_NOT_S64:
449 {
450 struct unary_op *insn = (struct unary_op *) pc;
451
452 if (unlikely(insn->reg >= REG_ERROR)) {
453 ERR("invalid register %u\n",
454 (unsigned int) insn->reg);
455 ret = -EINVAL;
456 goto end;
457 }
458 if (reg[insn->reg].type != REG_S64) {
459 ERR("Invalid register type\n");
460 ret = -EINVAL;
461 goto end;
462 }
463 next_pc += sizeof(struct unary_op);
464 break;
465 }
466
467 case FILTER_OP_UNARY_PLUS_DOUBLE:
468 case FILTER_OP_UNARY_MINUS_DOUBLE:
469 case FILTER_OP_UNARY_NOT_DOUBLE:
470 {
471 struct unary_op *insn = (struct unary_op *) pc;
472
473 if (unlikely(insn->reg >= REG_ERROR)) {
474 ERR("invalid register %u\n",
475 (unsigned int) insn->reg);
476 ret = -EINVAL;
477 goto end;
478 }
479 if (reg[insn->reg].type != REG_DOUBLE) {
480 ERR("Invalid register type\n");
481 ret = -EINVAL;
482 goto end;
483 }
484 next_pc += sizeof(struct unary_op);
485 break;
486 }
487
488 /* logical */
489 case FILTER_OP_AND:
490 case FILTER_OP_OR:
491 {
492 struct logical_op *insn = (struct logical_op *) pc;
493
494 if (reg[REG_R0].type != REG_S64) {
495 ERR("Logical comparator expects S64 register\n");
496 ret = -EINVAL;
497 goto end;
498 }
499
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");
504 ret = -EINVAL;
505 goto end;
506 }
507 next_pc += sizeof(struct logical_op);
508 break;
509 }
510
511 /* load */
512 case FILTER_OP_LOAD_FIELD_REF:
513 {
514 ERR("Unknown field ref type\n");
515 ret = -EINVAL;
516 goto end;
517 }
518 case FILTER_OP_LOAD_FIELD_REF_STRING:
519 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
520 {
521 struct load_op *insn = (struct load_op *) pc;
522 struct field_ref *ref = (struct field_ref *) insn->data;
523
524 if (unlikely(insn->reg >= REG_ERROR)) {
525 ERR("invalid register %u\n",
526 (unsigned int) insn->reg);
527 ret = -EINVAL;
528 goto end;
529 }
530 dbg_printf("Validate load field ref offset %u type string\n",
531 ref->offset);
532 reg[insn->reg].type = REG_STRING;
533 reg[insn->reg].literal = 0;
534 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
535 break;
536 }
537 case FILTER_OP_LOAD_FIELD_REF_S64:
538 {
539 struct load_op *insn = (struct load_op *) pc;
540 struct field_ref *ref = (struct field_ref *) insn->data;
541
542 if (unlikely(insn->reg >= REG_ERROR)) {
543 ERR("invalid register %u\n",
544 (unsigned int) insn->reg);
545 ret = -EINVAL;
546 goto end;
547 }
548 dbg_printf("Validate load field ref offset %u type s64\n",
549 ref->offset);
550 reg[insn->reg].type = REG_S64;
551 reg[insn->reg].literal = 0;
552 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
553 break;
554 }
555 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
556 {
557 struct load_op *insn = (struct load_op *) pc;
558 struct field_ref *ref = (struct field_ref *) insn->data;
559
560 if (unlikely(insn->reg >= REG_ERROR)) {
561 ERR("invalid register %u\n",
562 (unsigned int) insn->reg);
563 ret = -EINVAL;
564 goto end;
565 }
566 dbg_printf("Validate load field ref offset %u type double\n",
567 ref->offset);
568 reg[insn->reg].type = REG_DOUBLE;
569 reg[insn->reg].literal = 0;
570 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
571 break;
572 }
573
574 case FILTER_OP_LOAD_STRING:
575 {
576 struct load_op *insn = (struct load_op *) pc;
577
578 if (unlikely(insn->reg >= REG_ERROR)) {
579 ERR("invalid register %u\n",
580 (unsigned int) insn->reg);
581 ret = -EINVAL;
582 goto end;
583 }
584 reg[insn->reg].type = REG_STRING;
585 reg[insn->reg].literal = 1;
586 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
587 break;
588 }
589
590 case FILTER_OP_LOAD_S64:
591 {
592 struct load_op *insn = (struct load_op *) pc;
593
594 if (unlikely(insn->reg >= REG_ERROR)) {
595 ERR("invalid register %u\n",
596 (unsigned int) insn->reg);
597 ret = -EINVAL;
598 goto end;
599 }
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);
604 break;
605 }
606
607 case FILTER_OP_LOAD_DOUBLE:
608 {
609 struct load_op *insn = (struct load_op *) pc;
610
611 if (unlikely(insn->reg >= REG_ERROR)) {
612 ERR("invalid register %u\n",
613 (unsigned int) insn->reg);
614 ret = -EINVAL;
615 goto end;
616 }
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);
621 break;
622 }
623
624 case FILTER_OP_CAST_TO_S64:
625 case FILTER_OP_CAST_DOUBLE_TO_S64:
626 {
627 struct cast_op *insn = (struct cast_op *) pc;
628
629 if (unlikely(insn->reg >= REG_ERROR)) {
630 ERR("invalid register %u\n",
631 (unsigned int) insn->reg);
632 ret = -EINVAL;
633 goto end;
634 }
635 switch (reg[insn->reg].type) {
636 default:
637 ERR("unknown register type\n");
638 ret = -EINVAL;
639 goto end;
640
641 case REG_STRING:
642 ERR("Cast op can only be applied to numeric or floating point registers\n");
643 ret = -EINVAL;
644 goto end;
645 case REG_S64:
646 break;
647 case REG_DOUBLE:
648 break;
649 }
650 if (insn->op == FILTER_OP_CAST_DOUBLE_TO_S64) {
651 if (reg[insn->reg].type != REG_DOUBLE) {
652 ERR("Cast expects double\n");
653 ret = -EINVAL;
654 goto end;
655 }
656 }
657 reg[insn->reg].type = REG_S64;
658 next_pc += sizeof(struct cast_op);
659 break;
660 }
661 case FILTER_OP_CAST_NOP:
662 {
663 next_pc += sizeof(struct cast_op);
664 break;
665 }
666
667 }
668 }
669 end:
670 return ret;
671 }
This page took 0.04477 seconds and 5 git commands to generate.