Browse code

add support for new hardware acceleration library

git-svn: trunk@2004

Tomasz Kojm authored on 2006/06/04 06:57:47
Showing 3 changed files
... ...
@@ -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");