Browse code

libclamav: fix handling of signature offsets in cli_scanbuff() (bb#1546)

git-svn: trunk@5026

Tomasz Kojm authored on 2009/04/07 05:01:09
Showing 6 changed files
... ...
@@ -1,3 +1,8 @@
1
+Mon Apr  6 21:58:45 CEST 2009 (tk)
2
+----------------------------------
3
+ * libclamav: fix handling of signature offsets in cli_scanbuff() (bb#1546)
4
+	      Reported by Christoph
5
+
1 6
 Mon Apr  6 12:32:44 EEST 2009 (edwin)
2 7
 -------------------------------------
3 8
  * docs/man/clamd.conf.5.in, etc/clamd.conf, shared/optparser.c: fix
... ...
@@ -590,7 +590,7 @@ fileblobAddData(fileblob *fb, const unsigned char *data, size_t len)
590 590
 					*ctx->scanned += (unsigned long)len / CL_COUNT_PRECISION;
591 591
 				fb->bytes_scanned += (unsigned long)len;
592 592
 				
593
-				if((len > 5) && cli_updatelimits(ctx, len)==CL_CLEAN && (cli_scanbuff(data, (unsigned int)len, ctx->virname, ctx->engine, CL_TYPE_BINARY_DATA, NULL) == CL_VIRUS)) {
593
+				if((len > 5) && cli_updatelimits(ctx, len)==CL_CLEAN && (cli_scanbuff(data, (unsigned int)len, 0, ctx->virname, ctx->engine, CL_TYPE_BINARY_DATA, NULL) == CL_VIRUS)) {
594 594
 					cli_dbgmsg("fileblobAddData: found %s\n", *ctx->virname);
595 595
 					fb->isInfected = 1;
596 596
 				}
... ...
@@ -46,7 +46,7 @@
46 46
 #include "default.h"
47 47
 
48 48
 
49
-int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
49
+int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
50 50
 {
51 51
 	int ret = CL_CLEAN;
52 52
 	unsigned int i;
... ...
@@ -76,8 +76,8 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli
76 76
 	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
77 77
 	    return ret;
78 78
 
79
-	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, 0, ftype, -1)) != CL_VIRUS)
80
-	    ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), 0, ftype, -1, NULL, AC_SCAN_VIR, NULL);
79
+	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, ftype, -1)) != CL_VIRUS)
80
+	    ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL);
81 81
 
82 82
 	if(!acdata)
83 83
 	    cli_ac_freedata(&mdata);
... ...
@@ -89,8 +89,8 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli
89 89
     if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
90 90
 	return ret;
91 91
 
92
-    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, 0, ftype, -1)) != CL_VIRUS)
93
-	ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), 0, ftype, -1, NULL, AC_SCAN_VIR, NULL);
92
+    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, ftype, -1)) != CL_VIRUS)
93
+	ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, -1, NULL, AC_SCAN_VIR, NULL);
94 94
 
95 95
     if(!acdata)
96 96
 	cli_ac_freedata(&mdata);
... ...
@@ -108,6 +108,17 @@ off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, cli_f
108 108
 
109 109
     *ret = 0;
110 110
 
