Browse code

pcre: moved cli_pcre_scanbuff from cli_fmap_scandesc to matcher_run matcher: adjusted pcre offset storage and recalculation location various changes to commented developer notes

Kevin Lin authored on 2014/09/19 02:54:57
Showing 2 changed files
... ...
@@ -183,7 +183,7 @@ int cli_pcre_addpatt(struct cli_matcher *root, const char *trigger, const char *
183 183
         return CL_ENULLARG;
184 184
     }
185 185
 
186
-    /* TODO: trigger and regex checking (string length limitations?)(backreference limitations?) */
186
+    /* TODO: trigger and regex checking (backreference limitations?) (control pattern limitations?) */
187 187
     /* cli_ac_chklsig will fail a empty trigger; empty patterns can cause an infinite loop */
188 188
     if (*trigger == '\0' || *pattern == '\0') {
189 189
         cli_errmsg("cli_pcre_addpatt: trigger or pattern cannot be an empty string\n");
... ...
@@ -1,5 +1,7 @@
1 1
 /*
2 2
  *  Copyright (C) 2007-2013 Sourcefire, Inc.
3
+ *  Copyright (C) 2014 Cisco Systems, Inc
4
+ *  All Rights Reserved.
3 5
  *
4 6
  *  Authors: Tomasz Kojm
5 7
  *
... ...
@@ -98,6 +100,7 @@ static inline int matcher_run(const struct cli_matcher *root,
98 98
 			      struct cli_ac_result **acres,
99 99
 			      fmap_t *map,
100 100
 			      struct cli_bm_off *offdata,
101
+			      struct cli_pcre_off *poffdata,
101 102
 			      uint32_t *viroffset,
102 103
 			      cli_ctx *ctx)
103 104
 {
... ...
@@ -108,8 +111,6 @@ static inline int matcher_run(const struct cli_matcher *root,
108 108
     const unsigned char* orig_buffer;
109 109
     unsigned int viruses_found = 0;
110 110
 
111
-    UNUSEDPARAM(map);
112
-
113 111
     if (root->filter) {
114 112
 	if(filter_search_ext(root->filter, buffer, length, &info) == -1) {
115 113
 	    /*  for safety always scan last maxpatlen bytes */
... ...
@@ -161,6 +162,21 @@ static inline int matcher_run(const struct cli_matcher *root,
161 161
     if (ctx && SCAN_ALL && viruses_found)
162 162
 	return CL_VIRUS;
163 163
 
164
+    /* due to logical triggered, pcres cannot be evaluated until after full subsig matching */
165
+    /* cannot save pcre execution state without possible evasion; must scan entire buffer */
166
+    /* however, scanning the whole buffer may require the whole buffer being loaded into memory */
167
+#if HAVE_PCRE
168
+    if (offset+length >= map->len && (buffer = fmap_need_off_once(map, 0, map->len))) {
169
+        cli_dbgmsg("%u+%u(%u) >= %zu: performing regex matching\n", offset, length, offset+length, map->len);
170
+
171
+	/* scan the full buffer */
172
+	ret = cli_pcre_scanbuf(buffer, map->len, root, mdata, acres, poffdata, ctx);
173
+	if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
174
+	    return ret;
175
+	}
176
+    }
177
+#endif /* HAVE_PCRE */
178
+    /* end experimental fragment */
164 179
     return ret;
165 180
 }
166 181
 
... ...
@@ -197,7 +213,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
197 197
 	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
198 198
 	    return ret;
199 199
 
200
-	ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);
200
+	ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, NULL, ctx);
201 201
 
202 202
 	if(!acdata)
203 203
 	    cli_ac_freedata(&mdata);
... ...
@@ -217,7 +233,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
217 217
     if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
218 218
 	return ret;
219 219
 
220
-    ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);
220
+    ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, NULL, ctx);
221 221
 
222 222
     if(!acdata)
223 223
 	cli_ac_freedata(&mdata);
... ...
@@ -725,6 +741,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
725 725
     uint32_t maxpatlen, offset = 0;
726 726
     struct cli_ac_data gdata, tdata;
727 727
     struct cli_bm_off toff;
728
+    struct cli_pcre_off gpoff, tpoff;
728 729
     unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
729 730
     struct cli_matcher *groot = NULL, *troot = NULL;
730 731
     struct cli_target_info info;
