Filter: implement bitwise lshift, rshift, not
[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:
97b58163
MD
313 {
314 ERR("unsupported bytecode op %u\n",
315 (unsigned int) *(filter_opcode_t *) pc);
316 ret = -EINVAL;
317 break;
318 }
319
320 case FILTER_OP_EQ:
321 case FILTER_OP_NE:
322 case FILTER_OP_GT:
323 case FILTER_OP_LT:
324 case FILTER_OP_GE:
325 case FILTER_OP_LE:
326 case FILTER_OP_EQ_STRING:
327 case FILTER_OP_NE_STRING:
328 case FILTER_OP_GT_STRING:
329 case FILTER_OP_LT_STRING:
330 case FILTER_OP_GE_STRING:
331 case FILTER_OP_LE_STRING:
3151a51d
PP
332 case FILTER_OP_EQ_STAR_GLOB_STRING:
333 case FILTER_OP_NE_STAR_GLOB_STRING:
97b58163
MD
334 case FILTER_OP_EQ_S64:
335 case FILTER_OP_NE_S64:
336 case FILTER_OP_GT_S64:
337 case FILTER_OP_LT_S64:
338 case FILTER_OP_GE_S64:
339 case FILTER_OP_LE_S64:
340 case FILTER_OP_EQ_DOUBLE:
341 case FILTER_OP_NE_DOUBLE:
342 case FILTER_OP_GT_DOUBLE:
343 case FILTER_OP_LT_DOUBLE:
344 case FILTER_OP_GE_DOUBLE:
345 case FILTER_OP_LE_DOUBLE:
dbea82ec
MD
346 case FILTER_OP_EQ_DOUBLE_S64:
347 case FILTER_OP_NE_DOUBLE_S64:
348 case FILTER_OP_GT_DOUBLE_S64:
349 case FILTER_OP_LT_DOUBLE_S64:
350 case FILTER_OP_GE_DOUBLE_S64:
351 case FILTER_OP_LE_DOUBLE_S64:
352 case FILTER_OP_EQ_S64_DOUBLE:
353 case FILTER_OP_NE_S64_DOUBLE:
354 case FILTER_OP_GT_S64_DOUBLE:
355 case FILTER_OP_LT_S64_DOUBLE:
356 case FILTER_OP_GE_S64_DOUBLE:
357 case FILTER_OP_LE_S64_DOUBLE:
0039e2d8
MD
358 case FILTER_OP_BIT_RSHIFT:
359 case FILTER_OP_BIT_LSHIFT:
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:
0039e2d8 381 case FILTER_OP_UNARY_BIT_NOT:
97b58163
MD
382 {
383 if (unlikely(pc + sizeof(struct unary_op)
384 > start_pc + bytecode->len)) {
82513dbe 385 ret = -ERANGE;
97b58163
MD
386 }
387 break;
388 }
389
390 /* logical */
391 case FILTER_OP_AND:
392 case FILTER_OP_OR:
393 {
394 if (unlikely(pc + sizeof(struct logical_op)
395 > start_pc + bytecode->len)) {
82513dbe 396 ret = -ERANGE;
97b58163
MD
397 }
398 break;
399 }
400
77aa5901 401 /* load field ref */
97b58163
MD
402 case FILTER_OP_LOAD_FIELD_REF:
403 {
404 ERR("Unknown field ref type\n");
405 ret = -EINVAL;
406 break;
407 }
47e5f13e 408
77aa5901
MD
409 /* get context ref */
410 case FILTER_OP_GET_CONTEXT_REF:
97b58163
MD
411 case FILTER_OP_LOAD_FIELD_REF_STRING:
412 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
413 case FILTER_OP_LOAD_FIELD_REF_S64:
414 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
77aa5901
MD
415 case FILTER_OP_GET_CONTEXT_REF_STRING:
416 case FILTER_OP_GET_CONTEXT_REF_S64:
417 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
97b58163
MD
418 {
419 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct field_ref)
420 > start_pc + bytecode->len)) {
82513dbe 421 ret = -ERANGE;
97b58163
MD
422 }
423 break;
424 }
425
77aa5901 426 /* load from immediate operand */
97b58163 427 case FILTER_OP_LOAD_STRING:
3151a51d 428 case FILTER_OP_LOAD_STAR_GLOB_STRING:
97b58163
MD
429 {
430 struct load_op *insn = (struct load_op *) pc;
431 uint32_t str_len, maxlen;
432
433 if (unlikely(pc + sizeof(struct load_op)
434 > start_pc + bytecode->len)) {
82513dbe 435 ret = -ERANGE;
97b58163
MD
436 break;
437 }
438
439 maxlen = start_pc + bytecode->len - pc - sizeof(struct load_op);
440 str_len = strnlen(insn->data, maxlen);
441 if (unlikely(str_len >= maxlen)) {
442 /* Final '\0' not found within range */
82513dbe 443 ret = -ERANGE;
97b58163
MD
444 }
445 break;
446 }
447
448 case FILTER_OP_LOAD_S64:
449 {
450 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_numeric)
451 > start_pc + bytecode->len)) {
82513dbe 452 ret = -ERANGE;
97b58163
MD
453 }
454 break;
455 }
456
457 case FILTER_OP_LOAD_DOUBLE:
458 {
459 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_double)
460 > start_pc + bytecode->len)) {
82513dbe 461 ret = -ERANGE;
97b58163
MD
462 }
463 break;
464 }
465
466 case FILTER_OP_CAST_TO_S64:
467 case FILTER_OP_CAST_DOUBLE_TO_S64:
468 case FILTER_OP_CAST_NOP:
469 {
470 if (unlikely(pc + sizeof(struct cast_op)
471 > start_pc + bytecode->len)) {
82513dbe 472 ret = -ERANGE;
97b58163
MD
473 }
474 break;
475 }
77aa5901 476
47e5f13e
MD
477 /*
478 * Instructions for recursive traversal through composed types.
479 */
480 case FILTER_OP_GET_CONTEXT_ROOT:
481 case FILTER_OP_GET_APP_CONTEXT_ROOT:
482 case FILTER_OP_GET_PAYLOAD_ROOT:
483 case FILTER_OP_LOAD_FIELD:
484 case FILTER_OP_LOAD_FIELD_S8:
485 case FILTER_OP_LOAD_FIELD_S16:
486 case FILTER_OP_LOAD_FIELD_S32:
487 case FILTER_OP_LOAD_FIELD_S64:
488 case FILTER_OP_LOAD_FIELD_U8:
489 case FILTER_OP_LOAD_FIELD_U16:
490 case FILTER_OP_LOAD_FIELD_U32:
491 case FILTER_OP_LOAD_FIELD_U64:
492 case FILTER_OP_LOAD_FIELD_STRING:
493 case FILTER_OP_LOAD_FIELD_SEQUENCE:
494 case FILTER_OP_LOAD_FIELD_DOUBLE:
495 if (unlikely(pc + sizeof(struct load_op)
496 > start_pc + bytecode->len)) {
497 ret = -ERANGE;
498 }
499 break;
500
501 case FILTER_OP_GET_SYMBOL:
502 {
503 struct load_op *insn = (struct load_op *) pc;
504 struct get_symbol *sym = (struct get_symbol *) insn->data;
505
506 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_symbol)
507 > start_pc + bytecode->len)) {
508 ret = -ERANGE;
509 }
510 ret = validate_get_symbol(bytecode, sym);
511 break;
512 }
513
514 case FILTER_OP_GET_SYMBOL_FIELD:
515 ERR("Unexpected get symbol field");
516 ret = -EINVAL;
517 break;
518
519 case FILTER_OP_GET_INDEX_U16:
520 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_index_u16)
521 > start_pc + bytecode->len)) {
522 ret = -ERANGE;
523 }
524 break;
525
526 case FILTER_OP_GET_INDEX_U64:
527 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_index_u64)
528 > start_pc + bytecode->len)) {
529 ret = -ERANGE;
530 }
531 break;
97b58163
MD
532 }
533
534 return ret;
535}
536
bf956ec0
MD
537static
538unsigned long delete_all_nodes(struct cds_lfht *ht)
97b58163 539{
bf956ec0
MD
540 struct cds_lfht_iter iter;
541 struct lfht_mp_node *node;
542 unsigned long nr_nodes = 0;
97b58163 543
bf956ec0
MD
544 cds_lfht_for_each_entry(ht, &iter, node, node) {
545 int ret;
546
547 ret = cds_lfht_del(ht, cds_lfht_iter_get_node(&iter));
548 assert(!ret);
549 /* note: this hash table is never used concurrently */
550 free(node);
551 nr_nodes++;
97b58163 552 }
bf956ec0
MD
553 return nr_nodes;
554}
97b58163 555
bf956ec0
MD
556/*
557 * Return value:
53569322 558 * >=0: success
bf956ec0
MD
559 * <0: error
560 */
561static
562int validate_instruction_context(struct bytecode_runtime *bytecode,
0305960f 563 struct vstack *stack,
22389ecb
MD
564 char *start_pc,
565 char *pc)
bf956ec0
MD
566{
567 int ret = 0;
3151a51d 568 const filter_opcode_t opcode = *(filter_opcode_t *) pc;
bf956ec0 569
3151a51d 570 switch (opcode) {
bf956ec0
MD
571 case FILTER_OP_UNKNOWN:
572 default:
573 {
574 ERR("unknown bytecode op %u\n",
97b58163 575 (unsigned int) *(filter_opcode_t *) pc);
bf956ec0
MD
576 ret = -EINVAL;
577 goto end;
578 }
579
580 case FILTER_OP_RETURN:
581 {
582 goto end;
583 }
584
585 /* binary */
586 case FILTER_OP_MUL:
587 case FILTER_OP_DIV:
588 case FILTER_OP_MOD:
589 case FILTER_OP_PLUS:
590 case FILTER_OP_MINUS:
bf956ec0
MD
591 {
592 ERR("unsupported bytecode op %u\n",
3151a51d 593 (unsigned int) opcode);
bf956ec0
MD
594 ret = -EINVAL;
595 goto end;
596 }
97b58163 597
bf956ec0
MD
598 case FILTER_OP_EQ:
599 {
3151a51d 600 ret = bin_op_compare_check(stack, opcode, "==");
53569322 601 if (ret < 0)
bf956ec0
MD
602 goto end;
603 break;
604 }
605 case FILTER_OP_NE:
606 {
3151a51d 607 ret = bin_op_compare_check(stack, opcode, "!=");
53569322 608 if (ret < 0)
bf956ec0
MD
609 goto end;
610 break;
611 }
612 case FILTER_OP_GT:
613 {
3151a51d 614 ret = bin_op_compare_check(stack, opcode, ">");
53569322 615 if (ret < 0)
bf956ec0
MD
616 goto end;
617 break;
618 }
619 case FILTER_OP_LT:
620 {
3151a51d 621 ret = bin_op_compare_check(stack, opcode, "<");
53569322 622 if (ret < 0)
bf956ec0
MD
623 goto end;
624 break;
625 }
626 case FILTER_OP_GE:
627 {
3151a51d 628 ret = bin_op_compare_check(stack, opcode, ">=");
53569322 629 if (ret < 0)
bf956ec0
MD
630 goto end;
631 break;
632 }
633 case FILTER_OP_LE:
634 {
3151a51d 635 ret = bin_op_compare_check(stack, opcode, "<=");
53569322 636 if (ret < 0)
97b58163 637 goto end;
bf956ec0
MD
638 break;
639 }
97b58163 640
bf956ec0
MD
641 case FILTER_OP_EQ_STRING:
642 case FILTER_OP_NE_STRING:
643 case FILTER_OP_GT_STRING:
644 case FILTER_OP_LT_STRING:
645 case FILTER_OP_GE_STRING:
646 case FILTER_OP_LE_STRING:
647 {
0305960f
MD
648 if (!vstack_ax(stack) || !vstack_bx(stack)) {
649 ERR("Empty stack\n");
650 ret = -EINVAL;
651 goto end;
652 }
653 if (vstack_ax(stack)->type != REG_STRING
654 || vstack_bx(stack)->type != REG_STRING) {
bf956ec0 655 ERR("Unexpected register type for string comparator\n");
97b58163
MD
656 ret = -EINVAL;
657 goto end;
97b58163 658 }
bf956ec0
MD
659 break;
660 }
97b58163 661
3151a51d
PP
662 case FILTER_OP_EQ_STAR_GLOB_STRING:
663 case FILTER_OP_NE_STAR_GLOB_STRING:
664 {
665 if (!vstack_ax(stack) || !vstack_bx(stack)) {
666 ERR("Empty stack\n");
667 ret = -EINVAL;
668 goto end;
669 }
670 if (vstack_ax(stack)->type != REG_STAR_GLOB_STRING
671 && vstack_bx(stack)->type != REG_STAR_GLOB_STRING) {
672 ERR("Unexpected register type for globbing pattern comparator\n");
673 ret = -EINVAL;
674 goto end;
675 }
676 break;
677 }
678
bf956ec0
MD
679 case FILTER_OP_EQ_S64:
680 case FILTER_OP_NE_S64:
681 case FILTER_OP_GT_S64:
682 case FILTER_OP_LT_S64:
683 case FILTER_OP_GE_S64:
684 case FILTER_OP_LE_S64:
685 {
0305960f
MD
686 if (!vstack_ax(stack) || !vstack_bx(stack)) {
687 ERR("Empty stack\n");
688 ret = -EINVAL;
689 goto end;
690 }
691 if (vstack_ax(stack)->type != REG_S64
692 || vstack_bx(stack)->type != REG_S64) {
bf956ec0
MD
693 ERR("Unexpected register type for s64 comparator\n");
694 ret = -EINVAL;
695 goto end;
97b58163 696 }
bf956ec0
MD
697 break;
698 }
97b58163 699
bf956ec0
MD
700 case FILTER_OP_EQ_DOUBLE:
701 case FILTER_OP_NE_DOUBLE:
702 case FILTER_OP_GT_DOUBLE:
703 case FILTER_OP_LT_DOUBLE:
704 case FILTER_OP_GE_DOUBLE:
705 case FILTER_OP_LE_DOUBLE:
706 {
0305960f
MD
707 if (!vstack_ax(stack) || !vstack_bx(stack)) {
708 ERR("Empty stack\n");
709 ret = -EINVAL;
710 goto end;
711 }
dbea82ec
MD
712 if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_DOUBLE) {
713 ERR("Double operator should have two double registers\n");
bf956ec0
MD
714 ret = -EINVAL;
715 goto end;
97b58163 716 }
dbea82ec
MD
717 break;
718 }
719
720 case FILTER_OP_EQ_DOUBLE_S64:
721 case FILTER_OP_NE_DOUBLE_S64:
722 case FILTER_OP_GT_DOUBLE_S64:
723 case FILTER_OP_LT_DOUBLE_S64:
724 case FILTER_OP_GE_DOUBLE_S64:
725 case FILTER_OP_LE_DOUBLE_S64:
726 {
727 if (!vstack_ax(stack) || !vstack_bx(stack)) {
728 ERR("Empty stack\n");
729 ret = -EINVAL;
730 goto end;
731 }
732 if (vstack_ax(stack)->type != REG_S64 && vstack_bx(stack)->type != REG_DOUBLE) {
733 ERR("Double-S64 operator has unexpected register types\n");
734 ret = -EINVAL;
735 goto end;
736 }
737 break;
738 }
739
740 case FILTER_OP_EQ_S64_DOUBLE:
741 case FILTER_OP_NE_S64_DOUBLE:
742 case FILTER_OP_GT_S64_DOUBLE:
743 case FILTER_OP_LT_S64_DOUBLE:
744 case FILTER_OP_GE_S64_DOUBLE:
745 case FILTER_OP_LE_S64_DOUBLE:
746 {
747 if (!vstack_ax(stack) || !vstack_bx(stack)) {
748 ERR("Empty stack\n");
749 ret = -EINVAL;
750 goto end;
751 }
752 if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_S64) {
753 ERR("S64-Double operator has unexpected register types\n");
bf956ec0
MD
754 ret = -EINVAL;
755 goto end;
97b58163 756 }
bf956ec0
MD
757 break;
758 }
97b58163 759
0039e2d8
MD
760 case FILTER_OP_BIT_RSHIFT:
761 ret = bin_op_bitwise_check(stack, opcode, ">>");
762 if (ret < 0)
763 goto end;
764 break;
765 case FILTER_OP_BIT_LSHIFT:
766 ret = bin_op_bitwise_check(stack, opcode, "<<");
767 if (ret < 0)
768 goto end;
769 break;
47e5f13e
MD
770 case FILTER_OP_BIT_AND:
771 ret = bin_op_bitwise_check(stack, opcode, "&");
772 if (ret < 0)
773 goto end;
774 break;
775 case FILTER_OP_BIT_OR:
776 ret = bin_op_bitwise_check(stack, opcode, "|");
777 if (ret < 0)
778 goto end;
779 break;
780 case FILTER_OP_BIT_XOR:
781 ret = bin_op_bitwise_check(stack, opcode, "^");
782 if (ret < 0)
783 goto end;
784 break;
785
bf956ec0
MD
786 /* unary */
787 case FILTER_OP_UNARY_PLUS:
788 case FILTER_OP_UNARY_MINUS:
789 case FILTER_OP_UNARY_NOT:
790 {
0305960f
MD
791 if (!vstack_ax(stack)) {
792 ERR("Empty stack\n");
bf956ec0
MD
793 ret = -EINVAL;
794 goto end;
795 }
0305960f 796 switch (vstack_ax(stack)->type) {
bf956ec0
MD
797 default:
798 ERR("unknown register type\n");
799 ret = -EINVAL;
800 goto end;
97b58163 801
bf956ec0 802 case REG_STRING:
3151a51d 803 case REG_STAR_GLOB_STRING:
bf956ec0
MD
804 ERR("Unary op can only be applied to numeric or floating point registers\n");
805 ret = -EINVAL;
806 goto end;
807 case REG_S64:
808 break;
809 case REG_DOUBLE:
97b58163 810 break;
53569322
MD
811 case REG_UNKNOWN:
812 break;
97b58163 813 }
bf956ec0
MD
814 break;
815 }
0039e2d8
MD
816 case FILTER_OP_UNARY_BIT_NOT:
817 {
818 if (!vstack_ax(stack)) {
819 ERR("Empty stack\n");
820 ret = -EINVAL;
821 goto end;
822 }
823 switch (vstack_ax(stack)->type) {
824 default:
825 ERR("unknown register type\n");
826 ret = -EINVAL;
827 goto end;
828
829 case REG_STRING:
830 case REG_STAR_GLOB_STRING:
831 case REG_DOUBLE:
832 ERR("Unary bitwise op can only be applied to numeric registers\n");
833 ret = -EINVAL;
834 goto end;
835 case REG_S64:
836 break;
837 case REG_UNKNOWN:
838 break;
839 }
840 break;
841 }
97b58163 842
bf956ec0
MD
843 case FILTER_OP_UNARY_PLUS_S64:
844 case FILTER_OP_UNARY_MINUS_S64:
845 case FILTER_OP_UNARY_NOT_S64:
846 {
0305960f
MD
847 if (!vstack_ax(stack)) {
848 ERR("Empty stack\n");
bf956ec0
MD
849 ret = -EINVAL;
850 goto end;
851 }
0305960f 852 if (vstack_ax(stack)->type != REG_S64) {
bf956ec0
MD
853 ERR("Invalid register type\n");
854 ret = -EINVAL;
855 goto end;
97b58163 856 }
bf956ec0
MD
857 break;
858 }
97b58163 859
bf956ec0
MD
860 case FILTER_OP_UNARY_PLUS_DOUBLE:
861 case FILTER_OP_UNARY_MINUS_DOUBLE:
862 case FILTER_OP_UNARY_NOT_DOUBLE:
863 {
0305960f
MD
864 if (!vstack_ax(stack)) {
865 ERR("Empty stack\n");
bf956ec0
MD
866 ret = -EINVAL;
867 goto end;
97b58163 868 }
0305960f 869 if (vstack_ax(stack)->type != REG_DOUBLE) {
bf956ec0
MD
870 ERR("Invalid register type\n");
871 ret = -EINVAL;
872 goto end;
873 }
874 break;
875 }
97b58163 876
bf956ec0
MD
877 /* logical */
878 case FILTER_OP_AND:
879 case FILTER_OP_OR:
880 {
881 struct logical_op *insn = (struct logical_op *) pc;
97b58163 882
0305960f
MD
883 if (!vstack_ax(stack)) {
884 ERR("Empty stack\n");
885 ret = -EINVAL;
886 goto end;
887 }
53569322
MD
888 if (vstack_ax(stack)->type != REG_S64
889 && vstack_ax(stack)->type != REG_UNKNOWN) {
890 ERR("Logical comparator expects S64 or dynamic register\n");
bf956ec0
MD
891 ret = -EINVAL;
892 goto end;
97b58163
MD
893 }
894
bf956ec0
MD
895 dbg_printf("Validate jumping to bytecode offset %u\n",
896 (unsigned int) insn->skip_offset);
897 if (unlikely(start_pc + insn->skip_offset <= pc)) {
898 ERR("Loops are not allowed in bytecode\n");
97b58163
MD
899 ret = -EINVAL;
900 goto end;
901 }
bf956ec0
MD
902 break;
903 }
97b58163 904
77aa5901 905 /* load field ref */
bf956ec0
MD
906 case FILTER_OP_LOAD_FIELD_REF:
907 {
908 ERR("Unknown field ref type\n");
909 ret = -EINVAL;
910 goto end;
911 }
912 case FILTER_OP_LOAD_FIELD_REF_STRING:
913 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
914 {
915 struct load_op *insn = (struct load_op *) pc;
916 struct field_ref *ref = (struct field_ref *) insn->data;
917
bf956ec0
MD
918 dbg_printf("Validate load field ref offset %u type string\n",
919 ref->offset);
920 break;
921 }
922 case FILTER_OP_LOAD_FIELD_REF_S64:
923 {
924 struct load_op *insn = (struct load_op *) pc;
925 struct field_ref *ref = (struct field_ref *) insn->data;
97b58163 926
bf956ec0
MD
927 dbg_printf("Validate load field ref offset %u type s64\n",
928 ref->offset);
929 break;
930 }
931 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
932 {
933 struct load_op *insn = (struct load_op *) pc;
934 struct field_ref *ref = (struct field_ref *) insn->data;
97b58163 935
bf956ec0
MD
936 dbg_printf("Validate load field ref offset %u type double\n",
937 ref->offset);
938 break;
939 }
97b58163 940
77aa5901 941 /* load from immediate operand */
bf956ec0 942 case FILTER_OP_LOAD_STRING:
3151a51d 943 case FILTER_OP_LOAD_STAR_GLOB_STRING:
bf956ec0 944 {
bf956ec0
MD
945 break;
946 }
97b58163 947
bf956ec0
MD
948 case FILTER_OP_LOAD_S64:
949 {
bf956ec0
MD
950 break;
951 }
97b58163 952
bf956ec0
MD
953 case FILTER_OP_LOAD_DOUBLE:
954 {
bf956ec0
MD
955 break;
956 }
97b58163 957
bf956ec0
MD
958 case FILTER_OP_CAST_TO_S64:
959 case FILTER_OP_CAST_DOUBLE_TO_S64:
960 {
961 struct cast_op *insn = (struct cast_op *) pc;
97b58163 962
0305960f
MD
963 if (!vstack_ax(stack)) {
964 ERR("Empty stack\n");
bf956ec0
MD
965 ret = -EINVAL;
966 goto end;
967 }
0305960f 968 switch (vstack_ax(stack)->type) {
bf956ec0
MD
969 default:
970 ERR("unknown register type\n");
971 ret = -EINVAL;
972 goto end;
97b58163 973
bf956ec0 974 case REG_STRING:
3151a51d 975 case REG_STAR_GLOB_STRING:
bf956ec0
MD
976 ERR("Cast op can only be applied to numeric or floating point registers\n");
977 ret = -EINVAL;
978 goto end;
979 case REG_S64:
980 break;
981 case REG_DOUBLE:
982 break;
53569322
MD
983 case REG_UNKNOWN:
984 break;
bf956ec0
MD
985 }
986 if (insn->op == FILTER_OP_CAST_DOUBLE_TO_S64) {
0305960f 987 if (vstack_ax(stack)->type != REG_DOUBLE) {
bf956ec0 988 ERR("Cast expects double\n");
97b58163
MD
989 ret = -EINVAL;
990 goto end;
97b58163 991 }
97b58163 992 }
bf956ec0
MD
993 break;
994 }
995 case FILTER_OP_CAST_NOP:
996 {
997 break;
998 }
999
77aa5901
MD
1000 /* get context ref */
1001 case FILTER_OP_GET_CONTEXT_REF:
1002 {
53569322
MD
1003 struct load_op *insn = (struct load_op *) pc;
1004 struct field_ref *ref = (struct field_ref *) insn->data;
1005
1006 dbg_printf("Validate get context ref offset %u type dynamic\n",
1007 ref->offset);
1008 break;
77aa5901
MD
1009 }
1010 case FILTER_OP_GET_CONTEXT_REF_STRING:
1011 {
1012 struct load_op *insn = (struct load_op *) pc;
1013 struct field_ref *ref = (struct field_ref *) insn->data;
1014
1015 dbg_printf("Validate get context ref offset %u type string\n",
1016 ref->offset);
1017 break;
1018 }
1019 case FILTER_OP_GET_CONTEXT_REF_S64:
1020 {
1021 struct load_op *insn = (struct load_op *) pc;
1022 struct field_ref *ref = (struct field_ref *) insn->data;
1023
1024 dbg_printf("Validate get context ref offset %u type s64\n",
1025 ref->offset);
1026 break;
1027 }
1028 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
1029 {
1030 struct load_op *insn = (struct load_op *) pc;
1031 struct field_ref *ref = (struct field_ref *) insn->data;
1032
1033 dbg_printf("Validate get context ref offset %u type double\n",
1034 ref->offset);
1035 break;
1036 }
1037
47e5f13e
MD
1038 /*
1039 * Instructions for recursive traversal through composed types.
1040 */
1041 case FILTER_OP_GET_CONTEXT_ROOT:
1042 {
1043 dbg_printf("Validate get context root\n");
1044 break;
1045 }
1046 case FILTER_OP_GET_APP_CONTEXT_ROOT:
1047 {
1048 dbg_printf("Validate get app context root\n");
1049 break;
1050 }
1051 case FILTER_OP_GET_PAYLOAD_ROOT:
1052 {
1053 dbg_printf("Validate get payload root\n");
1054 break;
1055 }
1056 case FILTER_OP_LOAD_FIELD:
1057 {
1058 /*
1059 * We tolerate that field type is unknown at validation,
1060 * because we are performing the load specialization in
1061 * a phase after validation.
1062 */
1063 dbg_printf("Validate load field\n");
1064 break;
1065 }
1066 case FILTER_OP_LOAD_FIELD_S8:
1067 {
1068 dbg_printf("Validate load field s8\n");
1069 break;
1070 }
1071 case FILTER_OP_LOAD_FIELD_S16:
1072 {
1073 dbg_printf("Validate load field s16\n");
1074 break;
1075 }
1076 case FILTER_OP_LOAD_FIELD_S32:
1077 {
1078 dbg_printf("Validate load field s32\n");
1079 break;
1080 }
1081 case FILTER_OP_LOAD_FIELD_S64:
1082 {
1083 dbg_printf("Validate load field s64\n");
1084 break;
1085 }
1086 case FILTER_OP_LOAD_FIELD_U8:
1087 {
1088 dbg_printf("Validate load field u8\n");
1089 break;
1090 }
1091 case FILTER_OP_LOAD_FIELD_U16:
1092 {
1093 dbg_printf("Validate load field u16\n");
1094 break;
1095 }
1096 case FILTER_OP_LOAD_FIELD_U32:
1097 {
1098 dbg_printf("Validate load field u32\n");
1099 break;
1100 }
1101 case FILTER_OP_LOAD_FIELD_U64:
1102 {
1103 dbg_printf("Validate load field u64\n");
1104 break;
1105 }
1106 case FILTER_OP_LOAD_FIELD_STRING:
1107 {
1108 dbg_printf("Validate load field string\n");
1109 break;
1110 }
1111 case FILTER_OP_LOAD_FIELD_SEQUENCE:
1112 {
1113 dbg_printf("Validate load field sequence\n");
1114 break;
1115 }
1116 case FILTER_OP_LOAD_FIELD_DOUBLE:
1117 {
1118 dbg_printf("Validate load field double\n");
1119 break;
1120 }
1121
1122 case FILTER_OP_GET_SYMBOL:
1123 {
1124 struct load_op *insn = (struct load_op *) pc;
1125 struct get_symbol *sym = (struct get_symbol *) insn->data;
1126
1127 dbg_printf("Validate get symbol offset %u\n", sym->offset);
1128 break;
1129 }
1130
1131 case FILTER_OP_GET_SYMBOL_FIELD:
1132 {
1133 struct load_op *insn = (struct load_op *) pc;
1134 struct get_symbol *sym = (struct get_symbol *) insn->data;
1135
1136 dbg_printf("Validate get symbol field offset %u\n", sym->offset);
1137 break;
1138 }
1139
1140 case FILTER_OP_GET_INDEX_U16:
1141 {
1142 struct load_op *insn = (struct load_op *) pc;
1143 struct get_index_u16 *get_index = (struct get_index_u16 *) insn->data;
1144
1145 dbg_printf("Validate get index u16 index %u\n", get_index->index);
1146 break;
1147 }
1148
1149 case FILTER_OP_GET_INDEX_U64:
1150 {
1151 struct load_op *insn = (struct load_op *) pc;
1152 struct get_index_u64 *get_index = (struct get_index_u64 *) insn->data;
1153
1154 dbg_printf("Validate get index u64 index %" PRIu64 "\n", get_index->index);
1155 break;
1156 }
bf956ec0
MD
1157 }
1158end:
1159 return ret;
1160}
1161
1162/*
1163 * Return value:
1164 * 0: success
1165 * <0: error
1166 */
1167static
1168int validate_instruction_all_contexts(struct bytecode_runtime *bytecode,
1169 struct cds_lfht *merge_points,
0305960f 1170 struct vstack *stack,
22389ecb
MD
1171 char *start_pc,
1172 char *pc)
bf956ec0
MD
1173{
1174 int ret;
1175 unsigned long target_pc = pc - start_pc;
1176 struct cds_lfht_iter iter;
1177 struct cds_lfht_node *node;
71c1ceeb 1178 struct lfht_mp_node *mp_node;
bf956ec0
MD
1179 unsigned long hash;
1180
1181 /* Validate the context resulting from the previous instruction */
0305960f 1182 ret = validate_instruction_context(bytecode, stack, start_pc, pc);
53569322 1183 if (ret < 0)
bf956ec0
MD
1184 return ret;
1185
1186 /* Validate merge points */
22389ecb 1187 hash = lttng_hash_mix((const char *) target_pc, sizeof(target_pc),
bf956ec0 1188 lttng_hash_seed);
71c1ceeb 1189 cds_lfht_lookup(merge_points, hash, lttng_hash_match,
22389ecb 1190 (const char *) target_pc, &iter);
71c1ceeb
MD
1191 node = cds_lfht_iter_get_node(&iter);
1192 if (node) {
1193 mp_node = caa_container_of(node, struct lfht_mp_node, node);
3151a51d 1194
bf956ec0
MD
1195 dbg_printf("Filter: validate merge point at offset %lu\n",
1196 target_pc);
71c1ceeb
MD
1197 if (merge_points_compare(stack, &mp_node->stack)) {
1198 ERR("Merge points differ for offset %lu\n",
1199 target_pc);
1200 return -EINVAL;
1201 }
bf956ec0 1202 /* Once validated, we can remove the merge point */
71c1ceeb 1203 dbg_printf("Filter: remove merge point at offset %lu\n",
bf956ec0
MD
1204 target_pc);
1205 ret = cds_lfht_del(merge_points, node);
1206 assert(!ret);
1207 }
1208 return 0;
1209}
1210
1211/*
1212 * Return value:
1213 * >0: going to next insn.
1214 * 0: success, stop iteration.
1215 * <0: error
1216 */
1217static
1218int exec_insn(struct bytecode_runtime *bytecode,
1219 struct cds_lfht *merge_points,
0305960f 1220 struct vstack *stack,
22389ecb
MD
1221 char **_next_pc,
1222 char *pc)
bf956ec0
MD
1223{
1224 int ret = 1;
22389ecb 1225 char *next_pc = *_next_pc;
bf956ec0
MD
1226
1227 switch (*(filter_opcode_t *) pc) {
1228 case FILTER_OP_UNKNOWN:
1229 default:
1230 {
1231 ERR("unknown bytecode op %u\n",
1232 (unsigned int) *(filter_opcode_t *) pc);
1233 ret = -EINVAL;
1234 goto end;
1235 }
1236
1237 case FILTER_OP_RETURN:
1238 {
71c1ceeb
MD
1239 if (!vstack_ax(stack)) {
1240 ERR("Empty stack\n");
1241 ret = -EINVAL;
1242 goto end;
1243 }
47e5f13e
MD
1244 switch (vstack_ax(stack)->type) {
1245 case REG_S64:
1246 case REG_UNKNOWN:
1247 break;
1248 default:
1249 ERR("Unexpected register type %d at end of bytecode\n",
1250 (int) vstack_ax(stack)->type);
1251 ret = -EINVAL;
1252 goto end;
1253 }
1254
bf956ec0
MD
1255 ret = 0;
1256 goto end;
1257 }
1258
1259 /* binary */
1260 case FILTER_OP_MUL:
1261 case FILTER_OP_DIV:
1262 case FILTER_OP_MOD:
1263 case FILTER_OP_PLUS:
1264 case FILTER_OP_MINUS:
bf956ec0
MD
1265 {
1266 ERR("unsupported bytecode op %u\n",
1267 (unsigned int) *(filter_opcode_t *) pc);
1268 ret = -EINVAL;
1269 goto end;
1270 }
1271
1272 case FILTER_OP_EQ:
1273 case FILTER_OP_NE:
1274 case FILTER_OP_GT:
1275 case FILTER_OP_LT:
1276 case FILTER_OP_GE:
1277 case FILTER_OP_LE:
1278 case FILTER_OP_EQ_STRING:
1279 case FILTER_OP_NE_STRING:
1280 case FILTER_OP_GT_STRING:
1281 case FILTER_OP_LT_STRING:
1282 case FILTER_OP_GE_STRING:
1283 case FILTER_OP_LE_STRING:
3151a51d
PP
1284 case FILTER_OP_EQ_STAR_GLOB_STRING:
1285 case FILTER_OP_NE_STAR_GLOB_STRING:
bf956ec0
MD
1286 case FILTER_OP_EQ_S64:
1287 case FILTER_OP_NE_S64:
1288 case FILTER_OP_GT_S64:
1289 case FILTER_OP_LT_S64:
1290 case FILTER_OP_GE_S64:
1291 case FILTER_OP_LE_S64:
bf956ec0
MD
1292 case FILTER_OP_EQ_DOUBLE:
1293 case FILTER_OP_NE_DOUBLE:
1294 case FILTER_OP_GT_DOUBLE:
1295 case FILTER_OP_LT_DOUBLE:
1296 case FILTER_OP_GE_DOUBLE:
1297 case FILTER_OP_LE_DOUBLE:
dbea82ec
MD
1298 case FILTER_OP_EQ_DOUBLE_S64:
1299 case FILTER_OP_NE_DOUBLE_S64:
1300 case FILTER_OP_GT_DOUBLE_S64:
1301 case FILTER_OP_LT_DOUBLE_S64:
1302 case FILTER_OP_GE_DOUBLE_S64:
1303 case FILTER_OP_LE_DOUBLE_S64:
1304 case FILTER_OP_EQ_S64_DOUBLE:
1305 case FILTER_OP_NE_S64_DOUBLE:
1306 case FILTER_OP_GT_S64_DOUBLE:
1307 case FILTER_OP_LT_S64_DOUBLE:
1308 case FILTER_OP_GE_S64_DOUBLE:
1309 case FILTER_OP_LE_S64_DOUBLE:
0039e2d8
MD
1310 case FILTER_OP_BIT_RSHIFT:
1311 case FILTER_OP_BIT_LSHIFT:
47e5f13e
MD
1312 case FILTER_OP_BIT_AND:
1313 case FILTER_OP_BIT_OR:
1314 case FILTER_OP_BIT_XOR:
bf956ec0 1315 {
0305960f
MD
1316 /* Pop 2, push 1 */
1317 if (vstack_pop(stack)) {
1318 ret = -EINVAL;
1319 goto end;
1320 }
1321 if (!vstack_ax(stack)) {
1322 ERR("Empty stack\n");
1323 ret = -EINVAL;
1324 goto end;
1325 }
47e5f13e
MD
1326 switch (vstack_ax(stack)->type) {
1327 case REG_S64:
1328 case REG_DOUBLE:
1329 case REG_STRING:
1330 case REG_STAR_GLOB_STRING:
1331 case REG_UNKNOWN:
1332 break;
1333 default:
1334 ERR("Unexpected register type %d for operation\n",
1335 (int) vstack_ax(stack)->type);
1336 ret = -EINVAL;
1337 goto end;
1338 }
1339
0305960f 1340 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1341 next_pc += sizeof(struct binary_op);
1342 break;
1343 }
1344
1345 /* unary */
1346 case FILTER_OP_UNARY_PLUS:
1347 case FILTER_OP_UNARY_MINUS:
53569322
MD
1348 {
1349 /* Pop 1, push 1 */
1350 if (!vstack_ax(stack)) {
1351 ERR("Empty stack\n");
1352 ret = -EINVAL;
1353 goto end;
1354 }
47e5f13e
MD
1355 switch (vstack_ax(stack)->type) {
1356 case REG_UNKNOWN:
1357 case REG_DOUBLE:
1358 case REG_S64:
1359 break;
1360 default:
1361 ERR("Unexpected register type %d for operation\n",
1362 (int) vstack_ax(stack)->type);
1363 ret = -EINVAL;
1364 goto end;
1365 }
53569322
MD
1366 vstack_ax(stack)->type = REG_UNKNOWN;
1367 next_pc += sizeof(struct unary_op);
1368 break;
1369 }
1370
bf956ec0
MD
1371 case FILTER_OP_UNARY_PLUS_S64:
1372 case FILTER_OP_UNARY_MINUS_S64:
1373 case FILTER_OP_UNARY_NOT_S64:
47e5f13e
MD
1374 {
1375 /* Pop 1, push 1 */
1376 if (!vstack_ax(stack)) {
1377 ERR("Empty stack\n");
1378 ret = -EINVAL;
1379 goto end;
1380 }
1381 switch (vstack_ax(stack)->type) {
1382 case REG_S64:
1383 break;
1384 default:
1385 ERR("Unexpected register type %d for operation\n",
1386 (int) vstack_ax(stack)->type);
1387 ret = -EINVAL;
1388 goto end;
1389 }
1390
1391 vstack_ax(stack)->type = REG_S64;
1392 next_pc += sizeof(struct unary_op);
1393 break;
1394 }
1395
1396 case FILTER_OP_UNARY_NOT:
1397 {
1398 /* Pop 1, push 1 */
1399 if (!vstack_ax(stack)) {
1400 ERR("Empty stack\n");
1401 ret = -EINVAL;
1402 goto end;
1403 }
1404 switch (vstack_ax(stack)->type) {
1405 case REG_UNKNOWN:
1406 case REG_DOUBLE:
1407 case REG_S64:
1408 break;
1409 default:
1410 ERR("Unexpected register type %d for operation\n",
1411 (int) vstack_ax(stack)->type);
1412 ret = -EINVAL;
1413 goto end;
1414 }
1415
1416 vstack_ax(stack)->type = REG_S64;
1417 next_pc += sizeof(struct unary_op);
1418 break;
1419 }
1420
0039e2d8
MD
1421 case FILTER_OP_UNARY_BIT_NOT:
1422 {
1423 /* Pop 1, push 1 */
1424 if (!vstack_ax(stack)) {
1425 ERR("Empty stack\n");
1426 ret = -EINVAL;
1427 goto end;
1428 }
1429 switch (vstack_ax(stack)->type) {
1430 case REG_UNKNOWN:
1431 case REG_S64:
1432 break;
1433 case REG_DOUBLE:
1434 default:
1435 ERR("Unexpected register type %d for operation\n",
1436 (int) vstack_ax(stack)->type);
1437 ret = -EINVAL;
1438 goto end;
1439 }
1440
1441 vstack_ax(stack)->type = REG_S64;
1442 next_pc += sizeof(struct unary_op);
1443 break;
1444 }
1445
53569322 1446 case FILTER_OP_UNARY_NOT_DOUBLE:
bf956ec0 1447 {
0305960f
MD
1448 /* Pop 1, push 1 */
1449 if (!vstack_ax(stack)) {
1450 ERR("Empty stack\n");
1451 ret = -EINVAL;
1452 goto end;
1453 }
47e5f13e
MD
1454 switch (vstack_ax(stack)->type) {
1455 case REG_DOUBLE:
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
0305960f 1464 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1465 next_pc += sizeof(struct unary_op);
1466 break;
1467 }
1468
1469 case FILTER_OP_UNARY_PLUS_DOUBLE:
1470 case FILTER_OP_UNARY_MINUS_DOUBLE:
bf956ec0 1471 {
0305960f
MD
1472 /* Pop 1, push 1 */
1473 if (!vstack_ax(stack)) {
1474 ERR("Empty stack\n");
1475 ret = -EINVAL;
1476 goto end;
1477 }
47e5f13e
MD
1478 switch (vstack_ax(stack)->type) {
1479 case REG_DOUBLE:
1480 break;
1481 default:
1482 ERR("Incorrect register type %d for operation\n",
1483 (int) vstack_ax(stack)->type);
1484 ret = -EINVAL;
1485 goto end;
1486 }
1487
0305960f 1488 vstack_ax(stack)->type = REG_DOUBLE;
bf956ec0
MD
1489 next_pc += sizeof(struct unary_op);
1490 break;
1491 }
1492
1493 /* logical */
1494 case FILTER_OP_AND:
1495 case FILTER_OP_OR:
1496 {
1497 struct logical_op *insn = (struct logical_op *) pc;
1498 int merge_ret;
1499
1500 /* Add merge point to table */
71c1ceeb
MD
1501 merge_ret = merge_point_add_check(merge_points,
1502 insn->skip_offset, stack);
bf956ec0
MD
1503 if (merge_ret) {
1504 ret = merge_ret;
1505 goto end;
97b58163 1506 }
47e5f13e
MD
1507
1508 if (!vstack_ax(stack)) {
1509 ERR("Empty stack\n");
1510 ret = -EINVAL;
1511 goto end;
1512 }
1513 /* There is always a cast-to-s64 operation before a or/and op. */
1514 switch (vstack_ax(stack)->type) {
1515 case REG_S64:
1516 break;
1517 default:
1518 ERR("Incorrect register type %d for operation\n",
1519 (int) vstack_ax(stack)->type);
1520 ret = -EINVAL;
1521 goto end;
1522 }
1523
bf956ec0 1524 /* Continue to next instruction */
71c1ceeb
MD
1525 /* Pop 1 when jump not taken */
1526 if (vstack_pop(stack)) {
1527 ret = -EINVAL;
1528 goto end;
1529 }
bf956ec0
MD
1530 next_pc += sizeof(struct logical_op);
1531 break;
1532 }
1533
77aa5901 1534 /* load field ref */
bf956ec0
MD
1535 case FILTER_OP_LOAD_FIELD_REF:
1536 {
1537 ERR("Unknown field ref type\n");
1538 ret = -EINVAL;
1539 goto end;
1540 }
77aa5901
MD
1541 /* get context ref */
1542 case FILTER_OP_GET_CONTEXT_REF:
1543 {
53569322
MD
1544 if (vstack_push(stack)) {
1545 ret = -EINVAL;
1546 goto end;
1547 }
1548 vstack_ax(stack)->type = REG_UNKNOWN;
1549 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1550 break;
77aa5901 1551 }
bf956ec0
MD
1552 case FILTER_OP_LOAD_FIELD_REF_STRING:
1553 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
77aa5901 1554 case FILTER_OP_GET_CONTEXT_REF_STRING:
bf956ec0 1555 {
0305960f
MD
1556 if (vstack_push(stack)) {
1557 ret = -EINVAL;
1558 goto end;
1559 }
1560 vstack_ax(stack)->type = REG_STRING;
bf956ec0
MD
1561 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1562 break;
1563 }
1564 case FILTER_OP_LOAD_FIELD_REF_S64:
77aa5901 1565 case FILTER_OP_GET_CONTEXT_REF_S64:
bf956ec0 1566 {
0305960f
MD
1567 if (vstack_push(stack)) {
1568 ret = -EINVAL;
1569 goto end;
1570 }
1571 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1572 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1573 break;
1574 }
1575 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
77aa5901 1576 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
bf956ec0 1577 {
0305960f
MD
1578 if (vstack_push(stack)) {
1579 ret = -EINVAL;
1580 goto end;
1581 }
1582 vstack_ax(stack)->type = REG_DOUBLE;
bf956ec0
MD
1583 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1584 break;
1585 }
1586
77aa5901 1587 /* load from immediate operand */
bf956ec0
MD
1588 case FILTER_OP_LOAD_STRING:
1589 {
1590 struct load_op *insn = (struct load_op *) pc;
1591
0305960f
MD
1592 if (vstack_push(stack)) {
1593 ret = -EINVAL;
1594 goto end;
1595 }
1596 vstack_ax(stack)->type = REG_STRING;
bf956ec0
MD
1597 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1598 break;
1599 }
1600
3151a51d
PP
1601 case FILTER_OP_LOAD_STAR_GLOB_STRING:
1602 {
1603 struct load_op *insn = (struct load_op *) pc;
1604
1605 if (vstack_push(stack)) {
1606 ret = -EINVAL;
1607 goto end;
1608 }
1609 vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
1610 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1611 break;
1612 }
1613
bf956ec0
MD
1614 case FILTER_OP_LOAD_S64:
1615 {
0305960f
MD
1616 if (vstack_push(stack)) {
1617 ret = -EINVAL;
1618 goto end;
1619 }
1620 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1621 next_pc += sizeof(struct load_op)
1622 + sizeof(struct literal_numeric);
1623 break;
1624 }
1625
1626 case FILTER_OP_LOAD_DOUBLE:
1627 {
0305960f
MD
1628 if (vstack_push(stack)) {
1629 ret = -EINVAL;
1630 goto end;
1631 }
1632 vstack_ax(stack)->type = REG_DOUBLE;
bf956ec0
MD
1633 next_pc += sizeof(struct load_op)
1634 + sizeof(struct literal_double);
1635 break;
1636 }
1637
1638 case FILTER_OP_CAST_TO_S64:
1639 case FILTER_OP_CAST_DOUBLE_TO_S64:
1640 {
0305960f
MD
1641 /* Pop 1, push 1 */
1642 if (!vstack_ax(stack)) {
1643 ERR("Empty stack\n");
1644 ret = -EINVAL;
1645 goto end;
1646 }
47e5f13e
MD
1647 switch (vstack_ax(stack)->type) {
1648 case REG_S64:
1649 case REG_DOUBLE:
1650 case REG_UNKNOWN:
1651 break;
1652 default:
1653 ERR("Incorrect register type %d for cast\n",
1654 (int) vstack_ax(stack)->type);
1655 ret = -EINVAL;
1656 goto end;
1657 }
0305960f 1658 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1659 next_pc += sizeof(struct cast_op);
1660 break;
1661 }
1662 case FILTER_OP_CAST_NOP:
1663 {
1664 next_pc += sizeof(struct cast_op);
1665 break;
1666 }
97b58163 1667
47e5f13e
MD
1668 /*
1669 * Instructions for recursive traversal through composed types.
1670 */
1671 case FILTER_OP_GET_CONTEXT_ROOT:
1672 case FILTER_OP_GET_APP_CONTEXT_ROOT:
1673 case FILTER_OP_GET_PAYLOAD_ROOT:
1674 {
1675 if (vstack_push(stack)) {
1676 ret = -EINVAL;
1677 goto end;
1678 }
1679 vstack_ax(stack)->type = REG_PTR;
1680 next_pc += sizeof(struct load_op);
1681 break;
1682 }
1683
1684 case FILTER_OP_LOAD_FIELD:
1685 {
1686 /* Pop 1, push 1 */
1687 if (!vstack_ax(stack)) {
1688 ERR("Empty stack\n");
1689 ret = -EINVAL;
1690 goto end;
1691 }
1692 if (vstack_ax(stack)->type != REG_PTR) {
1693 ERR("Expecting pointer on top of stack\n");
1694 ret = -EINVAL;
1695 goto end;
1696 }
1697 vstack_ax(stack)->type = REG_UNKNOWN;
1698 next_pc += sizeof(struct load_op);
1699 break;
1700 }
1701
1702 case FILTER_OP_LOAD_FIELD_S8:
1703 case FILTER_OP_LOAD_FIELD_S16:
1704 case FILTER_OP_LOAD_FIELD_S32:
1705 case FILTER_OP_LOAD_FIELD_S64:
1706 case FILTER_OP_LOAD_FIELD_U8:
1707 case FILTER_OP_LOAD_FIELD_U16:
1708 case FILTER_OP_LOAD_FIELD_U32:
1709 case FILTER_OP_LOAD_FIELD_U64:
1710 {
1711 /* Pop 1, push 1 */
1712 if (!vstack_ax(stack)) {
1713 ERR("Empty stack\n");
1714 ret = -EINVAL;
1715 goto end;
1716 }
1717 if (vstack_ax(stack)->type != REG_PTR) {
1718 ERR("Expecting pointer on top of stack\n");
1719 ret = -EINVAL;
1720 goto end;
1721 }
1722 vstack_ax(stack)->type = REG_S64;
1723 next_pc += sizeof(struct load_op);
1724 break;
1725 }
1726
1727 case FILTER_OP_LOAD_FIELD_STRING:
1728 case FILTER_OP_LOAD_FIELD_SEQUENCE:
1729 {
1730 /* Pop 1, push 1 */
1731 if (!vstack_ax(stack)) {
1732 ERR("Empty stack\n");
1733 ret = -EINVAL;
1734 goto end;
1735 }
1736 if (vstack_ax(stack)->type != REG_PTR) {
1737 ERR("Expecting pointer on top of stack\n");
1738 ret = -EINVAL;
1739 goto end;
1740 }
1741 vstack_ax(stack)->type = REG_STRING;
1742 next_pc += sizeof(struct load_op);
1743 break;
1744 }
1745
1746 case FILTER_OP_LOAD_FIELD_DOUBLE:
1747 {
1748 /* Pop 1, push 1 */
1749 if (!vstack_ax(stack)) {
1750 ERR("Empty stack\n");
1751 ret = -EINVAL;
1752 goto end;
1753 }
1754 if (vstack_ax(stack)->type != REG_PTR) {
1755 ERR("Expecting pointer on top of stack\n");
1756 ret = -EINVAL;
1757 goto end;
1758 }
1759 vstack_ax(stack)->type = REG_DOUBLE;
1760 next_pc += sizeof(struct load_op);
1761 break;
1762 }
1763
1764 case FILTER_OP_GET_SYMBOL:
1765 case FILTER_OP_GET_SYMBOL_FIELD:
1766 {
1767 /* Pop 1, push 1 */
1768 if (!vstack_ax(stack)) {
1769 ERR("Empty stack\n");
1770 ret = -EINVAL;
1771 goto end;
1772 }
1773 if (vstack_ax(stack)->type != REG_PTR) {
1774 ERR("Expecting pointer on top of stack\n");
1775 ret = -EINVAL;
1776 goto end;
1777 }
1778 next_pc += sizeof(struct load_op) + sizeof(struct get_symbol);
1779 break;
1780 }
1781
1782 case FILTER_OP_GET_INDEX_U16:
1783 {
1784 /* Pop 1, push 1 */
1785 if (!vstack_ax(stack)) {
1786 ERR("Empty stack\n");
1787 ret = -EINVAL;
1788 goto end;
1789 }
1790 if (vstack_ax(stack)->type != REG_PTR) {
1791 ERR("Expecting pointer on top of stack\n");
1792 ret = -EINVAL;
1793 goto end;
1794 }
1795 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16);
1796 break;
1797 }
1798
1799 case FILTER_OP_GET_INDEX_U64:
1800 {
1801 /* Pop 1, push 1 */
1802 if (!vstack_ax(stack)) {
1803 ERR("Empty stack\n");
1804 ret = -EINVAL;
1805 goto end;
1806 }
1807 if (vstack_ax(stack)->type != REG_PTR) {
1808 ERR("Expecting pointer on top of stack\n");
1809 ret = -EINVAL;
1810 goto end;
1811 }
1812 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64);
1813 break;
1814 }
1815
bf956ec0
MD
1816 }
1817end:
1818 *_next_pc = next_pc;
1819 return ret;
1820}
1821
1822/*
1823 * Never called concurrently (hash seed is shared).
1824 */
1825int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
1826{
1827 struct cds_lfht *merge_points;
22389ecb 1828 char *pc, *next_pc, *start_pc;
bf956ec0 1829 int ret = -EINVAL;
0305960f 1830 struct vstack stack;
bf956ec0 1831
0305960f 1832 vstack_init(&stack);
bf956ec0
MD
1833
1834 if (!lttng_hash_seed_ready) {
1835 lttng_hash_seed = time(NULL);
1836 lttng_hash_seed_ready = 1;
1837 }
1838 /*
1839 * Note: merge_points hash table used by single thread, and
1840 * never concurrently resized. Therefore, we can use it without
1841 * holding RCU read-side lock and free nodes without using
1842 * call_rcu.
1843 */
1844 merge_points = cds_lfht_new(DEFAULT_NR_MERGE_POINTS,
1845 MIN_NR_BUCKETS, MAX_NR_BUCKETS,
1846 0, NULL);
1847 if (!merge_points) {
1848 ERR("Error allocating hash table for bytecode validation\n");
1849 return -ENOMEM;
1850 }
47e5f13e 1851 start_pc = &bytecode->code[0];
bf956ec0
MD
1852 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1853 pc = next_pc) {
82513dbe
MD
1854 ret = bytecode_validate_overflow(bytecode, start_pc, pc);
1855 if (ret != 0) {
1856 if (ret == -ERANGE)
1857 ERR("filter bytecode overflow\n");
bf956ec0 1858 goto end;
97b58163 1859 }
bf956ec0
MD
1860 dbg_printf("Validating op %s (%u)\n",
1861 print_op((unsigned int) *(filter_opcode_t *) pc),
1862 (unsigned int) *(filter_opcode_t *) pc);
1863
1864 /*
1865 * For each instruction, validate the current context
1866 * (traversal of entire execution flow), and validate
53569322 1867 * all merge points targeting this instruction.
bf956ec0
MD
1868 */
1869 ret = validate_instruction_all_contexts(bytecode, merge_points,
0305960f 1870 &stack, start_pc, pc);
bf956ec0
MD
1871 if (ret)
1872 goto end;
0305960f 1873 ret = exec_insn(bytecode, merge_points, &stack, &next_pc, pc);
bf956ec0
MD
1874 if (ret <= 0)
1875 goto end;
97b58163
MD
1876 }
1877end:
bf956ec0
MD
1878 if (delete_all_nodes(merge_points)) {
1879 if (!ret) {
1880 ERR("Unexpected merge points\n");
1881 ret = -EINVAL;
1882 }
1883 }
1884 if (cds_lfht_destroy(merge_points, NULL)) {
1885 ERR("Error destroying hash table\n");
1886 }
97b58163
MD
1887 return ret;
1888}
This page took 0.10943 seconds and 4 git commands to generate.