111
+    if((pt = strchr(offstr, ',')))
112
+	*maxshift = atoi(++pt);
113
+
114
+    if(isdigit(offstr[0]))
115
+	return atoi(offstr);
116
+
117
+    if(fd == -1) {
118
+	*ret = -1;
119
+	return 0;
120
+    }
121
+
111 122
     if(!strncmp(offstr, "EP", 2) || offstr[0] == 'S') {
112 123
 
113 124
 	if(info->status == -1) {
... ...
@@ -140,13 +151,7 @@ off_t cli_caloff(const char *offstr, struct cli_target_info *info, int fd, cli_f
140 140
 	}
141 141
     }
142 142
 
143
-    if((pt = strchr(offstr, ',')))
144
-	*maxshift = atoi(++pt);
145
-
146
-    if(isdigit(offstr[0])) {
147
-	return atoi(offstr);
148
-
149
-    } else if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
143
+    if(info->status == 1 && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) {
150 144
 
151 145
 	if(offstr[2] == '+')
152 146
 	    return info->exeinfo.ep + atoi(offstr + 3);
... ...
@@ -229,13 +234,11 @@ int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct
229 229
 	unsigned int maxshift = 0;
230 230
 
231 231
 
232
-    if(offstr && desc != -1) {
232
+    if(offstr) {
233 233
 	offset = cli_caloff(offstr, info, desc, ftype, &ret, &maxshift);
234 234
 
235
-	if(ret == -1) {
236
-	    cli_dbgmsg("cli_validatesig: Can't calculate offset for signature %s\n", virname);
235
+	if(ret == -1)
237 236
 	    return 0;
238
-	}
239 237
 
240 238
 	if(maxshift) {
241 239
 	    if((fileoff < offset) || (fileoff > offset + (off_t) maxshift)) {
... ...
@@ -123,7 +123,7 @@ struct cli_target_info {
123 123
     int8_t status; /* 0 == not initialised, 1 == initialised OK, -1 == error */
124 124
 };
125 125
 
126
-int cli_scanbuff(const unsigned char *buffer, uint32_t length, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata);
126
+int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata);
127 127
 
128 128
 int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode);
129 129
 
... ...
@@ -1043,7 +1043,7 @@ save_text(cli_ctx *ctx, const char *dir, const char *start, size_t len)
1043 1043
 		 *	in this way. It gets the "filetype" wrong and then
1044 1044
 		 *	doesn't scan correctly
1045 1045
 		 */
1046
-		if(cli_scanbuff((char *)p, len, ctx, CL_TYPE_BINARY_DATA, NULL) == CL_VIRUS) {
1046
+		if(cli_scanbuff((char *)p, len, 0, ctx, CL_TYPE_BINARY_DATA, NULL) == CL_VIRUS) {
1047 1047
 			cli_dbgmsg("save_text: found %s\n", *ctx->virname);
1048 1048
 			return CL_VIRUS;
1049 1049
 		}
... ...
@@ -780,7 +780,7 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U)
780 780
 		    /* cli_dbgmsg("Project content:\n%s", data); */
781 781
 		    if(ctx->scanned)
782 782
 			*ctx->scanned += data_len / CL_COUNT_PRECISION;
783
-		    if(cli_scanbuff(data, data_len, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
783
+		    if(cli_scanbuff(data, data_len, 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
784 784
 			free(data);
785 785
 			ret = CL_VIRUS;
786 786
 			break;
... ...
@@ -838,7 +838,7 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U)
838 838
 			cli_dbgmsg("Project content:\n%s", data);
839 839
 			if(ctx->scanned)
840 840
 			    *ctx->scanned += vba_project->length[i] / CL_COUNT_PRECISION;
841
-			if(cli_scanbuff(data, vba_project->length[i], ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
841
+			if(cli_scanbuff(data, vba_project->length[i], 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
842 842
 				free(data);
843 843
 				ret = CL_VIRUS;
844 844
 				break;
... ...
@@ -1012,7 +1012,7 @@ static int cli_scanscript(int desc, cli_ctx *ctx)
1012 1012
 	int ofd = -1, ret;
1013 1013
 	ssize_t nread;
1014 1014
 	const struct cli_matcher *troot = ctx->engine->root[7];
1015
-	uint32_t maxpatlen = troot ? troot->maxpatlen : 0;
1015
+	uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
1016 1016
 	struct cli_matcher *groot = ctx->engine->root[0];
1017 1017
 	struct cli_ac_data gmdata, tmdata;
1018 1018
 	struct cli_ac_data *mdata[2];
... ...
@@ -1068,10 +1068,13 @@ static int cli_scanscript(int desc, cli_ctx *ctx)
1068 1068
 				/* we can continue to scan in memory */
1069 1069
 			}
1070 1070
 			/* when we flush the buffer also scan */
1071
-			if(cli_scanbuff(state.out, state.out_pos, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1071
+			if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1072 1072
 				ret = CL_VIRUS;
1073 1073
 				break;
1074 1074
 			}
1075
+			if(ctx->scanned)
1076
+			    *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
1077
+			offset += state.out_pos;
1075 1078
 			/* carry over maxpatlen from previous buffer */
1076 1079
 			if (state.out_pos > maxpatlen)
1077 1080
 				memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);