... ...
@@ -791,7 +808,8 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
791 791
     cli_targetinfo(&info, i, map);
792 792
 
793 793
     if(!ftonly) {
794
-        if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, &info))) {
794
+        if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, &info)) ||
795
+           (ret = cli_pcre_recaloff(groot, &gpoff, &info, ctx))) {
795 796
             if(info.exeinfo.section)
796 797
                 free(info.exeinfo.section);
797 798
 
... ...
@@ -804,9 +822,12 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
804 804
     }
805 805
 
806 806
     if(troot) {
807
-        if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, &info))) {
808
-            if(!ftonly)
807
+        if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, &info)) ||
808
+           (ret = cli_pcre_recaloff(troot, &tpoff, &info, ctx))) {
809
+            if(!ftonly) {
809 810
                 cli_ac_freedata(&gdata);
811
+                cli_pcre_freeoff(&gpoff);
812
+            }
810 813
             if(info.exeinfo.section)
811 814
                 free(info.exeinfo.section);
812 815
 
... ...
@@ -819,10 +840,13 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
819 819
         if(troot->bm_offmode) {
820 820
             if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
821 821
                 if((ret = cli_bm_initoff(troot, &toff, &info))) {
822
-                    if(!ftonly)
822
+                    if(!ftonly) {
823 823
                         cli_ac_freedata(&gdata);
824
+                        cli_pcre_freeoff(&gpoff);
825
+                    }
824 826
 
825 827
                     cli_ac_freedata(&tdata);
828
+                    cli_pcre_freeoff(&tpoff);
826 829
                     if(info.exeinfo.section)
827 830
                         free(info.exeinfo.section);
828 831
 
... ...
@@ -878,17 +902,20 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
878 878
         if(troot) {
879 879
                 virname = NULL;
880 880
                 viroffset = 0;
881
-                ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx);
881
+                ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &tpoff, &viroffset, ctx);
882 882
 
883 883
             if (virname) {
884 884
                 /* virname already appended by matcher_run */
885 885
                 viruses_found = 1;
886 886
             }
887 887
             if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
888
-                if(!ftonly)
888
+                if(!ftonly) {
889 889
                     cli_ac_freedata(&gdata);
890
+                    cli_pcre_freeoff(&gpoff);
891
+                }
890 892
 
891 893
                 cli_ac_freedata(&tdata);
894
+                cli_pcre_freeoff(&tpoff);
892 895
                 if(bm_offmode)
893 896
                     cli_bm_freeoff(&toff);
894 897
 
... ...
@@ -906,7 +933,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
906 906
         if(!ftonly) {
907 907
             virname = NULL;
908 908
             viroffset = 0;
909
-            ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx);
909
+            ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &gpoff, &viroffset, ctx);
910 910
 
911 911
             if (virname) {
912 912
                 /* virname already appended by matcher_run */
... ...
@@ -914,8 +941,10 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
914 914
             }
915 915
             if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
916 916
                 cli_ac_freedata(&gdata);
917
+                cli_pcre_freeoff(&gpoff);
917 918
                 if(troot) {
918 919
                     cli_ac_freedata(&tdata);
920
+                    cli_pcre_freeoff(&tpoff);
919 921
                     if(bm_offmode)
920 922
                         cli_bm_freeoff(&toff);
921 923
                 }
... ...
@@ -957,102 +986,6 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
957 957
         offset += bytes - maxpatlen;
958 958
     }
959 959
 
