... | ... |
@@ -62,6 +62,7 @@ |
62 | 62 |
cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, const char *hexsig, const uint32_t *lsigid, unsigned int options) { |
63 | 63 |
|
64 | 64 |
size_t len = 0; |
65 |
+ uint32_t i = 0; |
|
65 | 66 |
const char *buf_start = NULL; |
66 | 67 |
const char *buf_end = NULL; |
67 | 68 |
char *buf = NULL; |
... | ... |
@@ -72,6 +73,9 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
72 | 72 |
int64_t ret = CL_SUCCESS; |
73 | 73 |
size_t byte_length = 0; |
74 | 74 |
int64_t comp_val = 0; |
75 |
+ char *comp_buf = NULL; |
|
76 |
+ char *comp_start = NULL; |
|
77 |
+ char *comp_end = NULL; |
|
75 | 78 |
char *hexcpy = NULL; |
76 | 79 |
|
77 | 80 |
if (!hexsig || !(*hexsig) || !root || !virname) { |
... | ... |
@@ -289,47 +293,108 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
289 | 289 |
|
290 | 290 |
bcomp->byte_len = byte_length; |
291 | 291 |
|
292 |
- /* currently only >, <, and = are supported comparison symbols--this makes parsing very simple */ |
|
293 |
- buf_start = tokens[2]; |
|
294 |
- switch (*buf_start) { |
|
295 |
- case '<': |
|
296 |
- case '>': |
|
297 |
- case '=': |
|
298 |
- bcomp->comp_symbol = *buf_start; break; |
|
292 |
+ /* we can have up to two comparison eval statements, each sperated by a comma, let's parse them in a separate string */ |
|
293 |
+ comp_buf = cli_strdup(tokens[2]); |
|
294 |
+ if (!comp_buf) { |
|
295 |
+ cli_errmsg("cli_bcomp_addpatt: Unable to allocate memory for comparison buffer\n"); |
|
296 |
+ cli_bcomp_freemeta(root, bcomp); |
|
297 |
+ return CL_EMEM; |
|
298 |
+ } |
|
299 |
+ /* use different buffer start and end markers so we can keep track of what we need to free later */ |
|
300 |
+ buf_start = comp_buf; |
|
301 |
+ comp_start = strchr(comp_buf, ','); |
|
302 |
+ comp_end = strrchr(comp_buf, ','); |
|
299 | 303 |
|
300 |
- default: |
|
301 |
- cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte comparison symbol was invalid (>, <, = are supported operators)\n", tokens[0], tokens[1], tokens[2]); |
|
302 |
- free(buf); |
|
304 |
+ /* check to see if we have exactly one comma, then set our count and tokenize our string apropriately */ |
|
305 |
+ if (comp_start && comp_end) { |
|
306 |
+ if (comp_end == comp_start) { |
|
307 |
+ comp_start[0] = '\0'; |
|
308 |
+ bcomp->comp_count = 2; |
|
309 |
+ |
|
310 |
+ } else { |
|
311 |
+ cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), too many commas found in comparison string\n", tokens[0], tokens[1], tokens[2]); |
|
303 | 312 |
cli_bcomp_freemeta(root, bcomp); |
304 |
- return CL_EMALFDB; |
|
313 |
+ free(buf); |
|
314 |
+ free((void*)buf_start); |
|
315 |
+ return CL_EPARSE; |
|
316 |
+ } |
|
317 |
+ } else { |
|
318 |
+ comp_start = comp_buf; |
|
319 |
+ bcomp->comp_count = 1; |
|
305 | 320 |
} |
306 | 321 |
|
307 |
- |
|
308 |
- /* no more tokens after this, so we take advantage of strtoll and check if the buf_end is null terminated or not */ |
|
309 |
- buf_start++; |
|
310 |
- buf_end = NULL; |
|
311 |
- comp_val = strtoll(buf_start, (char **) &buf_end, 0); |
|
312 |
- if (*buf_end) { |
|
313 |
- cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), comparison value contained invalid input\n", tokens[0], tokens[1], tokens[2]); |
|
322 |
+ /* allocate comp struct list space with the root structure's mempool instance */ |
|
323 |
+ bcomp->comps = (struct cli_bcomp_comp **) mpool_calloc(root->mempool, bcomp->comp_count, sizeof(struct cli_bcomp_comp *)); |
|
324 |
+ if(!bcomp->comps) { |
|
325 |
+ cli_errmsg("cli_bcomp_addpatt: unable to allocate memory for comp struct pointers\n"); |
|
314 | 326 |
free(buf); |
327 |
+ free((void*)buf_start); |
|
315 | 328 |
cli_bcomp_freemeta(root, bcomp); |
316 |
- return CL_EMALFDB; |
|
329 |
+ return CL_EMEM; |
|
317 | 330 |
} |
318 | 331 |
|
319 |
- bcomp->comp_value = comp_val; |
|
332 |
+ /* loop through our new list, allocate, and parse out the needed comparison evaluation bits for this subsig */ |
|
333 |
+ for (i = 0; i < bcomp->comp_count; i++) { |
|
334 |
+ |
|
335 |
+ bcomp->comps[i] = (struct cli_bcomp_comp*) mpool_calloc(root->mempool, 1, sizeof(struct cli_bcomp_comp)); |
|
336 |
+ if(!bcomp->virname) { |
|
337 |
+ cli_errmsg("cli_bcomp_addpatt: unable to allocate memory for comp struct\n"); |
|
338 |
+ free(buf); |
|
339 |
+ free((void*)buf_start); |
|
340 |
+ cli_bcomp_freemeta(root, bcomp); |
|
341 |
+ return CL_EMEM; |
|
342 |
+ } |
|
343 |
+ |
|
344 |
+ /* currently only >, <, and = are supported comparison symbols--this makes parsing very simple */ |
|
345 |
+ switch (*comp_buf) { |
|
346 |
+ case '<': |
|
347 |
+ case '>': |
|
348 |
+ case '=': |
|
349 |
+ bcomp->comps[i]->comp_symbol = *comp_buf; break; |
|
350 |
+ |
|
351 |
+ default: |
|
352 |
+ cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte comparison symbol was invalid (>, <, = are supported operators) %s\n", tokens[0], tokens[1], tokens[2], comp_buf); |
|
353 |
+ free(buf); |
|
354 |
+ free((void*)buf_start); |
|
355 |
+ cli_bcomp_freemeta(root, bcomp); |
|
356 |
+ return CL_EMALFDB; |
|
357 |
+ } |
|
358 |
+ |
|
359 |
+ /* grab the comparison value itself */ |
|
360 |
+ comp_end = NULL; |
|
361 |
+ comp_buf++; |
|
362 |
+ comp_val = strtoll(comp_buf, (char **) &comp_end, 0); |
|
363 |
+ if (*comp_end) { |
|
364 |
+ cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), comparison value contained invalid input\n", tokens[0], tokens[1], tokens[2]); |
|
365 |
+ free(buf); |
|
366 |
+ free((void*)buf_start); |
|
367 |
+ cli_bcomp_freemeta(root, bcomp); |
|
368 |
+ return CL_EMALFDB; |
|
369 |
+ } |
|
370 |
+ |
|
371 |
+ bcomp->comps[i]->comp_value = comp_val; |
|
372 |
+ |
|
373 |
+ /* a bit of tricksy pointer stuffs which handles all count cases, taking advantage of where strtoll drops endptr */ |
|
374 |
+ if (comp_end == comp_start) { |
|
375 |
+ comp_buf = comp_start; |
|
376 |
+ comp_buf++; |
|
377 |
+ } |
|
320 | 378 |
|
321 |
- /* manually verify successful pattern parsing */ |
|
322 |
- bcm_dbgmsg("Matcher Byte Compare: (%s%ld#%c%c%s%zu#%c%ld)\n", |
|
323 |
- bcomp->offset == 0 ? "" : |
|
324 |
- (bcomp->offset < 0 ? "<<" : ">>"), |
|
325 |
- bcomp->offset, |
|
326 |
- bcomp->options & CLI_BCOMP_HEX ? 'h' : (bcomp->options & CLI_BCOMP_DEC ? 'd' : 'i'), |
|
327 |
- bcomp->options & CLI_BCOMP_LE ? 'l' : 'b', |
|
328 |
- bcomp->options & CLI_BCOMP_EXACT ? "e" : "", |
|
329 |
- bcomp->byte_len, |
|
330 |
- bcomp->comp_symbol, |
|
331 |
- bcomp->comp_value); |
|
379 |
+ /* manually verify successful pattern parsing */ |
|
380 |
+ bcm_dbgmsg("Matcher Byte Compare: (%s%ld#%c%c%s%zu#%c%ld)\n", |
|
381 |
+ bcomp->offset == 0 ? "" : |
|
382 |
+ (bcomp->offset < 0 ? "<<" : ">>"), |
|
383 |
+ bcomp->offset, |
|
384 |
+ bcomp->options & CLI_BCOMP_HEX ? 'h' : (bcomp->options & CLI_BCOMP_DEC ? 'd' : 'i'), |
|
385 |
+ bcomp->options & CLI_BCOMP_LE ? 'l' : 'b', |
|
386 |
+ bcomp->options & CLI_BCOMP_EXACT ? "e" : "", |
|
387 |
+ bcomp->byte_len, |
|
388 |
+ bcomp->comps[i]->comp_symbol, |
|
389 |
+ bcomp->comps[i]->comp_value); |
|
390 |
+ } |
|
332 | 391 |
|
392 |
+ free((void*)buf_start); |
|
393 |
+ buf_start = NULL; |
|
333 | 394 |
/* add byte compare info to the root after reallocation */ |
334 | 395 |
bcomp_count = root->bcomp_metas+1; |
335 | 396 |
|
... | ... |
@@ -468,6 +533,8 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met |
468 | 468 |
|
469 | 469 |
uint32_t byte_len = 0; |
470 | 470 |
uint32_t length = 0; |
471 |
+ uint32_t i = 0; |
|
472 |
+ cl_error_t ret = 0; |
|
471 | 473 |
uint16_t opt = 0; |
472 | 474 |
const unsigned char *buffer = NULL; |
473 | 475 |
unsigned char *conversion_buf = NULL; |
... | ... |
@@ -623,37 +690,51 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met |
623 | 623 |
} |
624 | 624 |
|
625 | 625 |
/* do the actual comparison */ |
626 |
- switch (bm->comp_symbol) { |
|
626 |
+ ret = CL_CLEAN; |
|
627 |
+ for (i = 0; i < bm->comp_count; i++) { |
|
628 |
+ if (bm->comps && bm->comps[i]) { |
|
629 |
+ switch (bm->comps[i]->comp_symbol) { |
|
630 |
+ |
|
631 |
+ case '>': |
|
632 |
+ if (value > bm->comps[i]->comp_value) { |
|
633 |
+ bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) greater than comparison value (%ld)\n", value, bm->comps[i]->comp_value); |
|
634 |
+ ret = CL_VIRUS; |
|
635 |
+ } else { |
|
636 |
+ ret = CL_CLEAN; |
|
637 |
+ } |
|
638 |
+ break; |
|
627 | 639 |
|
628 |
- case '>': |
|
629 |
- if (value > bm->comp_value) { |
|
630 |
- bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) greater than comparison value (%ld)\n", value, bm->comp_value); |
|
631 |
- return CL_VIRUS; |
|
632 |
- } |
|
633 |
- break; |
|
640 |
+ case '<': |
|
641 |
+ if (value < bm->comps[i]->comp_value) { |
|
642 |
+ bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) less than comparison value (%ld)\n", value, bm->comps[i]->comp_value); |
|
643 |
+ ret = CL_VIRUS; |
|
644 |
+ } else { |
|
645 |
+ ret = CL_CLEAN; |
|
646 |
+ } |
|
647 |
+ break; |
|
634 | 648 |
|
635 |
- case '<': |
|
636 |
- if (value < bm->comp_value) { |
|
637 |
- bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) less than comparison value (%ld)\n", value, bm->comp_value); |
|
638 |
- return CL_VIRUS; |
|
639 |
- } |
|
640 |
- break; |
|
649 |
+ case '=': |
|
650 |
+ if (value == bm->comps[i]->comp_value) { |
|
651 |
+ bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) equal to comparison value (%ld)\n", value, bm->comps[i]->comp_value); |
|
652 |
+ ret = CL_VIRUS; |
|
653 |
+ } else { |
|
654 |
+ ret = CL_CLEAN; |
|
655 |
+ } |
|
656 |
+ break; |
|
641 | 657 |
|
642 |
- case '=': |
|
643 |
- if (value == bm->comp_value) { |
|
644 |
- bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) equal to comparison value (%ld)\n", value, bm->comp_value); |
|
645 |
- return CL_VIRUS; |
|
658 |
+ default: |
|
659 |
+ bcm_dbgmsg("cli_bcomp_compare_check: comparison symbol (%c) invalid\n", bm->comps[i]->comp_symbol); |
|
660 |
+ return CL_ENULLARG; |
|
646 | 661 |
} |
647 |
- break; |
|
648 | 662 |
|
649 |
- default: |
|
650 |
- bcm_dbgmsg("cli_bcomp_compare_check: comparison symbol (%c) invalid\n", bm->comp_symbol); |
|
651 |
- return CL_ENULLARG; |
|
663 |
+ if (CL_CLEAN == ret) { |
|
664 |
+ /* comparison was not successful */ |
|
665 |
+ bcm_dbgmsg("cli_bcomp_compare_check: extracted value was not %c %ld\n", bm->comps[i]->comp_symbol, bm->comps[i]->comp_value); |
|
666 |
+ return CL_CLEAN; |
|
667 |
+ } |
|
668 |
+ } |
|
652 | 669 |
} |
653 |
- |
|
654 |
- /* comparison was not successful */ |
|
655 |
- bcm_dbgmsg("cli_bcomp_compare_check: extracted value was not %c %ld\n", bm->comp_symbol, bm->comp_value); |
|
656 |
- return CL_CLEAN; |
|
670 |
+ return ret; |
|
657 | 671 |
} |
658 | 672 |
|
659 | 673 |
/** |
... | ... |
@@ -665,6 +746,8 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met |
665 | 665 |
*/ |
666 | 666 |
void cli_bcomp_freemeta(struct cli_matcher *root, struct cli_bcomp_meta *bm) { |
667 | 667 |
|
668 |
+ int i = 0; |
|
669 |
+ |
|
668 | 670 |
if(!root || !bm) { |
669 | 671 |
return; |
670 | 672 |
} |
... | ... |
@@ -673,7 +756,20 @@ void cli_bcomp_freemeta(struct cli_matcher *root, struct cli_bcomp_meta *bm) { |
673 | 673 |
mpool_free(root->mempool, bm->virname); |
674 | 674 |
bm->virname = NULL; |
675 | 675 |
} |
676 |
- |
|
676 |
+ |
|
677 |
+ /* can never have more than 2 */ |
|
678 |
+ if (bm->comps) { |
|
679 |
+ for (i = 0; i < 2; i++) { |
|
680 |
+ if (bm->comps[i]) { |
|
681 |
+ mpool_free(root->mempool, bm->comps[i]); |
|
682 |
+ bm->comps[i] = NULL; |
|
683 |
+ } |
|
684 |
+ } |
|
685 |
+ |
|
686 |
+ mpool_free(root->mempool, bm->comps); |
|
687 |
+ bm->comps = NULL; |
|
688 |
+ } |
|
689 |
+ |
|
677 | 690 |
mpool_free(root->mempool, bm); |
678 | 691 |
bm = NULL; |
679 | 692 |
|
... | ... |
@@ -45,11 +45,17 @@ |
45 | 45 |
|
46 | 46 |
struct cli_bcomp_meta { |
47 | 47 |
char *virname; |
48 |
- uint16_t ref_subsigid; /* identifies the dependent subsig from which we will do comparisons from */ |
|
48 |
+ uint16_t ref_subsigid; /* identifies the dependent subsig from which we will do comparisons */ |
|
49 | 49 |
uint32_t lsigid[3]; |
50 | 50 |
ssize_t offset; /* offset from the referenced subsig, handled at match-time */ |
51 | 51 |
uint16_t options; /* bitmask */ |
52 | 52 |
size_t byte_len; |
53 |
+ struct cli_bcomp_comp **comps; |
|
54 |
+ uint32_t comp_count; |
|
55 |
+}; |
|
56 |
+ |
|
57 |
+/* each byte compare subsig can perform multiple comparisons on the same extracted byte sequence */ |
|
58 |
+struct cli_bcomp_comp { |
|
53 | 59 |
char comp_symbol; /* <, >, = are supported */ |
54 | 60 |
int64_t comp_value; |
55 | 61 |
}; |