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