--max-scantime replaces the --timelimit clamscan option that had been experimental.
Default max-scantime set to 2 minutes (120000 milliseconds).
... | ... |
@@ -48,6 +48,21 @@ changes. |
48 | 48 |
release for offline viewing in the `docs/html` directory. |
49 | 49 |
- The new home for the documentation markdown is in our |
50 | 50 |
[ClamAV FAQ Github repository](https://github.com/Cisco-Talos/clamav-faq) |
51 |
+- To remediate future denial of service conditions caused by excessive scan times, |
|
52 |
+ we introduced a scan time limit. |
|
53 |
+ The default value is 2 minutes (120000 milliseconds). |
|
54 |
+ |
|
55 |
+ To customize the time limit: |
|
56 |
+ |
|
57 |
+ - use the `clamscan` `--max-scantime` option |
|
58 |
+ - use the `clamd` `MaxScanTime` config option |
|
59 |
+ |
|
60 |
+ Libclamav users may customize the time limit using the `cl_engine_set_num` |
|
61 |
+ function. For example: |
|
62 |
+ |
|
63 |
+ ```c |
|
64 |
+ cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, time_limit_milliseconds) |
|
65 |
+ ``` |
|
51 | 66 |
|
52 | 67 |
### Other improvements |
53 | 68 |
|
... | ... |
@@ -750,6 +750,19 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi |
750 | 750 |
memset(&options, 0, sizeof(struct cl_scan_options)); |
751 | 751 |
|
752 | 752 |
/* set up limits */ |
753 |
+ if ((opt = optget(opts, "MaxScanTime"))->active) { |
|
754 |
+ if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, opt->numarg))) { |
|
755 |
+ logg("!cl_engine_set_num(CL_ENGINE_MAX_SCANTIME) failed: %s\n", cl_strerror(ret)); |
|
756 |
+ cl_engine_free(engine); |
|
757 |
+ return 1; |
|
758 |
+ } |
|
759 |
+ } |
|
760 |
+ val = cl_engine_get_num(engine, CL_ENGINE_MAX_SCANTIME, NULL); |
|
761 |
+ if (val) |
|
762 |
+ logg("Limits: Global time limit set to %llu milliseconds.\n", val); |
|
763 |
+ else |
|
764 |
+ logg("^Limits: Global time limit protection disabled.\n"); |
|
765 |
+ |
|
753 | 766 |
if ((opt = optget(opts, "MaxScanSize"))->active) { |
754 | 767 |
if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) { |
755 | 768 |
logg("!cl_engine_set_num(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret)); |
... | ... |
@@ -273,6 +273,7 @@ void help(void) |
273 | 273 |
mprintf(" --nocerts Disable authenticode certificate chain verification in PE files\n"); |
274 | 274 |
mprintf(" --dumpcerts Dump authenticode certificate chain in PE files\n"); |
275 | 275 |
mprintf("\n"); |
276 |
+ mprintf(" --max-scantime=#n Scan time longer than this will be skipped and assumed clean\n"); |
|
276 | 277 |
mprintf(" --max-filesize=#n Files larger than this will be skipped and assumed clean\n"); |
277 | 278 |
mprintf(" --max-scansize=#n The maximum amount of data to scan for each container file (**)\n"); |
278 | 279 |
mprintf(" --max-files=#n The maximum number of files to scan for each container file (**)\n"); |
... | ... |
@@ -867,6 +867,24 @@ int scanmanager(const struct optstruct *opts) |
867 | 867 |
|
868 | 868 |
/* set limits */ |
869 | 869 |
|
870 |
+ /* TODO: Remove deprecated option in a future feature release */ |
|
871 |
+ if ((opt = optget(opts, "timelimit"))->active) { |
|
872 |
+ if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, opt->numarg))) { |
|
873 |
+ logg("!cli_engine_set_num(CL_ENGINE_MAX_SCANTIME) failed: %s\n", cl_strerror(ret)); |
|
874 |
+ |
|
875 |
+ cl_engine_free(engine); |
|
876 |
+ return 2; |
|
877 |
+ } |
|
878 |
+ } |
|
879 |
+ if ((opt = optget(opts, "max-scantime"))->active) { |
|
880 |
+ if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, opt->numarg))) { |
|
881 |
+ logg("!cli_engine_set_num(CL_ENGINE_MAX_SCANTIME) failed: %s\n", cl_strerror(ret)); |
|
882 |
+ |
|
883 |
+ cl_engine_free(engine); |
|
884 |
+ return 2; |
|
885 |
+ } |
|
886 |
+ } |
|
887 |
+ |
|
870 | 888 |
if ((opt = optget(opts, "max-scansize"))->active) { |
871 | 889 |
if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) { |
872 | 890 |
logg("!cli_engine_set_num(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret)); |
... | ... |
@@ -988,15 +1006,6 @@ int scanmanager(const struct optstruct *opts) |
988 | 988 |
} |
989 | 989 |
} |
990 | 990 |
|
991 |
- if ((opt = optget(opts, "timelimit"))->active) { |
|
992 |
- if ((ret = cl_engine_set_num(engine, CL_ENGINE_TIME_LIMIT, opt->numarg))) { |
|
993 |
- logg("!cli_engine_set_num(CL_ENGINE_TIME_LIMIT) failed: %s\n", cl_strerror(ret)); |
|
994 |
- |
|
995 |
- cl_engine_free(engine); |
|
996 |
- return 2; |
|
997 |
- } |
|
998 |
- } |
|
999 |
- |
|
1000 | 991 |
if ((opt = optget(opts, "pcre-max-filesize"))->active) { |
1001 | 992 |
if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MAX_FILESIZE, opt->numarg))) { |
1002 | 993 |
logg("!cli_engine_set_num(CL_ENGINE_PCRE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret)); |
... | ... |
@@ -85,7 +85,7 @@ Example |
85 | 85 |
# Default: no |
86 | 86 |
#OfficialDatabaseOnly no |
87 | 87 |
|
88 |
-# The daemon can work in local mode, network mode or both. |
|
88 |
+# The daemon can work in local mode, network mode or both. |
|
89 | 89 |
# Due to security reasons we recommend the local mode. |
90 | 90 |
|
91 | 91 |
# Path to a local socket file the daemon will listen on. |
... | ... |
@@ -231,7 +231,7 @@ Example |
231 | 231 |
#DetectPUA yes |
232 | 232 |
|
233 | 233 |
# Exclude a specific PUA category. This directive can be used multiple times. |
234 |
-# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md for |
|
234 |
+# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md for |
|
235 | 235 |
# the complete list of PUA categories. |
236 | 236 |
# Default: Load all categories (if DetectPUA is activated) |
237 | 237 |
#ExcludePUA NetTool |
... | ... |
@@ -271,9 +271,9 @@ Example |
271 | 271 |
# the end of a scan. If an archive contains both a heuristically detected |
272 | 272 |
# virus/phish, and a real malware, the real malware will be reported |
273 | 273 |
# |
274 |
-# Keep this disabled if you intend to handle "*.Heuristics.*" viruses |
|
274 |
+# Keep this disabled if you intend to handle "*.Heuristics.*" viruses |
|
275 | 275 |
# differently from "real" malware. |
276 |
-# If a non-heuristically-detected virus (signature-based) is found first, |
|
276 |
+# If a non-heuristically-detected virus (signature-based) is found first, |
|
277 | 277 |
# the scan is interrupted immediately, regardless of this config option. |
278 | 278 |
# |
279 | 279 |
# Default: no |
... | ... |
@@ -475,6 +475,16 @@ Example |
475 | 475 |
# The options below protect your system against Denial of Service attacks |
476 | 476 |
# using archive bombs. |
477 | 477 |
|
478 |
+# This option sets the maximum amount of time to a scan may take. |
|
479 |
+# In this version, this field only affects the scan time of ZIP archives. |
|
480 |
+# Value of 0 disables the limit |
|
481 |
+# Note: disabling this limit or setting it too high may result allow scanning |
|
482 |
+# of certain files to lock up the scanning process/threads resulting in a Denial |
|
483 |
+# of Service. |
|
484 |
+# Time is in milliseconds. |
|
485 |
+# Default: 120000 |
|
486 |
+#MaxScanTime 300000 |
|
487 |
+ |
|
478 | 488 |
# This option sets the maximum amount of data to be scanned for each input |
479 | 489 |
# file. |
480 | 490 |
# Archives and other containers are recursively extracted and scanned up to |
... | ... |
@@ -619,13 +629,13 @@ Example |
619 | 619 |
#OnAccessMaxFileSize 10M |
620 | 620 |
|
621 | 621 |
# Max number of scanning threads to allocate to the OnAccess thread pool at startup. |
622 |
-# These threads are the ones responsible for creating a connection with the daemon |
|
623 |
-# and kicking off scanning after an event has been processed. To prevent clamonacc |
|
622 |
+# These threads are the ones responsible for creating a connection with the daemon |
|
623 |
+# and kicking off scanning after an event has been processed. To prevent clamonacc |
|
624 | 624 |
# from consuming all clamd's resources keep this lower than clamd's max threads. |
625 | 625 |
# Default: 5 |
626 | 626 |
#OnAccessMaxThreads 10 |
627 | 627 |
|
628 |
-# Max amount of time (in milliseconds) that the OnAccess client should spend for every |
|
628 |
+# Max amount of time (in milliseconds) that the OnAccess client should spend for every |
|
629 | 629 |
# connect, send, and recieve attempt when communicating with clamd via curl. |
630 | 630 |
# Default: 5000 (5 seconds) |
631 | 631 |
# OnAccessCurlTimeout 10000 |
... | ... |
@@ -652,9 +662,9 @@ Example |
652 | 652 |
# Default: no |
653 | 653 |
#OnAccessPrevention yes |
654 | 654 |
|
655 |
-# When using prevention, if this option is turned on, any errors that occur during |
|
656 |
-# scanning will result in the event attempt being denied. This could potentially |
|
657 |
-# lead to unwanted system behaviour with certain configurations, so the client defaults |
|
655 |
+# When using prevention, if this option is turned on, any errors that occur during |
|
656 |
+# scanning will result in the event attempt being denied. This could potentially |
|
657 |
+# lead to unwanted system behaviour with certain configurations, so the client defaults |
|
658 | 658 |
# this to off and prefers allowing access events in case of scan or connection error. |
659 | 659 |
# Default: no |
660 | 660 |
#OnAccessDenyOnError yes |
... | ... |
@@ -667,9 +677,9 @@ Example |
667 | 667 |
|
668 | 668 |
# Set the mount point to be scanned. The mount point specified, or the mount |
669 | 669 |
# point containing the specified directory will be watched. If any directories |
670 |
-# are specified, this option will preempt (disable and ignore all options related to) |
|
670 |
+# are specified, this option will preempt (disable and ignore all options related to) |
|
671 | 671 |
# the DDD system. This option will result in verdicts only. |
672 |
-# Note that prevention is explicitly disallowed to prevent common, fatal misconfigurations. (e.g. |
|
672 |
+# Note that prevention is explicitly disallowed to prevent common, fatal misconfigurations. (e.g. |
|
673 | 673 |
# watching "/" with prevention on and no exclusions made on vital system directories) |
674 | 674 |
# It can be used multiple times. |
675 | 675 |
# Default: disabled |
... | ... |
@@ -702,14 +712,14 @@ Example |
702 | 702 |
# Default: disabled |
703 | 703 |
#OnAccessExcludeUID -1 |
704 | 704 |
|
705 |
-# This option allows exclusions via user names when using the on-access |
|
705 |
+# This option allows exclusions via user names when using the on-access |
|
706 | 706 |
# scanning client. It can be used multiple times. |
707 | 707 |
# It has the same potential race condition limitations of the OnAccessExcludeUID option. |
708 | 708 |
# Default: disabled |
709 | 709 |
#OnAccessExcludeUname clamav |
710 | 710 |
|
711 |
-# Number of times the OnAccess client will retry a failed scan due to connection problems |
|
712 |
-# (or other issues). |
|
711 |
+# Number of times the OnAccess client will retry a failed scan due to connection problems |
|
712 |
+# (or other issues). |
|
713 | 713 |
# Default: 0 |
714 | 714 |
#OnAccessRetryAttempts 3 |
715 | 715 |
|
... | ... |
@@ -717,7 +727,7 @@ Example |
717 | 717 |
## Bytecode |
718 | 718 |
## |
719 | 719 |
|
720 |
-# With this option enabled ClamAV will load bytecode from the database. |
|
720 |
+# With this option enabled ClamAV will load bytecode from the database. |
|
721 | 721 |
# It is highly recommended you keep this option on, otherwise you'll miss |
722 | 722 |
# detections for many new viruses. |
723 | 723 |
# Default: yes |
... | ... |
@@ -741,7 +751,7 @@ Example |
741 | 741 |
#BytecodeSecurity TrustSigned |
742 | 742 |
|
743 | 743 |
# Set bytecode timeout in milliseconds. |
744 |
-# |
|
744 |
+# |
|
745 | 745 |
# Default: 5000 |
746 | 746 |
# BytecodeTimeout 1000 |
747 | 747 |
|
... | ... |
@@ -300,12 +300,12 @@ enum cl_engine_field { |
300 | 300 |
CL_ENGINE_MAX_PARTITIONS, /* uint32_t */ |
301 | 301 |
CL_ENGINE_MAX_ICONSPE, /* uint32_t */ |
302 | 302 |
CL_ENGINE_MAX_RECHWP3, /* uint32_t */ |
303 |
- CL_ENGINE_TIME_LIMIT, /* uint32_t */ |
|
303 |
+ CL_ENGINE_MAX_SCANTIME, /* uint32_t */ |
|
304 | 304 |
CL_ENGINE_PCRE_MATCH_LIMIT, /* uint64_t */ |
305 | 305 |
CL_ENGINE_PCRE_RECMATCH_LIMIT, /* uint64_t */ |
306 | 306 |
CL_ENGINE_PCRE_MAX_FILESIZE, /* uint64_t */ |
307 | 307 |
CL_ENGINE_DISABLE_PE_CERTS, /* uint32_t */ |
308 |
- CL_ENGINE_PE_DUMPCERTS /* uint32_t */ |
|
308 |
+ CL_ENGINE_PE_DUMPCERTS, /* uint32_t */ |
|
309 | 309 |
}; |
310 | 310 |
|
311 | 311 |
enum bytecode_security { |
... | ... |
@@ -679,6 +679,12 @@ cl_error_t cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const |
679 | 679 |
|
680 | 680 |
/* if the global flag is set, loop through the scanning */ |
681 | 681 |
do { |
682 |
+ if (cli_checktimelimit(ctx) != CL_SUCCESS) { |
|
683 |
+ cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime); |
|
684 |
+ ret = CL_ETIMEOUT; |
|
685 |
+ break; |
|
686 |
+ } |
|
687 |
+ |
|
682 | 688 |
/* reset the match results */ |
683 | 689 |
if ((ret = cli_pcre_results_reset(&p_res, pd)) != CL_SUCCESS) |
684 | 690 |
break; |
... | ... |
@@ -257,7 +257,7 @@ const char *cl_strerror(int clerror) |
257 | 257 |
case CL_EMEM: |
258 | 258 |
return "Can't allocate memory"; |
259 | 259 |
case CL_ETIMEOUT: |
260 |
- return "Time limit reached"; |
|
260 |
+ return "CL_ETIMEOUT: Time limit reached"; |
|
261 | 261 |
/* internal (needed for debug messages) */ |
262 | 262 |
case CL_EMAXREC: |
263 | 263 |
return "CL_EMAXREC"; |
... | ... |
@@ -321,6 +321,7 @@ struct cl_engine *cl_engine_new(void) |
321 | 321 |
} |
322 | 322 |
|
323 | 323 |
/* Setup default limits */ |
324 |
+ new->maxscantime = CLI_DEFAULT_TIMELIMIT; |
|
324 | 325 |
new->maxscansize = CLI_DEFAULT_MAXSCANSIZE; |
325 | 326 |
new->maxfilesize = CLI_DEFAULT_MAXFILESIZE; |
326 | 327 |
new->maxreclevel = CLI_DEFAULT_MAXRECLEVEL; |
... | ... |
@@ -613,8 +614,8 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long |
613 | 613 |
case CL_ENGINE_MAX_RECHWP3: |
614 | 614 |
engine->maxrechwp3 = (uint32_t)num; |
615 | 615 |
break; |
616 |
- case CL_ENGINE_TIME_LIMIT: |
|
617 |
- engine->time_limit = (uint32_t)num; |
|
616 |
+ case CL_ENGINE_MAX_SCANTIME: |
|
617 |
+ engine->maxscantime = (uint32_t)num; |
|
618 | 618 |
break; |
619 | 619 |
case CL_ENGINE_PCRE_MATCH_LIMIT: |
620 | 620 |
engine->pcre_match_limit = (uint64_t)num; |
... | ... |
@@ -714,8 +715,8 @@ long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field |
714 | 714 |
return engine->maxiconspe; |
715 | 715 |
case CL_ENGINE_MAX_RECHWP3: |
716 | 716 |
return engine->maxrechwp3; |
717 |
- case CL_ENGINE_TIME_LIMIT: |
|
718 |
- return engine->time_limit; |
|
717 |
+ case CL_ENGINE_MAX_SCANTIME: |
|
718 |
+ return engine->maxscantime; |
|
719 | 719 |
case CL_ENGINE_PCRE_MATCH_LIMIT: |
720 | 720 |
return engine->pcre_match_limit; |
721 | 721 |
case CL_ENGINE_PCRE_RECMATCH_LIMIT: |
... | ... |
@@ -795,6 +796,7 @@ struct cl_settings *cl_engine_settings_copy(const struct cl_engine *engine) |
795 | 795 |
settings->ac_maxdepth = engine->ac_maxdepth; |
796 | 796 |
settings->tmpdir = engine->tmpdir ? strdup(engine->tmpdir) : NULL; |
797 | 797 |
settings->keeptmp = engine->keeptmp; |
798 |
+ settings->maxscantime = engine->maxscantime; |
|
798 | 799 |
settings->maxscansize = engine->maxscansize; |
799 | 800 |
settings->maxfilesize = engine->maxfilesize; |
800 | 801 |
settings->maxreclevel = engine->maxreclevel; |
... | ... |
@@ -849,6 +851,7 @@ int cl_engine_settings_apply(struct cl_engine *engine, const struct cl_settings |
849 | 849 |
engine->ac_mindepth = settings->ac_mindepth; |
850 | 850 |
engine->ac_maxdepth = settings->ac_maxdepth; |
851 | 851 |
engine->keeptmp = settings->keeptmp; |
852 |
+ engine->maxscantime = settings->maxscantime; |
|
852 | 853 |
engine->maxscansize = settings->maxscansize; |
853 | 854 |
engine->maxfilesize = settings->maxfilesize; |
854 | 855 |
engine->maxreclevel = settings->maxreclevel; |
... | ... |
@@ -937,9 +940,9 @@ void cli_check_blockmax(cli_ctx *ctx, int rc) |
937 | 937 |
} |
938 | 938 |
} |
939 | 939 |
|
940 |
-int cli_checklimits(const char *who, cli_ctx *ctx, unsigned long need1, unsigned long need2, unsigned long need3) |
|
940 |
+cl_error_t cli_checklimits(const char *who, cli_ctx *ctx, unsigned long need1, unsigned long need2, unsigned long need3) |
|
941 | 941 |
{ |
942 |
- int ret = CL_SUCCESS; |
|
942 |
+ cl_error_t ret = CL_SUCCESS; |
|
943 | 943 |
unsigned long needed; |
944 | 944 |
|
945 | 945 |
/* if called without limits, go on, unpack, scan */ |
... | ... |
@@ -948,6 +951,9 @@ int cli_checklimits(const char *who, cli_ctx *ctx, unsigned long need1, unsigned |
948 | 948 |
needed = (need1 > need2) ? need1 : need2; |
949 | 949 |
needed = (needed > need3) ? needed : need3; |
950 | 950 |
|
951 |
+ /* Enforce timelimit */ |
|
952 |
+ ret = cli_checktimelimit(ctx); |
|
953 |
+ |
|
951 | 954 |
/* if we have global scan limits */ |
952 | 955 |
if (needed && ctx->engine->maxscansize) { |
953 | 956 |
/* if the remaining scansize is too small... */ |
... | ... |
@@ -976,9 +982,9 @@ int cli_checklimits(const char *who, cli_ctx *ctx, unsigned long need1, unsigned |
976 | 976 |
return ret; |
977 | 977 |
} |
978 | 978 |
|
979 |
-int cli_updatelimits(cli_ctx *ctx, unsigned long needed) |
|
979 |
+cl_error_t cli_updatelimits(cli_ctx *ctx, unsigned long needed) |
|
980 | 980 |
{ |
981 |
- int ret = cli_checklimits("cli_updatelimits", ctx, needed, 0, 0); |
|
981 |
+ cl_error_t ret = cli_checklimits("cli_updatelimits", ctx, needed, 0, 0); |
|
982 | 982 |
|
983 | 983 |
if (ret != CL_CLEAN) return ret; |
984 | 984 |
ctx->scannedfiles++; |
... | ... |
@@ -988,18 +994,33 @@ int cli_updatelimits(cli_ctx *ctx, unsigned long needed) |
988 | 988 |
return CL_CLEAN; |
989 | 989 |
} |
990 | 990 |
|
991 |
-int cli_checktimelimit(cli_ctx *ctx) |
|
991 |
+/** |
|
992 |
+ * @brief Check if we've exceeded the time limit. |
|
993 |
+ * If ctx is NULL, there can be no timelimit so just return success. |
|
994 |
+ * |
|
995 |
+ * @param ctx The scanning context. |
|
996 |
+ * @return cl_error_t CL_SUCCESS if has not exceeded, CL_ETIMEOUT if has exceeded. |
|
997 |
+ */ |
|
998 |
+cl_error_t cli_checktimelimit(cli_ctx *ctx) |
|
992 | 999 |
{ |
1000 |
+ cl_error_t ret = CL_SUCCESS; |
|
1001 |
+ |
|
1002 |
+ if (NULL == ctx) { |
|
1003 |
+ goto done; |
|
1004 |
+ } |
|
1005 |
+ |
|
993 | 1006 |
if (ctx->time_limit.tv_sec != 0) { |
994 | 1007 |
struct timeval now; |
995 | 1008 |
if (gettimeofday(&now, NULL) == 0) { |
996 |
- if (now.tv_sec < ctx->time_limit.tv_sec) |
|
997 |
- return CL_SUCCESS; |
|
998 |
- if (now.tv_sec > ctx->time_limit.tv_sec || now.tv_usec > ctx->time_limit.tv_usec) |
|
999 |
- return CL_ETIMEOUT; |
|
1009 |
+ if (now.tv_sec > ctx->time_limit.tv_sec) |
|
1010 |
+ ret = CL_ETIMEOUT; |
|
1011 |
+ else if (now.tv_sec == ctx->time_limit.tv_sec && now.tv_usec > ctx->time_limit.tv_usec) |
|
1012 |
+ ret = CL_ETIMEOUT; |
|
1000 | 1013 |
} |
1001 | 1014 |
} |
1002 |
- return CL_SUCCESS; |
|
1015 |
+ |
|
1016 |
+done: |
|
1017 |
+ return ret; |
|
1003 | 1018 |
} |
1004 | 1019 |
|
1005 | 1020 |
/* |
... | ... |
@@ -1103,7 +1124,7 @@ void cli_virus_found_cb(cli_ctx *ctx) |
1103 | 1103 |
ctx->engine->cb_virus_found(fmap_fd(*ctx->fmap), (const char *)*ctx->virname, ctx->cb_ctx); |
1104 | 1104 |
} |
1105 | 1105 |
|
1106 |
-int cli_append_possibly_unwanted(cli_ctx *ctx, const char *virname) |
|
1106 |
+cl_error_t cli_append_possibly_unwanted(cli_ctx *ctx, const char *virname) |
|
1107 | 1107 |
{ |
1108 | 1108 |
if (SCAN_ALLMATCHES) |
1109 | 1109 |
return cli_append_virus(ctx, virname); |
... | ... |
@@ -285,16 +285,17 @@ struct cl_engine { |
285 | 285 |
uint64_t engine_options; |
286 | 286 |
|
287 | 287 |
/* Limits */ |
288 |
+ uint32_t maxscantime; /* Time limit (in milliseconds) */ |
|
288 | 289 |
uint64_t maxscansize; /* during the scanning of archives this size |
289 |
- * will never be exceeded |
|
290 |
- */ |
|
290 |
+ * will never be exceeded |
|
291 |
+ */ |
|
291 | 292 |
uint64_t maxfilesize; /* compressed files will only be decompressed |
292 |
- * and scanned up to this size |
|
293 |
- */ |
|
293 |
+ * and scanned up to this size |
|
294 |
+ */ |
|
294 | 295 |
uint32_t maxreclevel; /* maximum recursion level for archives */ |
295 | 296 |
uint32_t maxfiles; /* maximum number of files to be scanned |
296 |
- * within a single archive |
|
297 |
- */ |
|
297 |
+ * within a single archive |
|
298 |
+ */ |
|
298 | 299 |
/* This is for structured data detection. You can set the minimum |
299 | 300 |
* number of occurrences of an CC# or SSN before the system will |
300 | 301 |
* generate a notification. |
... | ... |
@@ -403,9 +404,6 @@ struct cl_engine { |
403 | 403 |
uint32_t maxiconspe; /* max number of icons to scan for PE */ |
404 | 404 |
uint32_t maxrechwp3; /* max recursive calls for HWP3 parsing */ |
405 | 405 |
|
406 |
- /* millisecond time limit for preclassification scanning */ |
|
407 |
- uint32_t time_limit; |
|
408 |
- |
|
409 | 406 |
/* PCRE matching limitations */ |
410 | 407 |
uint64_t pcre_match_limit; |
411 | 408 |
uint64_t pcre_recmatch_limit; |
... | ... |
@@ -427,6 +425,7 @@ struct cl_settings { |
427 | 427 |
uint32_t ac_maxdepth; |
428 | 428 |
char *tmpdir; |
429 | 429 |
uint32_t keeptmp; |
430 |
+ uint32_t maxscantime; |
|
430 | 431 |
uint64_t maxscansize; |
431 | 432 |
uint64_t maxfilesize; |
432 | 433 |
uint32_t maxreclevel; |
... | ... |
@@ -815,21 +814,20 @@ cl_error_t cli_gentempfd_with_prefix(const char *dir, char *prefix, char **name, |
815 | 815 |
|
816 | 816 |
unsigned int cli_rndnum(unsigned int max); |
817 | 817 |
int cli_filecopy(const char *src, const char *dest); |
818 |
-int cli_mapscan(fmap_t *map, off_t offset, size_t size, cli_ctx *ctx, cli_file_t type); |
|
819 | 818 |
bitset_t *cli_bitset_init(void); |
820 | 819 |
void cli_bitset_free(bitset_t *bs); |
821 | 820 |
int cli_bitset_set(bitset_t *bs, unsigned long bit_offset); |
822 | 821 |
int cli_bitset_test(bitset_t *bs, unsigned long bit_offset); |
823 | 822 |
const char *cli_ctime(const time_t *timep, char *buf, const size_t bufsize); |
824 | 823 |
void cli_check_blockmax(cli_ctx *, int); |
825 |
-int cli_checklimits(const char *, cli_ctx *, unsigned long, unsigned long, unsigned long); |
|
826 |
-int cli_updatelimits(cli_ctx *, unsigned long); |
|
824 |
+cl_error_t cli_checklimits(const char *, cli_ctx *, unsigned long, unsigned long, unsigned long); |
|
825 |
+cl_error_t cli_updatelimits(cli_ctx *, unsigned long); |
|
827 | 826 |
unsigned long cli_getsizelimit(cli_ctx *, unsigned long); |
828 | 827 |
int cli_matchregex(const char *str, const char *regex); |
829 | 828 |
void cli_qsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *)); |
830 | 829 |
void cli_qsort_r(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *, const void *), void *arg); |
831 |
-int cli_checktimelimit(cli_ctx *ctx); |
|
832 |
-int cli_append_possibly_unwanted(cli_ctx *ctx, const char *virname); |
|
830 |
+cl_error_t cli_checktimelimit(cli_ctx *ctx); |
|
831 |
+cl_error_t cli_append_possibly_unwanted(cli_ctx *ctx, const char *virname); |
|
833 | 832 |
|
834 | 833 |
/* symlink behaviour */ |
835 | 834 |
#define CLI_FTW_FOLLOW_FILE_SYMLINK 0x01 |
... | ... |
@@ -601,7 +601,7 @@ done: |
601 | 601 |
|
602 | 602 |
static cl_error_t cli_scanegg(cli_ctx *ctx, size_t sfx_offset) |
603 | 603 |
{ |
604 |
- cl_error_t status = CL_EPARSE; |
|
604 |
+ cl_error_t status = CL_EPARSE; |
|
605 | 605 |
cl_error_t egg_ret = CL_EPARSE; |
606 | 606 |
|
607 | 607 |
char *buffer = NULL; |
... | ... |
@@ -616,7 +616,7 @@ static cl_error_t cli_scanegg(cli_ctx *ctx, size_t sfx_offset) |
616 | 616 |
|
617 | 617 |
void *hArchive = NULL; |
618 | 618 |
|
619 |
- char **comments = NULL; |
|
619 |
+ char **comments = NULL; |
|
620 | 620 |
uint32_t nComments = 0; |
621 | 621 |
|
622 | 622 |
cl_egg_metadata metadata; |
... | ... |
@@ -680,9 +680,9 @@ static cl_error_t cli_scanegg(cli_ctx *ctx, size_t sfx_offset) |
680 | 680 |
* Drop the comment to a temp file, if requested |
681 | 681 |
*/ |
682 | 682 |
if (ctx->engine->keeptmp) { |
683 |
- int comment_fd = -1; |
|
683 |
+ int comment_fd = -1; |
|
684 | 684 |
size_t prefixLen = strlen("comments_") + 5; |
685 |
- char * prefix = (char*)malloc(prefixLen + 1); |
|
685 |
+ char *prefix = (char *)malloc(prefixLen + 1); |
|
686 | 686 |
|
687 | 687 |
snprintf(prefix, prefixLen, "comments_%u", i); |
688 | 688 |
prefix[prefixLen] = '\0'; |
... | ... |
@@ -2448,7 +2448,7 @@ static int cli_scanmail(cli_ctx *ctx) |
2448 | 2448 |
static int cli_scan_structured(cli_ctx *ctx) |
2449 | 2449 |
{ |
2450 | 2450 |
char buf[8192]; |
2451 |
- size_t result = 0; |
|
2451 |
+ size_t result = 0; |
|
2452 | 2452 |
unsigned int cc_count = 0; |
2453 | 2453 |
unsigned int ssn_count = 0; |
2454 | 2454 |
int done = 0; |
... | ... |
@@ -3244,7 +3244,7 @@ static int dispatch_prescan(clcb_pre_scan cb, cli_ctx *ctx, const char *filetype |
3244 | 3244 |
|
3245 | 3245 |
static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3246 | 3246 |
{ |
3247 |
- int ret = CL_CLEAN; |
|
3247 |
+ cl_error_t ret = CL_CLEAN; |
|
3248 | 3248 |
cli_file_t dettype = 0; |
3249 | 3249 |
uint8_t typercg = 1; |
3250 | 3250 |
size_t hashed_size; |
... | ... |
@@ -3567,11 +3567,11 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3567 | 3567 |
break; |
3568 | 3568 |
} else if (ret != CL_SUCCESS) { |
3569 | 3569 |
/* |
3570 |
- * non-critical return => allow for the CL_TYPE_ZIP scan to occur |
|
3571 |
- * cli_process_ooxml other possible returns: |
|
3572 |
- * CL_ETIMEOUT, CL_EMAXSIZE, CL_EMAXFILES, CL_EPARSE, |
|
3573 |
- * CL_EFORMAT, CL_BREAK, CL_ESTAT |
|
3574 |
- */ |
|
3570 |
+ * non-critical return => allow for the CL_TYPE_ZIP scan to occur |
|
3571 |
+ * cli_process_ooxml other possible returns: |
|
3572 |
+ * CL_ETIMEOUT, CL_EMAXSIZE, CL_EMAXFILES, CL_EPARSE, |
|
3573 |
+ * CL_EFORMAT, CL_BREAK, CL_ESTAT |
|
3574 |
+ */ |
|
3575 | 3575 |
ret = CL_SUCCESS; |
3576 | 3576 |
} |
3577 | 3577 |
} |
... | ... |
@@ -3804,8 +3804,8 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3804 | 3804 |
case CL_TYPE_TEXT_ASCII: |
3805 | 3805 |
if (SCAN_HEURISTIC_STRUCTURED && (DCONF_OTHER & OTHER_CONF_DLP)) |
3806 | 3806 |
/* TODO: consider calling this from cli_scanscript() for |
3807 |
- * a normalised text |
|
3808 |
- */ |
|
3807 |
+ * a normalised text |
|
3808 |
+ */ |
|
3809 | 3809 |
|
3810 | 3810 |
ret = cli_scan_structured(ctx); |
3811 | 3811 |
break; |
... | ... |
@@ -3845,7 +3845,6 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3845 | 3845 |
case CL_ETMPFILE: |
3846 | 3846 |
case CL_ETMPDIR: |
3847 | 3847 |
case CL_EMEM: |
3848 |
- case CL_ETIMEOUT: |
|
3849 | 3848 |
cli_dbgmsg("Descriptor[%d]: cli_scanraw error %s\n", fmap_fd(*ctx->fmap), cl_strerror(res)); |
3850 | 3849 |
cli_bitset_free(ctx->hook_lsig_matches); |
3851 | 3850 |
ctx->hook_lsig_matches = old_hook_lsig_matches; |
... | ... |
@@ -3866,7 +3865,15 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3866 | 3866 |
cli_bitset_free(ctx->hook_lsig_matches); |
3867 | 3867 |
ctx->hook_lsig_matches = old_hook_lsig_matches; |
3868 | 3868 |
return magic_scandesc_cleanup(ctx, type, hash, hashed_size, cache_clean, ret, parent_property); |
3869 |
- /* "MAX" conditions should still fully scan the current file */ |
|
3869 |
+ /* The CL_ETIMEOUT "MAX" condition should set exceeds max flag and exit out quietly. */ |
|
3870 |
+ case CL_ETIMEOUT: |
|
3871 |
+ cli_check_blockmax(ctx, ret); |
|
3872 |
+ cli_bitset_free(ctx->hook_lsig_matches); |
|
3873 |
+ ctx->hook_lsig_matches = old_hook_lsig_matches; |
|
3874 |
+ cli_dbgmsg("Descriptor[%d]: Stopping after cli_scanraw reached %s\n", |
|
3875 |
+ fmap_fd(*ctx->fmap), cl_strerror(res)); |
|
3876 |
+ return magic_scandesc_cleanup(ctx, type, hash, hashed_size, cache_clean, CL_CLEAN, parent_property); |
|
3877 |
+ /* All other "MAX" conditions should still fully scan the current file */ |
|
3870 | 3878 |
case CL_EMAXREC: |
3871 | 3879 |
case CL_EMAXSIZE: |
3872 | 3880 |
case CL_EMAXFILES: |
... | ... |
@@ -3875,9 +3882,9 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3875 | 3875 |
fmap_fd(*ctx->fmap), cl_strerror(res)); |
3876 | 3876 |
break; |
3877 | 3877 |
/* Other errors must not block further scans below |
3878 |
- * This specifically includes CL_EFORMAT & CL_EREAD & CL_EUNPACK |
|
3879 |
- * Malformed/truncated files could report as any of these three. |
|
3880 |
- */ |
|
3878 |
+ * This specifically includes CL_EFORMAT & CL_EREAD & CL_EUNPACK |
|
3879 |
+ * Malformed/truncated files could report as any of these three. |
|
3880 |
+ */ |
|
3881 | 3881 |
default: |
3882 | 3882 |
ret = res; |
3883 | 3883 |
cli_dbgmsg("Descriptor[%d]: Continuing after cli_scanraw error %s\n", |
... | ... |
@@ -3889,7 +3896,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3889 | 3889 |
ctx->recursion++; |
3890 | 3890 |
switch (type) { |
3891 | 3891 |
/* bytecode hooks triggered by a lsig must be a hook |
3892 |
- * called from one of the functions here */ |
|
3892 |
+ * called from one of the functions here */ |
|
3893 | 3893 |
case CL_TYPE_TEXT_ASCII: |
3894 | 3894 |
case CL_TYPE_TEXT_UTF16BE: |
3895 | 3895 |
case CL_TYPE_TEXT_UTF16LE: |
... | ... |
@@ -3903,8 +3910,8 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3903 | 3903 |
perf_nested_stop(ctx, PERFT_SCRIPT, PERFT_SCAN); |
3904 | 3904 |
break; |
3905 | 3905 |
/* Due to performance reasons all executables were first scanned |
3906 |
- * in raw mode. Now we will try to unpack them |
|
3907 |
- */ |
|
3906 |
+ * in raw mode. Now we will try to unpack them |
|
3907 |
+ */ |
|
3908 | 3908 |
case CL_TYPE_MSEXE: |
3909 | 3909 |
perf_nested_start(ctx, PERFT_PE, PERFT_SCAN); |
3910 | 3910 |
if (SCAN_PARSE_PE && ctx->dconf->pe) { |
... | ... |
@@ -3937,14 +3944,16 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3937 | 3937 |
ctx->hook_lsig_matches = old_hook_lsig_matches; |
3938 | 3938 |
|
3939 | 3939 |
switch (ret) { |
3940 |
- /* Malformed file cases */ |
|
3941 |
- case CL_EFORMAT: |
|
3942 |
- case CL_EREAD: |
|
3943 |
- case CL_EUNPACK: |
|
3944 | 3940 |
/* Limits exceeded */ |
3941 |
+ case CL_ETIMEOUT: |
|
3945 | 3942 |
case CL_EMAXREC: |
3946 | 3943 |
case CL_EMAXSIZE: |
3947 | 3944 |
case CL_EMAXFILES: |
3945 |
+ cli_check_blockmax(ctx, ret); |
|
3946 |
+ /* Malformed file cases */ |
|
3947 |
+ case CL_EFORMAT: |
|
3948 |
+ case CL_EREAD: |
|
3949 |
+ case CL_EUNPACK: |
|
3948 | 3950 |
cli_dbgmsg("Descriptor[%d]: %s\n", fmap_fd(*ctx->fmap), cl_strerror(ret)); |
3949 | 3951 |
#if HAVE_JSON |
3950 | 3952 |
ctx->wrkproperty = parent_property; |
... | ... |
@@ -4233,10 +4242,10 @@ static cl_error_t scan_common(int desc, cl_fmap_t *map, const char *filepath, co |
4233 | 4233 |
} |
4234 | 4234 |
perf_init(&ctx); |
4235 | 4235 |
|
4236 |
- if (ctx.options->general & CL_SCAN_GENERAL_COLLECT_METADATA && ctx.engine->time_limit != 0) { |
|
4236 |
+ if (ctx.engine->maxscantime != 0) { |
|
4237 | 4237 |
if (gettimeofday(&ctx.time_limit, NULL) == 0) { |
4238 |
- uint32_t secs = ctx.engine->time_limit / 1000; |
|
4239 |
- uint32_t usecs = (ctx.engine->time_limit % 1000) * 1000; |
|
4238 |
+ uint32_t secs = ctx.engine->maxscantime / 1000; |
|
4239 |
+ uint32_t usecs = (ctx.engine->maxscantime % 1000) * 1000; |
|
4240 | 4240 |
ctx.time_limit.tv_sec += secs; |
4241 | 4241 |
ctx.time_limit.tv_usec += usecs; |
4242 | 4242 |
if (ctx.time_limit.tv_usec >= 1000000) { |
... | ... |
@@ -4245,7 +4254,7 @@ static cl_error_t scan_common(int desc, cl_fmap_t *map, const char *filepath, co |
4245 | 4245 |
} |
4246 | 4246 |
} else { |
4247 | 4247 |
char buf[64]; |
4248 |
- cli_dbgmsg("scan_common; gettimeofday error: %s\n", cli_strerror(errno, buf, 64)); |
|
4248 |
+ cli_dbgmsg("scan_common: gettimeofday error: %s\n", cli_strerror(errno, buf, 64)); |
|
4249 | 4249 |
} |
4250 | 4250 |
} |
4251 | 4251 |
|
... | ... |
@@ -4403,14 +4412,14 @@ int cli_found_possibly_unwanted(cli_ctx *ctx) |
4403 | 4403 |
cli_dbgmsg("found Possibly Unwanted: %s\n", cli_get_last_virus(ctx)); |
4404 | 4404 |
if (SCAN_HEURISTIC_PRECEDENCE) { |
4405 | 4405 |
/* we found a heuristic match, don't scan further, |
4406 |
- * but consider it a virus. */ |
|
4406 |
+ * but consider it a virus. */ |
|
4407 | 4407 |
cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n"); |
4408 | 4408 |
return CL_VIRUS; |
4409 | 4409 |
} |
4410 | 4410 |
/* heuristic scan isn't taking precedence, keep scanning. |
4411 |
- * If this is part of an archive, and |
|
4412 |
- * we find a real malware we report that instead of the |
|
4413 |
- * heuristic match */ |
|
4411 |
+ * If this is part of an archive, and |
|
4412 |
+ * we find a real malware we report that instead of the |
|
4413 |
+ * heuristic match */ |
|
4414 | 4414 |
ctx->found_possibly_unwanted = 1; |
4415 | 4415 |
} else { |
4416 | 4416 |
cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n"); |
... | ... |
@@ -930,6 +930,11 @@ cl_error_t cli_unzip(cli_ctx *ctx) |
930 | 930 |
ret = CL_EMAXFILES; |
931 | 931 |
} |
932 | 932 |
|
933 |
+ if (cli_checktimelimit(ctx) != CL_SUCCESS) { |
|
934 |
+ cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime); |
|
935 |
+ ret = CL_ETIMEOUT; |
|
936 |
+ } |
|
937 |
+ |
|
933 | 938 |
/* |
934 | 939 |
* Detect overlapping files and zip bombs. |
935 | 940 |
*/ |
... | ... |
@@ -366,6 +366,8 @@ const struct clam_option __clam_options[] = { |
366 | 366 |
|
367 | 367 |
{"ForceToDisk", "force-to-disk", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option causes memory or nested map scans to dump the content to disk.\nIf you turn on this option, more data is written to disk and is available\nwhen the leave-temps option is enabled at the cost of more disk writes.", "no"}, |
368 | 368 |
|
369 |
+ {"MaxScanTime", "max-scantime", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum amount of time a scan may take to complete.\nIn this version, this field only affects the scan time of ZIP archives.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result allow scanning\nof certain files to lock up the scanning process/threads resulting in a Denial of Service.\nThe value is in milliseconds.", "120000"}, |
|
370 |
+ |
|
369 | 371 |
{"MaxScanSize", "max-scansize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXSCANSIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum amount of data to be scanned for each input file.\nArchives and other containers are recursively extracted and scanned up to this\nvalue.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage.", "100M"}, |
370 | 372 |
|
371 | 373 |
{"MaxFileSize", "max-filesize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXFILESIZE, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN, "Files/messages larger than this limit won't be scanned. Affects the input\nfile itself as well as files contained inside it (when the input file is\nan archive, a document or some other kind of container).\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "25M"}, |
... | ... |
@@ -391,8 +393,6 @@ const struct clam_option __clam_options[] = { |
391 | 391 |
|
392 | 392 |
{"MaxRecHWP3", "max-rechwp3", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXRECHWP3, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum recursive calls to HWP3 parsing function.\nHWP3 files using more than this limit will be terminated and alert the user.\nScans will be unable to scan any HWP3 attachments if the recursive limit is reached.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "16"}, |
393 | 393 |
|
394 |
- {"TimeLimit", "timelimit", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMSCAN, "This clamscan option is currently for testing only. It sets the engine parameter CL_ENGINE_TIME_LIMIT. The value is in milliseconds.", "0"}, |
|
395 |
- |
|
396 | 394 |
{"PCREMatchLimit", "pcre-match-limit", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_PCRE_MATCH_LIMIT, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum calls to the PCRE match function during an instance of regex matching.\nInstances using more than this limit will be terminated and alert the user but the scan will continue.\nFor more information on match_limit, see the PCRE documentation.\nNegative values are not allowed.\nWARNING: setting this limit too high may severely impact performance.", "100000"}, |
397 | 395 |
|
398 | 396 |
{"PCRERecMatchLimit", "pcre-recmatch-limit", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_PCRE_RECMATCH_LIMIT, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum recursive calls to the PCRE match function during an instance of regex matching.\nInstances using more than this limit will be terminated and alert the user but the scan will continue.\nFor more information on match_limit_recursion, see the PCRE documentation.\nNegative values are not allowed and values > PCREMatchLimit are superfluous.\nWARNING: setting this limit too high may severely impact performance.", "5000"}, |
... | ... |
@@ -506,6 +506,7 @@ const struct clam_option __clam_options[] = { |
506 | 506 |
|
507 | 507 |
/* Deprecated options */ |
508 | 508 |
|
509 |
+ {"TimeLimit", "timelimit", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "Deprecated option to set the max-scantime.\nThe value is in milliseconds.", "120000"}, |
|
509 | 510 |
{"DetectBrokenExecutables", "detect-broken", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_DEPRECATED, "Deprecated option to alert on broken PE and ELF executable files.", "no"}, |
510 | 511 |
{"AlgorithmicDetection", "algorithmic-detection", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Deprecated option to enable heuristic alerts (e.g. \"Heuristics.<sig name>\")", "no"}, |
511 | 512 |
{"BlockMax", "block-max", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "", ""}, |
... | ... |
@@ -76,8 +76,8 @@ Example |
76 | 76 |
# Default: no |
77 | 77 |
#OfficialDatabaseOnly no |
78 | 78 |
|
79 |
-# The daemon on Windows only supports unsecured TCP sockets. |
|
80 |
-# Due to security reasons make sure that your IP & port is not |
|
79 |
+# The daemon on Windows only supports unsecured TCP sockets. |
|
80 |
+# Due to security reasons make sure that your IP & port is not |
|
81 | 81 |
# exposed to the open internet. |
82 | 82 |
|
83 | 83 |
# TCP port address. |
... | ... |
@@ -203,7 +203,7 @@ TCPAddr 127.0.0.1 |
203 | 203 |
#DetectPUA yes |
204 | 204 |
|
205 | 205 |
# Exclude a specific PUA category. This directive can be used multiple times. |
206 |
-# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md for |
|
206 |
+# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md for |
|
207 | 207 |
# the complete list of PUA categories. |
208 | 208 |
# Default: Load all categories (if DetectPUA is activated) |
209 | 209 |
#ExcludePUA NetTool |
... | ... |
@@ -243,9 +243,9 @@ TCPAddr 127.0.0.1 |
243 | 243 |
# the end of a scan. If an archive contains both a heuristically detected |
244 | 244 |
# virus/phish, and a real malware, the real malware will be reported |
245 | 245 |
# |
246 |
-# Keep this disabled if you intend to handle "*.Heuristics.*" viruses |
|
246 |
+# Keep this disabled if you intend to handle "*.Heuristics.*" viruses |
|
247 | 247 |
# differently from "real" malware. |
248 |
-# If a non-heuristically-detected virus (signature-based) is found first, |
|
248 |
+# If a non-heuristically-detected virus (signature-based) is found first, |
|
249 | 249 |
# the scan is interrupted immediately, regardless of this config option. |
250 | 250 |
# |
251 | 251 |
# Default: no |
... | ... |
@@ -446,6 +446,16 @@ TCPAddr 127.0.0.1 |
446 | 446 |
# The options below protect your system against Denial of Service attacks |
447 | 447 |
# using archive bombs. |
448 | 448 |
|
449 |
+# This option sets the maximum amount of time to a scan may take. |
|
450 |
+# In this version, this field only affects the scan time of ZIP archives. |
|
451 |
+# Value of 0 disables the limit |
|
452 |
+# Note: disabling this limit or setting it too high may result allow scanning |
|
453 |
+# of certain files to lock up the scanning process/threads resulting in a Denial |
|
454 |
+# of Service. |
|
455 |
+# Time is in milliseconds. |
|
456 |
+# Default: 120000 |
|
457 |
+#MaxScanTime 300000 |
|
458 |
+ |
|
449 | 459 |
# This option sets the maximum amount of data to be scanned for each input file. |
450 | 460 |
# Archives and other containers are recursively extracted and scanned up to this |
451 | 461 |
# value. |
... | ... |
@@ -584,7 +594,7 @@ TCPAddr 127.0.0.1 |
584 | 584 |
## Bytecode |
585 | 585 |
## |
586 | 586 |
|
587 |
-# With this option enabled ClamAV will load bytecode from the database. |
|
587 |
+# With this option enabled ClamAV will load bytecode from the database. |
|
588 | 588 |
# It is highly recommended you keep this option on, otherwise you'll miss |
589 | 589 |
# detections for many new viruses. |
590 | 590 |
# Default: yes |
... | ... |
@@ -608,7 +618,7 @@ TCPAddr 127.0.0.1 |
608 | 608 |
#BytecodeSecurity TrustSigned |
609 | 609 |
|
610 | 610 |
# Set bytecode timeout in milliseconds. |
611 |
-# |
|
611 |
+# |
|
612 | 612 |
# Default: 5000 |
613 | 613 |
# BytecodeTimeout 1000 |
614 | 614 |
|