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