git-svn: trunk@2004
Tomasz Kojm authored on 2006/06/04 06:57:47... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Sat Jun 3 23:54:51 CEST 2006 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav/matcher.c: add support for new hardware acceleration library |
|
4 |
+ |
|
1 | 5 |
Tue May 30 17:18:15 CEST 2006 (tk) |
2 | 6 |
---------------------------------- |
3 | 7 |
* libclamav/unzip.c: fix alignment problem on SPARC reported by Andy Fiddaman |
... | ... |
@@ -38,6 +38,7 @@ |
38 | 38 |
#include "elf.h" |
39 | 39 |
#include "execs.h" |
40 | 40 |
#include "special.h" |
41 |
+#include "str.h" |
|
41 | 42 |
|
42 | 43 |
static int targettab[CL_TARGET_TABLE_SIZE] = { 0, CL_TYPE_MSEXE, CL_TYPE_MSOLE2, CL_TYPE_HTML, CL_TYPE_MAIL, CL_TYPE_GRAPHICS, CL_TYPE_ELF }; |
43 | 44 |
|
... | ... |
@@ -48,6 +49,7 @@ extern short cli_debug_flag; |
48 | 48 |
#define HWBUFFSIZE 32768 |
49 | 49 |
#endif |
50 | 50 |
|
51 |
+ |
|
51 | 52 |
int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype) |
52 | 53 |
{ |
53 | 54 |
int ret = CL_CLEAN, i, tid = 0, *partcnt; |
... | ... |
@@ -59,6 +61,7 @@ int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, |
59 | 59 |
uint32_t datamask[2] = { 0xffffffff, 0xffffffff }; |
60 | 60 |
int count, hret; |
61 | 61 |
unsigned long long offset; |
62 |
+ char *pt; |
|
62 | 63 |
#endif |
63 | 64 |
|
64 | 65 |
|
... | ... |
@@ -87,7 +90,97 @@ int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, |
87 | 87 |
} |
88 | 88 |
|
89 | 89 |
count = sn_sigscan_resultcount(resulthandle); |
90 |
- cli_dbgmsg("cli_scanbuff: number of results: %d\n", count); |
|
90 |
+ |
|
91 |
+ for(i = 0; i < count; i++) { |
|
92 |
+ const char *matchname = NULL, *offsetstring = NULL, *optionalsigdata = NULL; |
|
93 |
+ int targettype = 0; |
|
94 |
+ |
|
95 |
+ if((hret = sn_sigscan_resultget_name(resulthandle, i, &matchname) < 0)) { |
|
96 |
+ cli_errmsg("cli_scanbuff: sn_sigscan_resultget_name failed for result %d: %d\n", i, hret); |
|
97 |
+ sn_sigscan_resultfree(resulthandle); |
|
98 |
+ return CL_EHWIO; |
|
99 |
+ } |
|
100 |
+ if(!matchname) { |
|
101 |
+ cli_errmsg("cli_scanbuff: HW Result[%d]: Signature without name\n", i); |
|
102 |
+ sn_sigscan_resultfree(resulthandle); |
|
103 |
+ return CL_EMALFDB; |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ if((hret = sn_sigscan_resultget_targettype(resulthandle, i, &targettype) < 0)) { |
|
107 |
+ cli_errmsg("cli_scanbuff: sn_sigscan_resultget_targettype failed for result %d, signature %s: %d\n", i, matchname, hret); |
|
108 |
+ sn_sigscan_resultfree(resulthandle); |
|
109 |
+ return CL_EHWIO; |
|
110 |
+ } |
|
111 |
+ if(targettype && targettab[targettype] != (int) ftype) { |
|
112 |
+ cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Target type: %d, expected: %d\n", i, matchname, targettab[targettype], ftype); |
|
113 |
+ continue; |
|
114 |
+ } |
|
115 |
+ |
|
116 |
+ if((hret = sn_sigscan_resultget_offsetstring(resulthandle, i, &offsetstring) < 0)) { |
|
117 |
+ cli_errmsg("cli_scanbuff: sn_sigscan_resultget_offsetstring failed for result %d, signature %s: %d\n", i, matchname, hret); |
|
118 |
+ sn_sigscan_resultfree(resulthandle); |
|
119 |
+ return CL_EHWIO; |
|
120 |
+ } |
|
121 |
+ if(offsetstring) { |
|
122 |
+ cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Offset based signature not supported in buffer mode\n", i, matchname); |
|
123 |
+ continue; |
|
124 |
+ } |
|
125 |
+ |
|
126 |
+ if((hret = sn_sigscan_resultget_extradata(resulthandle, i, &optionalsigdata) < 0)) { |
|
127 |
+ cli_errmsg("cli_scanbuff: sn_sigscan_resultget_extradata failed for result %d, signature %s: %d\n", i, matchname, hret); |
|
128 |
+ sn_sigscan_resultfree(resulthandle); |
|
129 |
+ return CL_EHWIO; |
|
130 |
+ } |
|
131 |
+ if(optionalsigdata) { |
|
132 |
+ if((pt = cli_strtok(optionalsigdata, 1, ":"))) { /* max version */ |
|
133 |
+ if(!isdigit(*pt)) { |
|
134 |
+ free(pt); |
|
135 |
+ cli_errmsg("cli_scanbuff: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata); |
|
136 |
+ sn_sigscan_resultfree(resulthandle); |
|
137 |
+ return CL_EMALFDB; |
|
138 |
+ } |
|
139 |
+ |
|
140 |
+ if(atoi(pt) < cl_retflevel()) { |
|
141 |
+ cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Signature max flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel()); |
|
142 |
+ free(pt); |
|
143 |
+ continue; |
|
144 |
+ } |
|
145 |
+ |
|
146 |
+ free(pt); |
|
147 |
+ if((pt = cli_strtok(optionalsigdata, 0, ":"))) { /* min version */ |
|
148 |
+ if(!isdigit(*pt)) { |
|
149 |
+ free(pt); |
|
150 |
+ cli_errmsg("cli_scanbuff: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata); |
|
151 |
+ sn_sigscan_resultfree(resulthandle); |
|
152 |
+ return CL_EMALFDB; |
|
153 |
+ } |
|
154 |
+ |
|
155 |
+ if(atoi(pt) > cl_retflevel()) { |
|
156 |
+ cli_dbgmsg("cli_scanbuff: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel()); |
|
157 |
+ free(pt); |
|
158 |
+ continue; |
|
159 |
+ } |
|
160 |
+ free(pt); |
|
161 |
+ } |
|
162 |
+ |
|
163 |
+ } else { |
|
164 |
+ if(!isdigit(*optionalsigdata)) { |
|
165 |
+ cli_errmsg("cli_scanbuff: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata); |
|
166 |
+ sn_sigscan_resultfree(resulthandle); |
|
167 |
+ return CL_EMALFDB; |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ if(atoi(optionalsigdata) > cl_retflevel()) { |
|
171 |
+ cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(optionalsigdata), cl_retflevel()); |
|
172 |
+ continue; |
|
173 |
+ } |
|
174 |
+ } |
|
175 |
+ } |
|
176 |
+ |
|
177 |
+ *virname = matchname; |
|
178 |
+ ret = CL_VIRUS; |
|
179 |
+ break; |
|
180 |
+ } |
|
91 | 181 |
|
92 | 182 |
if(count > 0) { |
93 | 183 |
if((hret = sn_sigscan_resultget(resulthandle, 0, virname, &offset)) < 0) { |
... | ... |
@@ -338,6 +431,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f |
338 | 338 |
unsigned long long hoffset; |
339 | 339 |
uint32_t datamask[2] = { 0xffffffff, 0xffffffff }; |
340 | 340 |
int count, hret; |
341 |
+ off_t origoff; |
|
341 | 342 |
#endif |
342 | 343 |
|
343 | 344 |
|
... | ... |
@@ -359,6 +453,12 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f |
359 | 359 |
return CL_EMEM; |
360 | 360 |
} |
361 | 361 |
|
362 |
+ if((origoff = lseek(desc, 0, SEEK_CUR)) == -1) { |
|
363 |
+ cli_errmsg("cli_scandesc: lseek() failed for descriptor %d\n", desc); |
|
364 |
+ free(buffer); |
|
365 |
+ return CL_EIO; |
|
366 |
+ } |
|
367 |
+ |
|
362 | 368 |
if(ctx->engine->md5_hlist) |
363 | 369 |
MD5_Init(&md5ctx); |
364 | 370 |
|
... | ... |
@@ -384,17 +484,113 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f |
384 | 384 |
} |
385 | 385 |
|
386 | 386 |
count = sn_sigscan_resultcount(resulthandle); |
387 |
- cli_dbgmsg("cli_scandesc: number of results: %d\n", count); |
|
388 | 387 |
|
389 |
- if(count > 0) { |
|
390 |
- if((hret = sn_sigscan_resultget(resulthandle, 0, ctx->virname, &hoffset)) < 0) { |
|
391 |
- cli_errmsg("cli_scandesc: can't get hardware match result: %d\n", hret); |
|
388 |
+ for(i = 0; i < count; i++) { |
|
389 |
+ const char *matchname = NULL, *offsetstring = NULL, *optionalsigdata = NULL; |
|
390 |
+ unsigned long long startoffset = 0; |
|
391 |
+ int targettype = 0; |
|
392 |
+ |
|
393 |
+ if((hret = sn_sigscan_resultget_name(resulthandle, i, &matchname) < 0)) { |
|
394 |
+ cli_errmsg("cli_scandesc: sn_sigscan_resultget_name failed for result %d: %d\n", i, hret); |
|
392 | 395 |
sn_sigscan_resultfree(resulthandle); |
393 | 396 |
return CL_EHWIO; |
394 |
- } else { |
|
395 |
- cli_dbgmsg("cli_scandesc: hardware match %s at %u\n", *ctx->virname, hoffset); |
|
396 |
- ret = CL_VIRUS; |
|
397 | 397 |
} |
398 |
+ |
|
399 |
+ if(!matchname) { |
|
400 |
+ cli_errmsg("cli_scandesc: HW Result[%d]: Signature without name\n", i); |
|
401 |
+ sn_sigscan_resultfree(resulthandle); |
|
402 |
+ return CL_EMALFDB; |
|
403 |
+ } |
|
404 |
+ |
|
405 |
+ if((hret = sn_sigscan_resultget_targettype(resulthandle, i, &targettype) < 0)) { |
|
406 |
+ cli_errmsg("cli_scandesc: sn_sigscan_resultget_targettype failed for result %d, signature %s: %d\n", i, matchname, hret); |
|
407 |
+ sn_sigscan_resultfree(resulthandle); |
|
408 |
+ return CL_EHWIO; |
|
409 |
+ } |
|
410 |
+ if(targettype && targettab[targettype] != (int) ftype) { |
|
411 |
+ cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Target type: %d, expected: %d\n", i, matchname, targettab[targettype], ftype); |
|
412 |
+ continue; |
|
413 |
+ } |
|
414 |
+ |
|
415 |
+ if((hret = sn_sigscan_resultget_offsetstring(resulthandle, i, &offsetstring) < 0)) { |
|
416 |
+ cli_errmsg("cli_scandesc: sn_sigscan_resultget_offsetstring failed for result %d, signature %s: %d\n", i, matchname, hret); |
|
417 |
+ sn_sigscan_resultfree(resulthandle); |
|
418 |
+ return CL_EHWIO; |
|
419 |
+ } |
|
420 |
+ if((hret = sn_sigscan_resultget_startoffset(resulthandle, i, &startoffset) < 0)) { |
|
421 |
+ cli_errmsg("cli_scandesc: sn_sigscan_resultget_startoffset failed for result %d, signature %s: %d\n", i, matchname, hret); |
|
422 |
+ sn_sigscan_resultfree(resulthandle); |
|
423 |
+ return CL_EHWIO; |
|
424 |
+ } |
|
425 |
+ if(offsetstring && strcmp(offsetstring, "*")) { |
|
426 |
+ long int off = cli_caloff(offsetstring, desc, ftype); |
|
427 |
+ |
|
428 |
+ if(off == -1) { |
|
429 |
+ cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Bad offset in signature\n", i, matchname); |
|
430 |
+ sn_sigscan_resultfree(resulthandle); |
|
431 |
+ return CL_EMALFDB; |
|
432 |
+ } |
|
433 |
+ |
|
434 |
+ if(startoffset != (unsigned long long) off) { |
|
435 |
+ cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Virus offset: %Lu, expected: %ld\n", i, matchname, startoffset, off); |
|
436 |
+ continue; |
|
437 |
+ } |
|
438 |
+ } |
|
439 |
+ |
|
440 |
+ if((hret = sn_sigscan_resultget_extradata(resulthandle, i, &optionalsigdata) < 0)) { |
|
441 |
+ cli_errmsg("cli_scandesc: sn_sigscan_resultget_extradata failed for result %d, signature %s: %d\n", i, matchname, hret); |
|
442 |
+ sn_sigscan_resultfree(resulthandle); |
|
443 |
+ return CL_EHWIO; |
|
444 |
+ } |
|
445 |
+ if(optionalsigdata) { |
|
446 |
+ if((pt = cli_strtok(optionalsigdata, 1, ":"))) { /* max version */ |
|
447 |
+ if(!isdigit(*pt)) { |
|
448 |
+ free(pt); |
|
449 |
+ cli_errmsg("cli_scandesc: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata); |
|
450 |
+ sn_sigscan_resultfree(resulthandle); |
|
451 |
+ return CL_EMALFDB; |
|
452 |
+ } |
|
453 |
+ |
|
454 |
+ if(atoi(pt) < cl_retflevel()) { |
|
455 |
+ cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature max flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel()); |
|
456 |
+ free(pt); |
|
457 |
+ continue; |
|
458 |
+ } |
|
459 |
+ |
|
460 |
+ free(pt); |
|
461 |
+ if((pt = cli_strtok(optionalsigdata, 0, ":"))) { /* min version */ |
|
462 |
+ if(!isdigit(*pt)) { |
|
463 |
+ free(pt); |
|
464 |
+ cli_errmsg("cli_scandesc: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata); |
|
465 |
+ sn_sigscan_resultfree(resulthandle); |
|
466 |
+ return CL_EMALFDB; |
|
467 |
+ } |
|
468 |
+ |
|
469 |
+ if(atoi(pt) > cl_retflevel()) { |
|
470 |
+ cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(pt), cl_retflevel()); |
|
471 |
+ free(pt); |
|
472 |
+ continue; |
|
473 |
+ } |
|
474 |
+ free(pt); |
|
475 |
+ } |
|
476 |
+ |
|
477 |
+ } else { |
|
478 |
+ if(!isdigit(*optionalsigdata)) { |
|
479 |
+ cli_errmsg("cli_scandesc: HW Result[%d]: %s: Incorrect optional signature data: %s\n", i, matchname, optionalsigdata); |
|
480 |
+ sn_sigscan_resultfree(resulthandle); |
|
481 |
+ return CL_EMALFDB; |
|
482 |
+ } |
|
483 |
+ |
|
484 |
+ if(atoi(optionalsigdata) > cl_retflevel()) { |
|
485 |
+ cli_dbgmsg("cli_scandesc: HW Result[%d]: %s: Signature required flevel: %d, current: %d\n", i, matchname, atoi(optionalsigdata), cl_retflevel()); |
|
486 |
+ continue; |
|
487 |
+ } |
|
488 |
+ } |
|
489 |
+ } |
|
490 |
+ |
|
491 |
+ *ctx->virname = matchname; |
|
492 |
+ ret = CL_VIRUS; |
|
493 |
+ break; |
|
398 | 494 |
} |
399 | 495 |
|
400 | 496 |
if((hret = sn_sigscan_resultfree(resulthandle)) < 0) { |
... | ... |
@@ -426,7 +622,13 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f |
426 | 426 |
} |
427 | 427 |
} |
428 | 428 |
|
429 |
- return ret; |
|
429 |
+ if(ret == CL_VIRUS || (ftype != CL_TYPE_UNKNOWN_TEXT && ftype != CL_TYPE_UNKNOWN_DATA)) |
|
430 |
+ return ret; |
|
431 |
+ |
|
432 |
+ if((origoff = lseek(desc, origoff, SEEK_SET)) == -1) { |
|
433 |
+ cli_errmsg("cli_scandesc: lseek() failed for descriptor %d\n", desc); |
|
434 |
+ return CL_EIO; |
|
435 |
+ } |
|
430 | 436 |
} |
431 | 437 |
#endif /* HAVE_HWACCEL */ |
432 | 438 |
|
... | ... |
@@ -1381,6 +1381,10 @@ void cl_free(struct cl_engine *engine) |
1381 | 1381 |
struct cli_md5_node *md5pt, *md5h; |
1382 | 1382 |
struct cli_meta_node *metapt, *metah; |
1383 | 1383 |
struct cli_matcher *root; |
1384 |
+#ifdef HAVE_HWACCEL |
|
1385 |
+ int ret; |
|
1386 |
+#endif |
|
1387 |
+ |
|
1384 | 1388 |
|
1385 | 1389 |
if(!engine) { |
1386 | 1390 |
cli_errmsg("cl_free: engine == NULL\n"); |