960
-    /* lsig '=' op does not work if pcre match occurs after AC matching */
961
-    /* cannot save pcre execution state without possible evasion; must scan entire buffer */
962
-    /* however, scanning the whole buffer may require the whole buffer being loaded into memory */
963
-    /* this should also be part of matcher_run but it cannot as matcher_run is done on partial buffers */
964
-#if HAVE_PCRE
965
-    if((buff = fmap_need_off_once(map, 0, map->len))) {
966
-        if (!ftonly) {
967
-            struct cli_pcre_off poff;
968
-
969
-            /* calculate the relative offsets */
970
-            ret = cli_pcre_recaloff(groot, &poff, &info, ctx);
971
-            if (ret != CL_SUCCESS) {
972
-                cli_ac_freedata(&gdata);
973
-                cli_ac_freedata(&tdata);
974
-                if(bm_offmode)
975
-                    cli_bm_freeoff(&toff);
976
-
977
-                if(info.exeinfo.section)
978
-                    free(info.exeinfo.section);
979
-
980
-                cli_hashset_destroy(&info.exeinfo.vinfo);
981
-                cl_hash_destroy(md5ctx);
982
-                cl_hash_destroy(sha1ctx);
983
-                cl_hash_destroy(sha256ctx);
984
-                return ret;
985
-            }
986
-
987
-            /* scan the full buffer */
988
-            ret = cli_pcre_scanbuf(buff, map->len, groot, &gdata, acres, &poff, ctx);
989
-            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
990
-                cli_ac_freedata(&gdata);
991
-                cli_ac_freedata(&tdata);
992
-                if(bm_offmode)
993
-                    cli_bm_freeoff(&toff);
994
-
995
-                if(info.exeinfo.section)
996
-                    free(info.exeinfo.section);
997
-
998
-                cli_pcre_freeoff(&poff);
999
-
1000
-                cli_hashset_destroy(&info.exeinfo.vinfo);
1001
-                cl_hash_destroy(md5ctx);
1002
-                cl_hash_destroy(sha1ctx);
1003
-                cl_hash_destroy(sha256ctx);
1004
-                return ret;
1005
-            }
1006
-            cli_pcre_freeoff(&poff);
1007
-        }
1008
-        if (troot) {
1009
-            struct cli_pcre_off poff;
1010
-
1011
-            /* calculate the relative offsets */
1012
-            ret = cli_pcre_recaloff(troot, &poff, &info, ctx);
1013
-            if (ret != CL_SUCCESS) {
1014
-                cli_ac_freedata(&gdata);
1015
-                cli_ac_freedata(&tdata);
1016
-                if(bm_offmode)
1017
-                    cli_bm_freeoff(&toff);
1018
-
1019
-                if(info.exeinfo.section)
1020
-                    free(info.exeinfo.section);
1021
-
1022
-                cli_hashset_destroy(&info.exeinfo.vinfo);
1023
-                cl_hash_destroy(md5ctx);
1024
-                cl_hash_destroy(sha1ctx);
1025
-                cl_hash_destroy(sha256ctx);
1026
-                return ret;
1027
-            }
1028
-
1029
-            /* scan the full buffer */
1030
-            ret = cli_pcre_scanbuf(buff, map->len, troot, &tdata, acres, &poff, ctx);
1031
-            if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
1032
-                if(!ftonly)
1033
-                    cli_ac_freedata(&gdata);
1034
-
1035
-                cli_ac_freedata(&tdata);
1036
-                if(bm_offmode)
1037
-                    cli_bm_freeoff(&toff);
1038
-
1039
-                if(info.exeinfo.section)
1040
-                    free(info.exeinfo.section);
1041
-
1042
-                cli_pcre_freeoff(&poff);
1043
-
1044
-                cli_hashset_destroy(&info.exeinfo.vinfo);
1045
-                cl_hash_destroy(md5ctx);
1046
-                cl_hash_destroy(sha1ctx);
1047
-                cl_hash_destroy(sha256ctx);
1048
-                return ret;
1049
-            }
1050
-            cli_pcre_freeoff(&poff);
1051
-        }
1052
-    }
1053
-#endif /* HAVE_PCRE */
1054
-    /* end experimental fragment */
1055
-
1056 960
     if(!ftonly && hdb) {
1057 961
         enum CLI_HASH_TYPE hashtype, hashtype2;
1058 962
 
... ...
@@ -1137,6 +1070,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
1137 1137
             viruses_found++;
1138 1138
 
1139 1139
         cli_ac_freedata(&tdata);
1140
+        cli_pcre_freeoff(&tpoff);
1140 1141
         if(bm_offmode)
1141 1142
             cli_bm_freeoff(&toff);
1142 1143
     }
... ...
@@ -1145,6 +1079,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
1145 1145
         if(ret != CL_VIRUS || SCAN_ALL)
1146 1146
             ret = cli_lsig_eval(ctx, groot, &gdata, &info, (const char *)refhash);
1147 1147
         cli_ac_freedata(&gdata);
1148
+        cli_pcre_freeoff(&gpoff);
1148 1149
     }
1149 1150
 
1150 1151
     if(info.exeinfo.section)