Fix: bytecode validator: reject specialized load instructions
[lttng-modules.git] / lttng-filter-validator.c
CommitLineData
9f36eaed
MJ
1/* SPDX-License-Identifier: MIT
2 *
07dfc1d0
MD
3 * lttng-filter-validator.c
4 *
5 * LTTng modules filter bytecode validator.
6 *
bbf3aef5 7 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
07dfc1d0
MD
8 */
9
499cc3f7 10#include <linux/types.h>
07dfc1d0
MD
11#include <linux/jhash.h>
12#include <linux/slab.h>
13
241ae9a8
MD
14#include <wrapper/list.h>
15#include <lttng-filter.h>
07dfc1d0
MD
16
17#define MERGE_POINT_TABLE_BITS 7
18#define MERGE_POINT_TABLE_SIZE (1U << MERGE_POINT_TABLE_BITS)
19
20/* merge point table node */
21struct mp_node {
22 struct hlist_node node;
23
24 /* Context at merge point */
25 struct vstack stack;
26 unsigned long target_pc;
27};
28
29struct mp_table {
30 struct hlist_head mp_head[MERGE_POINT_TABLE_SIZE];
31};
32
33static
34int lttng_hash_match(struct mp_node *mp_node, unsigned long key_pc)
35{
36 if (mp_node->target_pc == key_pc)
37 return 1;
38 else
39 return 0;
40}
41
42static
43int merge_points_compare(const struct vstack *stacka,
44 const struct vstack *stackb)
45{
46 int i, len;
47
48 if (stacka->top != stackb->top)
49 return 1;
50 len = stacka->top + 1;
51 WARN_ON_ONCE(len < 0);
52 for (i = 0; i < len; i++) {
53 if (stacka->e[i].type != stackb->e[i].type)
54 return 1;
55 }
56 return 0;
57}
58
59static
60int merge_point_add_check(struct mp_table *mp_table, unsigned long target_pc,
61 const struct vstack *stack)
62{
63 struct mp_node *mp_node;
64 unsigned long hash = jhash_1word(target_pc, 0);
65 struct hlist_head *head;
66 struct mp_node *lookup_node;
67 int found = 0;
68
69 dbg_printk("Filter: adding merge point at offset %lu, hash %lu\n",
70 target_pc, hash);
71 mp_node = kzalloc(sizeof(struct mp_node), GFP_KERNEL);
72 if (!mp_node)
73 return -ENOMEM;
74 mp_node->target_pc = target_pc;
75 memcpy(&mp_node->stack, stack, sizeof(mp_node->stack));
76
77 head = &mp_table->mp_head[hash & (MERGE_POINT_TABLE_SIZE - 1)];
d216ecae 78 lttng_hlist_for_each_entry(lookup_node, head, node) {
07dfc1d0
MD
79 if (lttng_hash_match(lookup_node, target_pc)) {
80 found = 1;
81 break;
82 }
83 }
84 if (found) {
85 /* Key already present */
86 dbg_printk("Filter: compare merge points for offset %lu, hash %lu\n",
87 target_pc, hash);
88 kfree(mp_node);
89 if (merge_points_compare(stack, &lookup_node->stack)) {
90 printk(KERN_WARNING "Merge points differ for offset %lu\n",
91 target_pc);
92 return -EINVAL;
93 }
5e13eb3c
MD
94 } else {
95 hlist_add_head(&mp_node->node, head);
07dfc1d0 96 }
07dfc1d0
MD
97 return 0;
98}
99
100/*
101 * Binary comparators use top of stack and top of stack -1.
102 */
103static
02aca193
PP
104int bin_op_compare_check(struct vstack *stack, const filter_opcode_t opcode,
105 const char *str)
07dfc1d0
MD
106{
107 if (unlikely(!vstack_ax(stack) || !vstack_bx(stack)))
3834b99f 108 goto error_empty;
07dfc1d0
MD
109
110 switch (vstack_ax(stack)->type) {
111 default:
112 case REG_DOUBLE:
3834b99f 113 goto error_type;
07dfc1d0
MD
114
115 case REG_STRING:
116 switch (vstack_bx(stack)->type) {
117 default:
118 case REG_DOUBLE:
3834b99f
MD
119 goto error_type;
120 case REG_TYPE_UNKNOWN:
121 goto unknown;
07dfc1d0
MD
122 case REG_STRING:
123 break;
02aca193
PP
124 case REG_STAR_GLOB_STRING:
125 if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
126 goto error_mismatch;
127 }
128 break;
129 case REG_S64:
130 goto error_mismatch;
131 }
132 break;
133 case REG_STAR_GLOB_STRING:
134 switch (vstack_bx(stack)->type) {
135 default:
136 case REG_DOUBLE:
3834b99f
MD
137 goto error_type;
138 case REG_TYPE_UNKNOWN:
139 goto unknown;
02aca193
PP
140 case REG_STRING:
141 if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
142 goto error_mismatch;
143 }
144 break;
145 case REG_STAR_GLOB_STRING:
07dfc1d0
MD
146 case REG_S64:
147 goto error_mismatch;
148 }
149 break;
150 case REG_S64:
151 switch (vstack_bx(stack)->type) {
152 default:
153 case REG_DOUBLE:
3834b99f
MD
154 goto error_type;
155 case REG_TYPE_UNKNOWN:
156 goto unknown;
07dfc1d0 157 case REG_STRING:
02aca193 158 case REG_STAR_GLOB_STRING:
07dfc1d0 159 goto error_mismatch;
07dfc1d0
MD
160 case REG_S64:
161 break;
162 }
163 break;
3834b99f
MD
164 case REG_TYPE_UNKNOWN:
165 switch (vstack_bx(stack)->type) {
166 default:
167 case REG_DOUBLE:
168 goto error_type;
169 case REG_TYPE_UNKNOWN:
170 case REG_STRING:
171 case REG_STAR_GLOB_STRING:
172 case REG_S64:
173 goto unknown;
174 }
175 break;
07dfc1d0
MD
176 }
177 return 0;
178
3834b99f
MD
179unknown:
180 return 1;
181
182error_empty:
183 printk(KERN_WARNING "empty stack for '%s' binary operator\n", str);
07dfc1d0
MD
184 return -EINVAL;
185
186error_mismatch:
187 printk(KERN_WARNING "type mismatch for '%s' binary operator\n", str);
188 return -EINVAL;
3834b99f
MD
189
190error_type:
191 printk(KERN_WARNING "unknown type for '%s' binary operator\n", str);
192 return -EINVAL;
193}
194
195/*
196 * Binary bitwise operators use top of stack and top of stack -1.
197 * Return 0 if typing is known to match, 1 if typing is dynamic
198 * (unknown), negative error value on error.
199 */
200static
201int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode,
202 const char *str)
203{
204 if (unlikely(!vstack_ax(stack) || !vstack_bx(stack)))
205 goto error_empty;
206
207 switch (vstack_ax(stack)->type) {
208 default:
209 case REG_DOUBLE:
210 goto error_type;
211
212 case REG_TYPE_UNKNOWN:
213 switch (vstack_bx(stack)->type) {
214 default:
215 case REG_DOUBLE:
216 goto error_type;
217 case REG_TYPE_UNKNOWN:
218 case REG_STRING:
219 case REG_STAR_GLOB_STRING:
220 case REG_S64:
221 goto unknown;
222 }
223 break;
224 case REG_S64:
225 switch (vstack_bx(stack)->type) {
226 default:
227 case REG_DOUBLE:
228 goto error_type;
229 case REG_TYPE_UNKNOWN:
230 goto unknown;
231 case REG_S64:
232 break;
233 }
234 break;
235 }
236 return 0;
237
238unknown:
239 return 1;
240
241error_empty:
242 printk(KERN_WARNING "empty stack for '%s' binary operator\n", str);
243 return -EINVAL;
244
245error_type:
246 printk(KERN_WARNING "unknown type for '%s' binary operator\n", str);
247 return -EINVAL;
248}
249
250static
251int validate_get_symbol(struct bytecode_runtime *bytecode,
252 const struct get_symbol *sym)
253{
254 const char *str, *str_limit;
255 size_t len_limit;
256
257 if (sym->offset >= bytecode->p.bc->bc.len - bytecode->p.bc->bc.reloc_offset)
258 return -EINVAL;
259
260 str = bytecode->p.bc->bc.data + bytecode->p.bc->bc.reloc_offset + sym->offset;
261 str_limit = bytecode->p.bc->bc.data + bytecode->p.bc->bc.len;
262 len_limit = str_limit - str;
263 if (strnlen(str, len_limit) == len_limit)
264 return -EINVAL;
265 return 0;
07dfc1d0
MD
266}
267
268/*
269 * Validate bytecode range overflow within the validation pass.
270 * Called for each instruction encountered.
271 */
272static
273int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
7962cb86 274 char *start_pc, char *pc)
07dfc1d0
MD
275{
276 int ret = 0;
277
278 switch (*(filter_opcode_t *) pc) {
279 case FILTER_OP_UNKNOWN:
280 default:
281 {
282 printk(KERN_WARNING "unknown bytecode op %u\n",
283 (unsigned int) *(filter_opcode_t *) pc);
284 ret = -EINVAL;
285 break;
286 }
287
288 case FILTER_OP_RETURN:
57ba4b41 289 case FILTER_OP_RETURN_S64:
07dfc1d0
MD
290 {
291 if (unlikely(pc + sizeof(struct return_op)
292 > start_pc + bytecode->len)) {
293 ret = -ERANGE;
294 }
295 break;
296 }
297
298 /* binary */
299 case FILTER_OP_MUL:
300 case FILTER_OP_DIV:
301 case FILTER_OP_MOD:
302 case FILTER_OP_PLUS:
303 case FILTER_OP_MINUS:
07dfc1d0
MD
304 case FILTER_OP_EQ_DOUBLE:
305 case FILTER_OP_NE_DOUBLE:
306 case FILTER_OP_GT_DOUBLE:
307 case FILTER_OP_LT_DOUBLE:
308 case FILTER_OP_GE_DOUBLE:
309 case FILTER_OP_LE_DOUBLE:
310 /* Floating point */
311 case FILTER_OP_EQ_DOUBLE_S64:
312 case FILTER_OP_NE_DOUBLE_S64:
313 case FILTER_OP_GT_DOUBLE_S64:
314 case FILTER_OP_LT_DOUBLE_S64:
315 case FILTER_OP_GE_DOUBLE_S64:
316 case FILTER_OP_LE_DOUBLE_S64:
317 case FILTER_OP_EQ_S64_DOUBLE:
318 case FILTER_OP_NE_S64_DOUBLE:
319 case FILTER_OP_GT_S64_DOUBLE:
320 case FILTER_OP_LT_S64_DOUBLE:
321 case FILTER_OP_GE_S64_DOUBLE:
322 case FILTER_OP_LE_S64_DOUBLE:
323 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
324 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
325 case FILTER_OP_LOAD_DOUBLE:
326 case FILTER_OP_CAST_DOUBLE_TO_S64:
327 case FILTER_OP_UNARY_PLUS_DOUBLE:
328 case FILTER_OP_UNARY_MINUS_DOUBLE:
329 case FILTER_OP_UNARY_NOT_DOUBLE:
330 {
331 printk(KERN_WARNING "unsupported bytecode op %u\n",
332 (unsigned int) *(filter_opcode_t *) pc);
333 ret = -EINVAL;
334 break;
335 }
336
337 case FILTER_OP_EQ:
338 case FILTER_OP_NE:
339 case FILTER_OP_GT:
340 case FILTER_OP_LT:
341 case FILTER_OP_GE:
342 case FILTER_OP_LE:
343 case FILTER_OP_EQ_STRING:
344 case FILTER_OP_NE_STRING:
345 case FILTER_OP_GT_STRING:
346 case FILTER_OP_LT_STRING:
347 case FILTER_OP_GE_STRING:
348 case FILTER_OP_LE_STRING:
02aca193
PP
349 case FILTER_OP_EQ_STAR_GLOB_STRING:
350 case FILTER_OP_NE_STAR_GLOB_STRING:
07dfc1d0
MD
351 case FILTER_OP_EQ_S64:
352 case FILTER_OP_NE_S64:
353 case FILTER_OP_GT_S64:
354 case FILTER_OP_LT_S64:
355 case FILTER_OP_GE_S64:
356 case FILTER_OP_LE_S64:
e16c054b
MD
357 case FILTER_OP_BIT_RSHIFT:
358 case FILTER_OP_BIT_LSHIFT:
3834b99f
MD
359 case FILTER_OP_BIT_AND:
360 case FILTER_OP_BIT_OR:
361 case FILTER_OP_BIT_XOR:
07dfc1d0
MD
362 {
363 if (unlikely(pc + sizeof(struct binary_op)
364 > start_pc + bytecode->len)) {
365 ret = -ERANGE;
366 }
367 break;
368 }
369
370 /* unary */
371 case FILTER_OP_UNARY_PLUS:
372 case FILTER_OP_UNARY_MINUS:
373 case FILTER_OP_UNARY_NOT:
374 case FILTER_OP_UNARY_PLUS_S64:
375 case FILTER_OP_UNARY_MINUS_S64:
376 case FILTER_OP_UNARY_NOT_S64:
e16c054b 377 case FILTER_OP_UNARY_BIT_NOT:
07dfc1d0
MD
378 {
379 if (unlikely(pc + sizeof(struct unary_op)
380 > start_pc + bytecode->len)) {
381 ret = -ERANGE;
382 }
383 break;
384 }
385
386 /* logical */
387 case FILTER_OP_AND:
388 case FILTER_OP_OR:
389 {
390 if (unlikely(pc + sizeof(struct logical_op)
391 > start_pc + bytecode->len)) {
392 ret = -ERANGE;
393 }
394 break;
395 }
396
397 /* load field ref */
398 case FILTER_OP_LOAD_FIELD_REF:
399 {
400 printk(KERN_WARNING "Unknown field ref type\n");
401 ret = -EINVAL;
402 break;
403 }
3834b99f 404
07dfc1d0
MD
405 /* get context ref */
406 case FILTER_OP_GET_CONTEXT_REF:
407 {
408 printk(KERN_WARNING "Unknown field ref type\n");
409 ret = -EINVAL;
410 break;
411 }
412 case FILTER_OP_LOAD_FIELD_REF_STRING:
413 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
f127e61e
MD
414 case FILTER_OP_LOAD_FIELD_REF_USER_STRING:
415 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE:
07dfc1d0
MD
416 case FILTER_OP_LOAD_FIELD_REF_S64:
417 case FILTER_OP_GET_CONTEXT_REF_STRING:
418 case FILTER_OP_GET_CONTEXT_REF_S64:
419 {
420 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct field_ref)
421 > start_pc + bytecode->len)) {
422 ret = -ERANGE;
423 }
424 break;
425 }
426
427 /* load from immediate operand */
428 case FILTER_OP_LOAD_STRING:
02aca193 429 case FILTER_OP_LOAD_STAR_GLOB_STRING:
07dfc1d0
MD
430 {
431 struct load_op *insn = (struct load_op *) pc;
432 uint32_t str_len, maxlen;
433
434 if (unlikely(pc + sizeof(struct load_op)
435 > start_pc + bytecode->len)) {
436 ret = -ERANGE;
437 break;
438 }
439
440 maxlen = start_pc + bytecode->len - pc - sizeof(struct load_op);
441 str_len = strnlen(insn->data, maxlen);
442 if (unlikely(str_len >= maxlen)) {
443 /* Final '\0' not found within range */
444 ret = -ERANGE;
445 }
446 break;
447 }
448
449 case FILTER_OP_LOAD_S64:
450 {
451 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_numeric)
452 > start_pc + bytecode->len)) {
453 ret = -ERANGE;
454 }
455 break;
456 }
457
458 case FILTER_OP_CAST_TO_S64:
459 case FILTER_OP_CAST_NOP:
460 {
461 if (unlikely(pc + sizeof(struct cast_op)
462 > start_pc + bytecode->len)) {
463 ret = -ERANGE;
464 }
465 break;
466 }
467
3834b99f
MD
468 /*
469 * Instructions for recursive traversal through composed types.
470 */
471 case FILTER_OP_GET_CONTEXT_ROOT:
472 case FILTER_OP_GET_APP_CONTEXT_ROOT:
473 case FILTER_OP_GET_PAYLOAD_ROOT:
474 case FILTER_OP_LOAD_FIELD:
475 case FILTER_OP_LOAD_FIELD_S8:
476 case FILTER_OP_LOAD_FIELD_S16:
477 case FILTER_OP_LOAD_FIELD_S32:
478 case FILTER_OP_LOAD_FIELD_S64:
479 case FILTER_OP_LOAD_FIELD_U8:
480 case FILTER_OP_LOAD_FIELD_U16:
481 case FILTER_OP_LOAD_FIELD_U32:
482 case FILTER_OP_LOAD_FIELD_U64:
483 case FILTER_OP_LOAD_FIELD_STRING:
484 case FILTER_OP_LOAD_FIELD_SEQUENCE:
485 case FILTER_OP_LOAD_FIELD_DOUBLE:
486 if (unlikely(pc + sizeof(struct load_op)
487 > start_pc + bytecode->len)) {
488 ret = -ERANGE;
489 }
490 break;
491
492 case FILTER_OP_GET_SYMBOL:
493 {
494 struct load_op *insn = (struct load_op *) pc;
495 struct get_symbol *sym = (struct get_symbol *) insn->data;
496
497 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_symbol)
498 > start_pc + bytecode->len)) {
499 ret = -ERANGE;
3aeca857 500 break;
3834b99f
MD
501 }
502 ret = validate_get_symbol(bytecode, sym);
503 break;
504 }
505
506 case FILTER_OP_GET_SYMBOL_FIELD:
507 printk(KERN_WARNING "Unexpected get symbol field\n");
508 ret = -EINVAL;
509 break;
510
511 case FILTER_OP_GET_INDEX_U16:
512 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_index_u16)
513 > start_pc + bytecode->len)) {
514 ret = -ERANGE;
515 }
516 break;
517
518 case FILTER_OP_GET_INDEX_U64:
519 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_index_u64)
520 > start_pc + bytecode->len)) {
521 ret = -ERANGE;
522 }
523 break;
07dfc1d0
MD
524 }
525
526 return ret;
527}
528
529static
530unsigned long delete_all_nodes(struct mp_table *mp_table)
531{
532 struct mp_node *mp_node;
533 struct hlist_node *tmp;
534 unsigned long nr_nodes = 0;
535 int i;
536
537 for (i = 0; i < MERGE_POINT_TABLE_SIZE; i++) {
538 struct hlist_head *head;
539
540 head = &mp_table->mp_head[i];
d216ecae 541 lttng_hlist_for_each_entry_safe(mp_node, tmp, head, node) {
07dfc1d0
MD
542 kfree(mp_node);
543 nr_nodes++;
544 }
545 }
546 return nr_nodes;
547}
548
549/*
550 * Return value:
3834b99f 551 * >=0: success
07dfc1d0
MD
552 * <0: error
553 */
554static
555int validate_instruction_context(struct bytecode_runtime *bytecode,
556 struct vstack *stack,
7962cb86
MD
557 char *start_pc,
558 char *pc)
07dfc1d0
MD
559{
560 int ret = 0;
02aca193 561 const filter_opcode_t opcode = *(filter_opcode_t *) pc;
07dfc1d0 562
02aca193 563 switch (opcode) {
07dfc1d0
MD
564 case FILTER_OP_UNKNOWN:
565 default:
566 {
567 printk(KERN_WARNING "unknown bytecode op %u\n",
568 (unsigned int) *(filter_opcode_t *) pc);
569 ret = -EINVAL;
570 goto end;
571 }
572
573 case FILTER_OP_RETURN:
57ba4b41 574 case FILTER_OP_RETURN_S64:
07dfc1d0
MD
575 {
576 goto end;
577 }
578
579 /* binary */
580 case FILTER_OP_MUL:
581 case FILTER_OP_DIV:
582 case FILTER_OP_MOD:
583 case FILTER_OP_PLUS:
584 case FILTER_OP_MINUS:
07dfc1d0
MD
585 /* Floating point */
586 case FILTER_OP_EQ_DOUBLE:
587 case FILTER_OP_NE_DOUBLE:
588 case FILTER_OP_GT_DOUBLE:
589 case FILTER_OP_LT_DOUBLE:
590 case FILTER_OP_GE_DOUBLE:
591 case FILTER_OP_LE_DOUBLE:
592 case FILTER_OP_EQ_DOUBLE_S64:
593 case FILTER_OP_NE_DOUBLE_S64:
594 case FILTER_OP_GT_DOUBLE_S64:
595 case FILTER_OP_LT_DOUBLE_S64:
596 case FILTER_OP_GE_DOUBLE_S64:
597 case FILTER_OP_LE_DOUBLE_S64:
598 case FILTER_OP_EQ_S64_DOUBLE:
599 case FILTER_OP_NE_S64_DOUBLE:
600 case FILTER_OP_GT_S64_DOUBLE:
601 case FILTER_OP_LT_S64_DOUBLE:
602 case FILTER_OP_GE_S64_DOUBLE:
603 case FILTER_OP_LE_S64_DOUBLE:
604 case FILTER_OP_UNARY_PLUS_DOUBLE:
605 case FILTER_OP_UNARY_MINUS_DOUBLE:
606 case FILTER_OP_UNARY_NOT_DOUBLE:
607 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
608 case FILTER_OP_LOAD_DOUBLE:
609 case FILTER_OP_CAST_DOUBLE_TO_S64:
610 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
611 {
612 printk(KERN_WARNING "unsupported bytecode op %u\n",
613 (unsigned int) *(filter_opcode_t *) pc);
614 ret = -EINVAL;
615 goto end;
616 }
617
618 case FILTER_OP_EQ:
619 {
02aca193 620 ret = bin_op_compare_check(stack, opcode, "==");
3834b99f 621 if (ret < 0)
07dfc1d0
MD
622 goto end;
623 break;
624 }
625 case FILTER_OP_NE:
626 {
02aca193 627 ret = bin_op_compare_check(stack, opcode, "!=");
3834b99f 628 if (ret < 0)
07dfc1d0
MD
629 goto end;
630 break;
631 }
632 case FILTER_OP_GT:
633 {
02aca193 634 ret = bin_op_compare_check(stack, opcode, ">");
3834b99f 635 if (ret < 0)
07dfc1d0
MD
636 goto end;
637 break;
638 }
639 case FILTER_OP_LT:
640 {
02aca193 641 ret = bin_op_compare_check(stack, opcode, "<");
3834b99f 642 if (ret < 0)
07dfc1d0
MD
643 goto end;
644 break;
645 }
646 case FILTER_OP_GE:
647 {
02aca193 648 ret = bin_op_compare_check(stack, opcode, ">=");
3834b99f 649 if (ret < 0)
07dfc1d0
MD
650 goto end;
651 break;
652 }
653 case FILTER_OP_LE:
654 {
02aca193 655 ret = bin_op_compare_check(stack, opcode, "<=");
3834b99f 656 if (ret < 0)
07dfc1d0
MD
657 goto end;
658 break;
659 }
660
661 case FILTER_OP_EQ_STRING:
662 case FILTER_OP_NE_STRING:
663 case FILTER_OP_GT_STRING:
664 case FILTER_OP_LT_STRING:
665 case FILTER_OP_GE_STRING:
666 case FILTER_OP_LE_STRING:
667 {
668 if (!vstack_ax(stack) || !vstack_bx(stack)) {
669 printk(KERN_WARNING "Empty stack\n");
670 ret = -EINVAL;
671 goto end;
672 }
673 if (vstack_ax(stack)->type != REG_STRING
674 || vstack_bx(stack)->type != REG_STRING) {
675 printk(KERN_WARNING "Unexpected register type for string comparator\n");
676 ret = -EINVAL;
677 goto end;
678 }
679 break;
680 }
681
02aca193
PP
682
683 case FILTER_OP_EQ_STAR_GLOB_STRING:
684 case FILTER_OP_NE_STAR_GLOB_STRING:
685 {
686 if (!vstack_ax(stack) || !vstack_bx(stack)) {
687 printk(KERN_WARNING "Empty stack\n");
688 ret = -EINVAL;
689 goto end;
690 }
691 if (vstack_ax(stack)->type != REG_STAR_GLOB_STRING
692 && vstack_bx(stack)->type != REG_STAR_GLOB_STRING) {
693 printk(KERN_WARNING "Unexpected register type for globbing pattern comparator\n");
694 ret = -EINVAL;
695 goto end;
696 }
697 break;
698 }
699
07dfc1d0
MD
700 case FILTER_OP_EQ_S64:
701 case FILTER_OP_NE_S64:
702 case FILTER_OP_GT_S64:
703 case FILTER_OP_LT_S64:
704 case FILTER_OP_GE_S64:
705 case FILTER_OP_LE_S64:
706 {
707 if (!vstack_ax(stack) || !vstack_bx(stack)) {
708 printk(KERN_WARNING "Empty stack\n");
709 ret = -EINVAL;
710 goto end;
711 }
712 if (vstack_ax(stack)->type != REG_S64
713 || vstack_bx(stack)->type != REG_S64) {
714 printk(KERN_WARNING "Unexpected register type for s64 comparator\n");
715 ret = -EINVAL;
716 goto end;
717 }
718 break;
719 }
720
e16c054b
MD
721 case FILTER_OP_BIT_RSHIFT:
722 ret = bin_op_bitwise_check(stack, opcode, ">>");
723 if (ret < 0)
724 goto end;
725 break;
726 case FILTER_OP_BIT_LSHIFT:
727 ret = bin_op_bitwise_check(stack, opcode, "<<");
728 if (ret < 0)
729 goto end;
730 break;
3834b99f
MD
731 case FILTER_OP_BIT_AND:
732 ret = bin_op_bitwise_check(stack, opcode, "&");
733 if (ret < 0)
734 goto end;
735 break;
736 case FILTER_OP_BIT_OR:
737 ret = bin_op_bitwise_check(stack, opcode, "|");
738 if (ret < 0)
739 goto end;
740 break;
741 case FILTER_OP_BIT_XOR:
742 ret = bin_op_bitwise_check(stack, opcode, "^");
743 if (ret < 0)
744 goto end;
745 break;
746
07dfc1d0
MD
747 /* unary */
748 case FILTER_OP_UNARY_PLUS:
749 case FILTER_OP_UNARY_MINUS:
750 case FILTER_OP_UNARY_NOT:
751 {
752 if (!vstack_ax(stack)) {
753 printk(KERN_WARNING "Empty stack\n");
754 ret = -EINVAL;
755 goto end;
756 }
757 switch (vstack_ax(stack)->type) {
758 default:
759 case REG_DOUBLE:
760 printk(KERN_WARNING "unknown register type\n");
761 ret = -EINVAL;
762 goto end;
763
764 case REG_STRING:
02aca193 765 case REG_STAR_GLOB_STRING:
07dfc1d0
MD
766 printk(KERN_WARNING "Unary op can only be applied to numeric or floating point registers\n");
767 ret = -EINVAL;
768 goto end;
769 case REG_S64:
3834b99f 770 case REG_TYPE_UNKNOWN:
07dfc1d0
MD
771 break;
772 }
773 break;
774 }
e16c054b
MD
775 case FILTER_OP_UNARY_BIT_NOT:
776 {
777 if (!vstack_ax(stack)) {
778 printk(KERN_WARNING "Empty stack\n");
779 ret = -EINVAL;
780 goto end;
781 }
782 switch (vstack_ax(stack)->type) {
783 default:
784 printk(KERN_WARNING "unknown register type\n");
785 ret = -EINVAL;
786 goto end;
787
788 case REG_STRING:
789 case REG_STAR_GLOB_STRING:
790 case REG_DOUBLE:
791 printk(KERN_WARNING "Unary bitwise op can only be applied to numeric registers\n");
792 ret = -EINVAL;
793 goto end;
794 case REG_S64:
795 break;
796 case REG_TYPE_UNKNOWN:
797 break;
798 }
799 break;
800 }
07dfc1d0
MD
801
802 case FILTER_OP_UNARY_PLUS_S64:
803 case FILTER_OP_UNARY_MINUS_S64:
804 case FILTER_OP_UNARY_NOT_S64:
805 {
806 if (!vstack_ax(stack)) {
807 printk(KERN_WARNING "Empty stack\n");
808 ret = -EINVAL;
809 goto end;
810 }
811 if (vstack_ax(stack)->type != REG_S64) {
812 printk(KERN_WARNING "Invalid register type\n");
813 ret = -EINVAL;
814 goto end;
815 }
816 break;
817 }
818
819 /* logical */
820 case FILTER_OP_AND:
821 case FILTER_OP_OR:
822 {
823 struct logical_op *insn = (struct logical_op *) pc;
824
825 if (!vstack_ax(stack)) {
826 printk(KERN_WARNING "Empty stack\n");
827 ret = -EINVAL;
828 goto end;
829 }
830 if (vstack_ax(stack)->type != REG_S64) {
831 printk(KERN_WARNING "Logical comparator expects S64 register\n");
832 ret = -EINVAL;
833 goto end;
834 }
835
836 dbg_printk("Validate jumping to bytecode offset %u\n",
837 (unsigned int) insn->skip_offset);
838 if (unlikely(start_pc + insn->skip_offset <= pc)) {
839 printk(KERN_WARNING "Loops are not allowed in bytecode\n");
840 ret = -EINVAL;
841 goto end;
842 }
843 break;
844 }
845
846 /* load field ref */
847 case FILTER_OP_LOAD_FIELD_REF:
848 {
849 printk(KERN_WARNING "Unknown field ref type\n");
850 ret = -EINVAL;
851 goto end;
852 }
853 case FILTER_OP_LOAD_FIELD_REF_STRING:
854 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
f127e61e
MD
855 case FILTER_OP_LOAD_FIELD_REF_USER_STRING:
856 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE:
07dfc1d0
MD
857 {
858 struct load_op *insn = (struct load_op *) pc;
859 struct field_ref *ref = (struct field_ref *) insn->data;
860
861 dbg_printk("Validate load field ref offset %u type string\n",
862 ref->offset);
863 break;
864 }
865 case FILTER_OP_LOAD_FIELD_REF_S64:
866 {
867 struct load_op *insn = (struct load_op *) pc;
868 struct field_ref *ref = (struct field_ref *) insn->data;
869
870 dbg_printk("Validate load field ref offset %u type s64\n",
871 ref->offset);
872 break;
873 }
874
875 /* load from immediate operand */
876 case FILTER_OP_LOAD_STRING:
02aca193 877 case FILTER_OP_LOAD_STAR_GLOB_STRING:
07dfc1d0
MD
878 {
879 break;
880 }
881
882 case FILTER_OP_LOAD_S64:
883 {
884 break;
885 }
886
887 case FILTER_OP_CAST_TO_S64:
888 {
889 struct cast_op *insn = (struct cast_op *) pc;
890
891 if (!vstack_ax(stack)) {
892 printk(KERN_WARNING "Empty stack\n");
893 ret = -EINVAL;
894 goto end;
895 }
896 switch (vstack_ax(stack)->type) {
897 default:
898 case REG_DOUBLE:
899 printk(KERN_WARNING "unknown register type\n");
900 ret = -EINVAL;
901 goto end;
902
903 case REG_STRING:
02aca193 904 case REG_STAR_GLOB_STRING:
07dfc1d0
MD
905 printk(KERN_WARNING "Cast op can only be applied to numeric or floating point registers\n");
906 ret = -EINVAL;
907 goto end;
908 case REG_S64:
909 break;
910 }
911 if (insn->op == FILTER_OP_CAST_DOUBLE_TO_S64) {
912 if (vstack_ax(stack)->type != REG_DOUBLE) {
913 printk(KERN_WARNING "Cast expects double\n");
914 ret = -EINVAL;
915 goto end;
916 }
917 }
918 break;
919 }
920 case FILTER_OP_CAST_NOP:
921 {
922 break;
923 }
924
925 /* get context ref */
926 case FILTER_OP_GET_CONTEXT_REF:
927 {
928 printk(KERN_WARNING "Unknown get context ref type\n");
929 ret = -EINVAL;
930 goto end;
931 }
932 case FILTER_OP_GET_CONTEXT_REF_STRING:
933 {
934 struct load_op *insn = (struct load_op *) pc;
935 struct field_ref *ref = (struct field_ref *) insn->data;
936
937 dbg_printk("Validate get context ref offset %u type string\n",
938 ref->offset);
939 break;
940 }
941 case FILTER_OP_GET_CONTEXT_REF_S64:
942 {
943 struct load_op *insn = (struct load_op *) pc;
944 struct field_ref *ref = (struct field_ref *) insn->data;
945
946 dbg_printk("Validate get context ref offset %u type s64\n",
947 ref->offset);
948 break;
949 }
950
3834b99f
MD
951 /*
952 * Instructions for recursive traversal through composed types.
953 */
954 case FILTER_OP_GET_CONTEXT_ROOT:
955 {
956 dbg_printk("Validate get context root\n");
957 break;
958 }
959 case FILTER_OP_GET_APP_CONTEXT_ROOT:
960 {
961 dbg_printk("Validate get app context root\n");
962 break;
963 }
964 case FILTER_OP_GET_PAYLOAD_ROOT:
965 {
966 dbg_printk("Validate get payload root\n");
967 break;
968 }
969 case FILTER_OP_LOAD_FIELD:
970 {
971 /*
972 * We tolerate that field type is unknown at validation,
973 * because we are performing the load specialization in
974 * a phase after validation.
975 */
976 dbg_printk("Validate load field\n");
977 break;
978 }
499ac8be
MD
979
980 /*
981 * Disallow already specialized bytecode op load field instructions to
982 * ensure that the received bytecode does not:
983 *
984 * - Read user-space memory without proper get_user accessors,
985 * - Read a memory area larger than the memory targeted by the instrumentation.
986 */
3834b99f 987 case FILTER_OP_LOAD_FIELD_S8:
3834b99f 988 case FILTER_OP_LOAD_FIELD_S16:
3834b99f 989 case FILTER_OP_LOAD_FIELD_S32:
3834b99f 990 case FILTER_OP_LOAD_FIELD_S64:
3834b99f 991 case FILTER_OP_LOAD_FIELD_U8:
3834b99f 992 case FILTER_OP_LOAD_FIELD_U16:
3834b99f 993 case FILTER_OP_LOAD_FIELD_U32:
3834b99f 994 case FILTER_OP_LOAD_FIELD_U64:
3834b99f 995 case FILTER_OP_LOAD_FIELD_STRING:
3834b99f 996 case FILTER_OP_LOAD_FIELD_SEQUENCE:
3834b99f
MD
997 case FILTER_OP_LOAD_FIELD_DOUBLE:
998 {
499ac8be
MD
999 dbg_printk("Validate load field, reject specialized load instruction (%d)\n",
1000 (int) opcode);
1001 ret = -EINVAL;
1002 goto end;
3834b99f
MD
1003 }
1004
1005 case FILTER_OP_GET_SYMBOL:
1006 {
1007 struct load_op *insn = (struct load_op *) pc;
1008 struct get_symbol *sym = (struct get_symbol *) insn->data;
1009
1010 dbg_printk("Validate get symbol offset %u\n", sym->offset);
1011 break;
1012 }
1013
1014 case FILTER_OP_GET_SYMBOL_FIELD:
1015 {
1016 struct load_op *insn = (struct load_op *) pc;
1017 struct get_symbol *sym = (struct get_symbol *) insn->data;
1018
1019 dbg_printk("Validate get symbol field offset %u\n", sym->offset);
1020 break;
1021 }
1022
1023 case FILTER_OP_GET_INDEX_U16:
1024 {
1025 struct load_op *insn = (struct load_op *) pc;
1026 struct get_index_u16 *get_index = (struct get_index_u16 *) insn->data;
1027
1028 dbg_printk("Validate get index u16 index %u\n", get_index->index);
1029 break;
1030 }
1031
1032 case FILTER_OP_GET_INDEX_U64:
1033 {
1034 struct load_op *insn = (struct load_op *) pc;
1035 struct get_index_u64 *get_index = (struct get_index_u64 *) insn->data;
1036
1037 dbg_printk("Validate get index u64 index %llu\n",
1038 (unsigned long long) get_index->index);
1039 break;
1040 }
07dfc1d0
MD
1041 }
1042end:
1043 return ret;
1044}
1045
1046/*
1047 * Return value:
1048 * 0: success
1049 * <0: error
1050 */
1051static
1052int validate_instruction_all_contexts(struct bytecode_runtime *bytecode,
1053 struct mp_table *mp_table,
1054 struct vstack *stack,
7962cb86
MD
1055 char *start_pc,
1056 char *pc)
07dfc1d0
MD
1057{
1058 int ret, found = 0;
1059 unsigned long target_pc = pc - start_pc;
1060 unsigned long hash;
1061 struct hlist_head *head;
1062 struct mp_node *mp_node;
1063
1064 /* Validate the context resulting from the previous instruction */
1065 ret = validate_instruction_context(bytecode, stack, start_pc, pc);
3834b99f 1066 if (ret < 0)
07dfc1d0
MD
1067 return ret;
1068
1069 /* Validate merge points */
1070 hash = jhash_1word(target_pc, 0);
1071 head = &mp_table->mp_head[hash & (MERGE_POINT_TABLE_SIZE - 1)];
d216ecae 1072 lttng_hlist_for_each_entry(mp_node, head, node) {
07dfc1d0
MD
1073 if (lttng_hash_match(mp_node, target_pc)) {
1074 found = 1;
1075 break;
1076 }
1077 }
1078 if (found) {
1079 dbg_printk("Filter: validate merge point at offset %lu\n",
1080 target_pc);
1081 if (merge_points_compare(stack, &mp_node->stack)) {
1082 printk(KERN_WARNING "Merge points differ for offset %lu\n",
1083 target_pc);
1084 return -EINVAL;
1085 }
1086 /* Once validated, we can remove the merge point */
1087 dbg_printk("Filter: remove merge point at offset %lu\n",
1088 target_pc);
1089 hlist_del(&mp_node->node);
1090 }
1091 return 0;
1092}
1093
1094/*
1095 * Return value:
1096 * >0: going to next insn.
1097 * 0: success, stop iteration.
1098 * <0: error
1099 */
1100static
1101int exec_insn(struct bytecode_runtime *bytecode,
1102 struct mp_table *mp_table,
1103 struct vstack *stack,
7962cb86
MD
1104 char **_next_pc,
1105 char *pc)
07dfc1d0
MD
1106{
1107 int ret = 1;
7962cb86 1108 char *next_pc = *_next_pc;
07dfc1d0
MD
1109
1110 switch (*(filter_opcode_t *) pc) {
1111 case FILTER_OP_UNKNOWN:
1112 default:
1113 {
1114 printk(KERN_WARNING "unknown bytecode op %u\n",
1115 (unsigned int) *(filter_opcode_t *) pc);
1116 ret = -EINVAL;
1117 goto end;
1118 }
1119
1120 case FILTER_OP_RETURN:
1121 {
1122 if (!vstack_ax(stack)) {
1123 printk(KERN_WARNING "Empty stack\n");
1124 ret = -EINVAL;
1125 goto end;
1126 }
3834b99f
MD
1127 switch (vstack_ax(stack)->type) {
1128 case REG_S64:
1129 case REG_TYPE_UNKNOWN:
1130 break;
1131 default:
1132 printk(KERN_WARNING "Unexpected register type %d at end of bytecode\n",
1133 (int) vstack_ax(stack)->type);
1134 ret = -EINVAL;
1135 goto end;
1136 }
1137
07dfc1d0
MD
1138 ret = 0;
1139 goto end;
1140 }
1141
57ba4b41
MD
1142 case FILTER_OP_RETURN_S64:
1143 {
1144 if (!vstack_ax(stack)) {
1145 printk(KERN_WARNING "Empty stack\n");
1146 ret = -EINVAL;
1147 goto end;
1148 }
1149 switch (vstack_ax(stack)->type) {
1150 case REG_S64:
1151 break;
1152 default:
1153 case REG_TYPE_UNKNOWN:
1154 printk(KERN_WARNING "Unexpected register type %d at end of bytecode\n",
1155 (int) vstack_ax(stack)->type);
1156 ret = -EINVAL;
1157 goto end;
1158 }
1159
1160 ret = 0;
1161 goto end;
1162 }
1163
07dfc1d0
MD
1164 /* binary */
1165 case FILTER_OP_MUL:
1166 case FILTER_OP_DIV:
1167 case FILTER_OP_MOD:
1168 case FILTER_OP_PLUS:
1169 case FILTER_OP_MINUS:
07dfc1d0
MD
1170 /* Floating point */
1171 case FILTER_OP_EQ_DOUBLE:
1172 case FILTER_OP_NE_DOUBLE:
1173 case FILTER_OP_GT_DOUBLE:
1174 case FILTER_OP_LT_DOUBLE:
1175 case FILTER_OP_GE_DOUBLE:
1176 case FILTER_OP_LE_DOUBLE:
1177 case FILTER_OP_EQ_DOUBLE_S64:
1178 case FILTER_OP_NE_DOUBLE_S64:
1179 case FILTER_OP_GT_DOUBLE_S64:
1180 case FILTER_OP_LT_DOUBLE_S64:
1181 case FILTER_OP_GE_DOUBLE_S64:
1182 case FILTER_OP_LE_DOUBLE_S64:
1183 case FILTER_OP_EQ_S64_DOUBLE:
1184 case FILTER_OP_NE_S64_DOUBLE:
1185 case FILTER_OP_GT_S64_DOUBLE:
1186 case FILTER_OP_LT_S64_DOUBLE:
1187 case FILTER_OP_GE_S64_DOUBLE:
1188 case FILTER_OP_LE_S64_DOUBLE:
1189 case FILTER_OP_UNARY_PLUS_DOUBLE:
1190 case FILTER_OP_UNARY_MINUS_DOUBLE:
1191 case FILTER_OP_UNARY_NOT_DOUBLE:
1192 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1193 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
1194 case FILTER_OP_LOAD_DOUBLE:
1195 case FILTER_OP_CAST_DOUBLE_TO_S64:
1196 {
1197 printk(KERN_WARNING "unsupported bytecode op %u\n",
1198 (unsigned int) *(filter_opcode_t *) pc);
1199 ret = -EINVAL;
1200 goto end;
1201 }
1202
1203 case FILTER_OP_EQ:
1204 case FILTER_OP_NE:
1205 case FILTER_OP_GT:
1206 case FILTER_OP_LT:
1207 case FILTER_OP_GE:
1208 case FILTER_OP_LE:
1209 case FILTER_OP_EQ_STRING:
1210 case FILTER_OP_NE_STRING:
1211 case FILTER_OP_GT_STRING:
1212 case FILTER_OP_LT_STRING:
1213 case FILTER_OP_GE_STRING:
1214 case FILTER_OP_LE_STRING:
02aca193
PP
1215 case FILTER_OP_EQ_STAR_GLOB_STRING:
1216 case FILTER_OP_NE_STAR_GLOB_STRING:
07dfc1d0
MD
1217 case FILTER_OP_EQ_S64:
1218 case FILTER_OP_NE_S64:
1219 case FILTER_OP_GT_S64:
1220 case FILTER_OP_LT_S64:
1221 case FILTER_OP_GE_S64:
1222 case FILTER_OP_LE_S64:
e16c054b
MD
1223 case FILTER_OP_BIT_RSHIFT:
1224 case FILTER_OP_BIT_LSHIFT:
3834b99f
MD
1225 case FILTER_OP_BIT_AND:
1226 case FILTER_OP_BIT_OR:
1227 case FILTER_OP_BIT_XOR:
07dfc1d0
MD
1228 {
1229 /* Pop 2, push 1 */
1230 if (vstack_pop(stack)) {
1231 ret = -EINVAL;
1232 goto end;
1233 }
1234 if (!vstack_ax(stack)) {
1235 printk(KERN_WARNING "Empty stack\n");
1236 ret = -EINVAL;
1237 goto end;
1238 }
3834b99f
MD
1239 switch (vstack_ax(stack)->type) {
1240 case REG_S64:
1241 case REG_DOUBLE:
1242 case REG_STRING:
1243 case REG_STAR_GLOB_STRING:
1244 case REG_TYPE_UNKNOWN:
1245 break;
1246 default:
1247 printk(KERN_WARNING "Unexpected register type %d for operation\n",
1248 (int) vstack_ax(stack)->type);
1249 ret = -EINVAL;
1250 goto end;
1251 }
1252
07dfc1d0
MD
1253 vstack_ax(stack)->type = REG_S64;
1254 next_pc += sizeof(struct binary_op);
1255 break;
1256 }
1257
1258 /* unary */
1259 case FILTER_OP_UNARY_PLUS:
1260 case FILTER_OP_UNARY_MINUS:
3834b99f
MD
1261 {
1262 /* Pop 1, push 1 */
1263 if (!vstack_ax(stack)) {
1264 printk(KERN_WARNING "Empty stack\n\n");
1265 ret = -EINVAL;
1266 goto end;
1267 }
1268 switch (vstack_ax(stack)->type) {
1269 case REG_S64:
1270 case REG_TYPE_UNKNOWN:
1271 break;
1272 default:
1273 printk(KERN_WARNING "Unexpected register type %d for operation\n",
1274 (int) vstack_ax(stack)->type);
1275 ret = -EINVAL;
1276 goto end;
1277 }
1278
1279 vstack_ax(stack)->type = REG_TYPE_UNKNOWN;
1280 next_pc += sizeof(struct unary_op);
1281 break;
1282 }
1283
07dfc1d0
MD
1284 case FILTER_OP_UNARY_PLUS_S64:
1285 case FILTER_OP_UNARY_MINUS_S64:
1286 case FILTER_OP_UNARY_NOT_S64:
1287 {
1288 /* Pop 1, push 1 */
1289 if (!vstack_ax(stack)) {
3834b99f
MD
1290 printk(KERN_WARNING "Empty stack\n\n");
1291 ret = -EINVAL;
1292 goto end;
1293 }
1294 switch (vstack_ax(stack)->type) {
1295 case REG_S64:
1296 break;
1297 default:
1298 printk(KERN_WARNING "Unexpected register type %d for operation\n",
1299 (int) vstack_ax(stack)->type);
1300 ret = -EINVAL;
1301 goto end;
1302 }
1303
1304 vstack_ax(stack)->type = REG_S64;
1305 next_pc += sizeof(struct unary_op);
1306 break;
1307 }
1308
1309 case FILTER_OP_UNARY_NOT:
1310 {
1311 /* Pop 1, push 1 */
1312 if (!vstack_ax(stack)) {
1313 printk(KERN_WARNING "Empty stack\n\n");
1314 ret = -EINVAL;
1315 goto end;
1316 }
1317 switch (vstack_ax(stack)->type) {
1318 case REG_S64:
1319 case REG_TYPE_UNKNOWN:
1320 break;
1321 default:
1322 printk(KERN_WARNING "Unexpected register type %d for operation\n",
e16c054b
MD
1323 (int) vstack_ax(stack)->type);
1324 ret = -EINVAL;
1325 goto end;
1326 }
1327
1328 vstack_ax(stack)->type = REG_S64;
1329 next_pc += sizeof(struct unary_op);
1330 break;
1331 }
1332
1333 case FILTER_OP_UNARY_BIT_NOT:
1334 {
1335 /* Pop 1, push 1 */
1336 if (!vstack_ax(stack)) {
1337 printk(KERN_WARNING "Empty stack\n");
1338 ret = -EINVAL;
1339 goto end;
1340 }
1341 switch (vstack_ax(stack)->type) {
1342 case REG_S64:
1343 case REG_TYPE_UNKNOWN:
1344 break;
1345 case REG_DOUBLE:
1346 default:
1347 printk(KERN_WARNING "Unexpected register type %d for operation\n",
3834b99f 1348 (int) vstack_ax(stack)->type);
07dfc1d0
MD
1349 ret = -EINVAL;
1350 goto end;
1351 }
3834b99f 1352
07dfc1d0
MD
1353 vstack_ax(stack)->type = REG_S64;
1354 next_pc += sizeof(struct unary_op);
1355 break;
1356 }
1357
1358 /* logical */
1359 case FILTER_OP_AND:
1360 case FILTER_OP_OR:
1361 {
1362 struct logical_op *insn = (struct logical_op *) pc;
1363 int merge_ret;
1364
1365 /* Add merge point to table */
1366 merge_ret = merge_point_add_check(mp_table,
1367 insn->skip_offset, stack);
1368 if (merge_ret) {
1369 ret = merge_ret;
1370 goto end;
1371 }
3834b99f
MD
1372
1373 if (!vstack_ax(stack)) {
1374 printk(KERN_WARNING "Empty stack\n\n");
1375 ret = -EINVAL;
1376 goto end;
1377 }
1378 /* There is always a cast-to-s64 operation before a or/and op. */
1379 switch (vstack_ax(stack)->type) {
1380 case REG_S64:
1381 break;
1382 default:
1383 printk(KERN_WARNING "Incorrect register type %d for operation\n",
1384 (int) vstack_ax(stack)->type);
1385 ret = -EINVAL;
1386 goto end;
1387 }
1388
07dfc1d0
MD
1389 /* Continue to next instruction */
1390 /* Pop 1 when jump not taken */
1391 if (vstack_pop(stack)) {
1392 ret = -EINVAL;
1393 goto end;
1394 }
1395 next_pc += sizeof(struct logical_op);
1396 break;
1397 }
1398
1399 /* load field ref */
1400 case FILTER_OP_LOAD_FIELD_REF:
1401 {
1402 printk(KERN_WARNING "Unknown field ref type\n");
1403 ret = -EINVAL;
1404 goto end;
1405 }
1406 /* get context ref */
1407 case FILTER_OP_GET_CONTEXT_REF:
1408 {
1409 printk(KERN_WARNING "Unknown get context ref type\n");
1410 ret = -EINVAL;
1411 goto end;
1412 }
1413 case FILTER_OP_LOAD_FIELD_REF_STRING:
1414 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1415 case FILTER_OP_GET_CONTEXT_REF_STRING:
f127e61e
MD
1416 case FILTER_OP_LOAD_FIELD_REF_USER_STRING:
1417 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE:
07dfc1d0
MD
1418 {
1419 if (vstack_push(stack)) {
1420 ret = -EINVAL;
1421 goto end;
1422 }
1423 vstack_ax(stack)->type = REG_STRING;
1424 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1425 break;
1426 }
1427 case FILTER_OP_LOAD_FIELD_REF_S64:
1428 case FILTER_OP_GET_CONTEXT_REF_S64:
1429 {
1430 if (vstack_push(stack)) {
1431 ret = -EINVAL;
1432 goto end;
1433 }
1434 vstack_ax(stack)->type = REG_S64;
1435 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1436 break;
1437 }
1438
1439 /* load from immediate operand */
1440 case FILTER_OP_LOAD_STRING:
1441 {
1442 struct load_op *insn = (struct load_op *) pc;
1443
1444 if (vstack_push(stack)) {
1445 ret = -EINVAL;
1446 goto end;
1447 }
1448 vstack_ax(stack)->type = REG_STRING;
1449 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
02aca193
PP
1450 break;
1451 }
1452
1453 case FILTER_OP_LOAD_STAR_GLOB_STRING:
1454 {
1455 struct load_op *insn = (struct load_op *) pc;
1456
1457 if (vstack_push(stack)) {
1458 ret = -EINVAL;
1459 goto end;
1460 }
1461 vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
1462 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
07dfc1d0
MD
1463 break;
1464 }
1465
1466 case FILTER_OP_LOAD_S64:
1467 {
1468 if (vstack_push(stack)) {
1469 ret = -EINVAL;
1470 goto end;
1471 }
1472 vstack_ax(stack)->type = REG_S64;
1473 next_pc += sizeof(struct load_op)
1474 + sizeof(struct literal_numeric);
1475 break;
1476 }
1477
1478 case FILTER_OP_CAST_TO_S64:
1479 {
1480 /* Pop 1, push 1 */
1481 if (!vstack_ax(stack)) {
1482 printk(KERN_WARNING "Empty stack\n");
1483 ret = -EINVAL;
1484 goto end;
1485 }
3834b99f
MD
1486 switch (vstack_ax(stack)->type) {
1487 case REG_S64:
1488 case REG_DOUBLE:
1489 case REG_TYPE_UNKNOWN:
1490 break;
1491 default:
1492 printk(KERN_WARNING "Incorrect register type %d for cast\n",
1493 (int) vstack_ax(stack)->type);
1494 ret = -EINVAL;
1495 goto end;
1496 }
07dfc1d0
MD
1497 vstack_ax(stack)->type = REG_S64;
1498 next_pc += sizeof(struct cast_op);
1499 break;
1500 }
1501 case FILTER_OP_CAST_NOP:
1502 {
1503 next_pc += sizeof(struct cast_op);
1504 break;
1505 }
1506
3834b99f
MD
1507 /*
1508 * Instructions for recursive traversal through composed types.
1509 */
1510 case FILTER_OP_GET_CONTEXT_ROOT:
1511 case FILTER_OP_GET_APP_CONTEXT_ROOT:
1512 case FILTER_OP_GET_PAYLOAD_ROOT:
1513 {
1514 if (vstack_push(stack)) {
1515 ret = -EINVAL;
1516 goto end;
1517 }
1518 vstack_ax(stack)->type = REG_PTR;
1519 next_pc += sizeof(struct load_op);
1520 break;
1521 }
1522
1523 case FILTER_OP_LOAD_FIELD:
1524 {
1525 /* Pop 1, push 1 */
1526 if (!vstack_ax(stack)) {
1527 printk(KERN_WARNING "Empty stack\n\n");
1528 ret = -EINVAL;
1529 goto end;
1530 }
1531 if (vstack_ax(stack)->type != REG_PTR) {
1532 printk(KERN_WARNING "Expecting pointer on top of stack\n\n");
1533 ret = -EINVAL;
1534 goto end;
1535 }
1536 vstack_ax(stack)->type = REG_TYPE_UNKNOWN;
1537 next_pc += sizeof(struct load_op);
1538 break;
1539 }
1540
1541 case FILTER_OP_LOAD_FIELD_S8:
1542 case FILTER_OP_LOAD_FIELD_S16:
1543 case FILTER_OP_LOAD_FIELD_S32:
1544 case FILTER_OP_LOAD_FIELD_S64:
1545 case FILTER_OP_LOAD_FIELD_U8:
1546 case FILTER_OP_LOAD_FIELD_U16:
1547 case FILTER_OP_LOAD_FIELD_U32:
1548 case FILTER_OP_LOAD_FIELD_U64:
1549 {
1550 /* Pop 1, push 1 */
1551 if (!vstack_ax(stack)) {
1552 printk(KERN_WARNING "Empty stack\n\n");
1553 ret = -EINVAL;
1554 goto end;
1555 }
1556 if (vstack_ax(stack)->type != REG_PTR) {
1557 printk(KERN_WARNING "Expecting pointer on top of stack\n\n");
1558 ret = -EINVAL;
1559 goto end;
1560 }
1561 vstack_ax(stack)->type = REG_S64;
1562 next_pc += sizeof(struct load_op);
1563 break;
1564 }
1565
1566 case FILTER_OP_LOAD_FIELD_STRING:
1567 case FILTER_OP_LOAD_FIELD_SEQUENCE:
1568 {
1569 /* Pop 1, push 1 */
1570 if (!vstack_ax(stack)) {
1571 printk(KERN_WARNING "Empty stack\n\n");
1572 ret = -EINVAL;
1573 goto end;
1574 }
1575 if (vstack_ax(stack)->type != REG_PTR) {
1576 printk(KERN_WARNING "Expecting pointer on top of stack\n\n");
1577 ret = -EINVAL;
1578 goto end;
1579 }
1580 vstack_ax(stack)->type = REG_STRING;
1581 next_pc += sizeof(struct load_op);
1582 break;
1583 }
1584
1585 case FILTER_OP_LOAD_FIELD_DOUBLE:
1586 {
1587 /* Pop 1, push 1 */
1588 if (!vstack_ax(stack)) {
1589 printk(KERN_WARNING "Empty stack\n\n");
1590 ret = -EINVAL;
1591 goto end;
1592 }
1593 if (vstack_ax(stack)->type != REG_PTR) {
1594 printk(KERN_WARNING "Expecting pointer on top of stack\n\n");
1595 ret = -EINVAL;
1596 goto end;
1597 }
1598 vstack_ax(stack)->type = REG_DOUBLE;
1599 next_pc += sizeof(struct load_op);
1600 break;
1601 }
1602
1603 case FILTER_OP_GET_SYMBOL:
1604 case FILTER_OP_GET_SYMBOL_FIELD:
1605 {
1606 /* Pop 1, push 1 */
1607 if (!vstack_ax(stack)) {
1608 printk(KERN_WARNING "Empty stack\n\n");
1609 ret = -EINVAL;
1610 goto end;
1611 }
1612 if (vstack_ax(stack)->type != REG_PTR) {
1613 printk(KERN_WARNING "Expecting pointer on top of stack\n\n");
1614 ret = -EINVAL;
1615 goto end;
1616 }
1617 next_pc += sizeof(struct load_op) + sizeof(struct get_symbol);
1618 break;
1619 }
1620
1621 case FILTER_OP_GET_INDEX_U16:
1622 {
1623 /* Pop 1, push 1 */
1624 if (!vstack_ax(stack)) {
1625 printk(KERN_WARNING "Empty stack\n\n");
1626 ret = -EINVAL;
1627 goto end;
1628 }
1629 if (vstack_ax(stack)->type != REG_PTR) {
1630 printk(KERN_WARNING "Expecting pointer on top of stack\n\n");
1631 ret = -EINVAL;
1632 goto end;
1633 }
1634 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16);
1635 break;
1636 }
1637
1638 case FILTER_OP_GET_INDEX_U64:
1639 {
1640 /* Pop 1, push 1 */
1641 if (!vstack_ax(stack)) {
1642 printk(KERN_WARNING "Empty stack\n\n");
1643 ret = -EINVAL;
1644 goto end;
1645 }
1646 if (vstack_ax(stack)->type != REG_PTR) {
1647 printk(KERN_WARNING "Expecting pointer on top of stack\n\n");
1648 ret = -EINVAL;
1649 goto end;
1650 }
1651 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64);
1652 break;
1653 }
1654
07dfc1d0
MD
1655 }
1656end:
1657 *_next_pc = next_pc;
1658 return ret;
1659}
1660
1661/*
1662 * Never called concurrently (hash seed is shared).
1663 */
1664int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
1665{
1666 struct mp_table *mp_table;
7962cb86 1667 char *pc, *next_pc, *start_pc;
07dfc1d0
MD
1668 int ret = -EINVAL;
1669 struct vstack stack;
1670
1671 vstack_init(&stack);
1672
1673 mp_table = kzalloc(sizeof(*mp_table), GFP_KERNEL);
1674 if (!mp_table) {
1675 printk(KERN_WARNING "Error allocating hash table for bytecode validation\n");
1676 return -ENOMEM;
1677 }
3834b99f 1678 start_pc = &bytecode->code[0];
07dfc1d0
MD
1679 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1680 pc = next_pc) {
1681 ret = bytecode_validate_overflow(bytecode, start_pc, pc);
1682 if (ret != 0) {
1683 if (ret == -ERANGE)
1684 printk(KERN_WARNING "filter bytecode overflow\n");
1685 goto end;
1686 }
1687 dbg_printk("Validating op %s (%u)\n",
1688 lttng_filter_print_op((unsigned int) *(filter_opcode_t *) pc),
1689 (unsigned int) *(filter_opcode_t *) pc);
1690
1691 /*
1692 * For each instruction, validate the current context
1693 * (traversal of entire execution flow), and validate
3834b99f 1694 * all merge points targeting this instruction.
07dfc1d0
MD
1695 */
1696 ret = validate_instruction_all_contexts(bytecode, mp_table,
1697 &stack, start_pc, pc);
1698 if (ret)
1699 goto end;
1700 ret = exec_insn(bytecode, mp_table, &stack, &next_pc, pc);
1701 if (ret <= 0)
1702 goto end;
1703 }
1704end:
1705 if (delete_all_nodes(mp_table)) {
1706 if (!ret) {
1707 printk(KERN_WARNING "Unexpected merge points\n");
1708 ret = -EINVAL;
1709 }
1710 }
1711 kfree(mp_table);
1712 return ret;
1713}
This page took 0.119187 seconds and 4 git commands to generate.