mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-20 02:43:16 +00:00
Raise artificial 4G limit for MaxScanSize
This limit is internally "long long", so >=64-bit even on 32-bit platforms. Also fixes a related issue where limits could have been set to negative values on 64-bit platforms where setting a "long long" (64-bit signed) can overflow if assigned from an "unsigned long" (64-bit unsigned). Resolves: https://github.com/Cisco-Talos/clamav/issues/809
This commit is contained in:
parent
e4ac4b646a
commit
2962509609
2 changed files with 48 additions and 17 deletions
|
@ -63,7 +63,7 @@
|
||||||
#define MAXCMDOPTS 150
|
#define MAXCMDOPTS 150
|
||||||
|
|
||||||
#define MATCH_NUMBER "^[0-9]+$"
|
#define MATCH_NUMBER "^[0-9]+$"
|
||||||
#define MATCH_SIZE "^[0-9]+[KM]?$"
|
#define MATCH_SIZE "^[0-9]+[KMG]?$"
|
||||||
#define MATCH_BOOL "^(yes|true|1|no|false|0)$"
|
#define MATCH_BOOL "^(yes|true|1|no|false|0)$"
|
||||||
|
|
||||||
#define FLAG_MULTIPLE 1 /* option can be used multiple times */
|
#define FLAG_MULTIPLE 1 /* option can be used multiple times */
|
||||||
|
@ -440,7 +440,7 @@ const struct clam_option __clam_options[] = {
|
||||||
|
|
||||||
{"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.\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"},
|
{"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.\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"},
|
||||||
|
|
||||||
{"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.", "400M"},
|
{"MaxScanSize", "max-scansize", 0, CLOPT_TYPE_SIZE64, 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.", "400M"},
|
||||||
|
|
||||||
{"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.", "100M"},
|
{"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.", "100M"},
|
||||||
|
|
||||||
|
@ -646,7 +646,7 @@ const struct clam_option __clam_options[] = {
|
||||||
{"LeaveTemporaryFiles", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
{"LeaveTemporaryFiles", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
||||||
{"LocalSocket", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
{"LocalSocket", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
||||||
{"MailFollowURLs", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
{"MailFollowURLs", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
||||||
{"MaxScanSize", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
{"MaxScanSize", NULL, 0, CLOPT_TYPE_SIZE64, MATCH_SIZE, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
||||||
{"MaxFiles", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
{"MaxFiles", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
||||||
{"MaxRecursion", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
{"MaxRecursion", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
||||||
{"PhishingSignatures", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
{"PhishingSignatures", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", ""},
|
||||||
|
@ -923,7 +923,7 @@ struct optstruct *optparse(const char *cfgfile, int argc, char **argv, int verbo
|
||||||
struct option longopts[MAXCMDOPTS];
|
struct option longopts[MAXCMDOPTS];
|
||||||
char shortopts[MAXCMDOPTS];
|
char shortopts[MAXCMDOPTS];
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
long long numarg, lnumarg;
|
long long numarg, lnumarg, lnumlimit;
|
||||||
int regflags = REG_EXTENDED | REG_NOSUB;
|
int regflags = REG_EXTENDED | REG_NOSUB;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -1204,25 +1204,40 @@ struct optstruct *optparse(const char *cfgfile, int argc, char **argv, int verbo
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLOPT_TYPE_SIZE:
|
case CLOPT_TYPE_SIZE:
|
||||||
|
case CLOPT_TYPE_SIZE64:
|
||||||
|
if (optentry->argtype == CLOPT_TYPE_SIZE64)
|
||||||
|
/* guaranteed to be "long long" (64 bit but possibly signed) further down the line */
|
||||||
|
lnumlimit = LLONG_MAX;
|
||||||
|
else
|
||||||
|
/* probably mostly "unsigned long int" (32 or 64 bit unsigned depending on platform),
|
||||||
|
* but may be expected to fit into a "long long" (64-bit signed) */
|
||||||
|
lnumlimit = LLONG_MAX < ULONG_MAX ? LLONG_MAX : ULONG_MAX;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (arg)
|
if (arg)
|
||||||
lnumarg = strtoul(arg, &buff, 0);
|
lnumarg = strtoll(arg, &buff, 0);
|
||||||
else {
|
else {
|
||||||
numarg = 0;
|
numarg = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (errno != ERANGE) {
|
if (errno != ERANGE) {
|
||||||
switch (*buff) {
|
switch (*buff) {
|
||||||
|
case 'G':
|
||||||
|
case 'g':
|
||||||
|
if (lnumarg <= lnumlimit / (1024 * 1024 * 1024))
|
||||||
|
lnumarg *= 1024 * 1024 * 1024;
|
||||||
|
else
|
||||||
|
errno = ERANGE;
|
||||||
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'm':
|
case 'm':
|
||||||
if (lnumarg <= UINT_MAX / (1024 * 1024))
|
if (lnumarg <= lnumlimit / (1024 * 1024))
|
||||||
lnumarg *= 1024 * 1024;
|
lnumarg *= 1024 * 1024;
|
||||||
else
|
else
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
break;
|
break;
|
||||||
case 'K':
|
case 'K':
|
||||||
case 'k':
|
case 'k':
|
||||||
if (lnumarg <= UINT_MAX / 1024)
|
if (lnumarg <= lnumlimit / 1024)
|
||||||
lnumarg *= 1024;
|
lnumarg *= 1024;
|
||||||
else
|
else
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
|
@ -1246,17 +1261,17 @@ struct optstruct *optparse(const char *cfgfile, int argc, char **argv, int verbo
|
||||||
if (err) break;
|
if (err) break;
|
||||||
if (errno == ERANGE) {
|
if (errno == ERANGE) {
|
||||||
if (cfgfile) {
|
if (cfgfile) {
|
||||||
fprintf(stderr, "WARNING: Numerical value for option %s too high, resetting to 4G\n", name);
|
fprintf(stderr, "WARNING: Numerical value for option %s too high, resetting to %lld\n", name, lnumlimit);
|
||||||
} else {
|
} else {
|
||||||
if (optentry->shortopt)
|
if (optentry->shortopt)
|
||||||
fprintf(stderr, "WARNING: Numerical value for option --%s (-%c) too high, resetting to 4G\n", optentry->longopt, optentry->shortopt);
|
fprintf(stderr, "WARNING: Numerical value for option --%s (-%c) too high, resetting to %lld\n", optentry->longopt, optentry->shortopt, lnumlimit);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "WARNING: Numerical value for option %s too high, resetting to 4G\n", optentry->longopt);
|
fprintf(stderr, "WARNING: Numerical value for option %s too high, resetting to %lld\n", optentry->longopt, lnumlimit);
|
||||||
}
|
}
|
||||||
lnumarg = UINT_MAX;
|
lnumarg = lnumlimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
numarg = lnumarg ? lnumarg : UINT_MAX;
|
numarg = lnumarg ? lnumarg : lnumlimit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLOPT_TYPE_BOOL:
|
case CLOPT_TYPE_BOOL:
|
||||||
|
@ -1319,7 +1334,7 @@ struct optstruct *optadditem(const char *name, const char *arg, int verbose, int
|
||||||
struct optstruct *opts = NULL, *opts_last = NULL, *opt;
|
struct optstruct *opts = NULL, *opts_last = NULL, *opt;
|
||||||
char *buff;
|
char *buff;
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
long long numarg, lnumarg;
|
long long numarg, lnumarg, lnumlimit;
|
||||||
int regflags = REG_EXTENDED | REG_NOSUB;
|
int regflags = REG_EXTENDED | REG_NOSUB;
|
||||||
const struct clam_option *optentry = NULL;
|
const struct clam_option *optentry = NULL;
|
||||||
|
|
||||||
|
@ -1417,25 +1432,40 @@ struct optstruct *optadditem(const char *name, const char *arg, int verbose, int
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLOPT_TYPE_SIZE:
|
case CLOPT_TYPE_SIZE:
|
||||||
|
case CLOPT_TYPE_SIZE64:
|
||||||
|
if (optentry->argtype == CLOPT_TYPE_SIZE64)
|
||||||
|
/* guaranteed to be "long long" (64 bit but possibly signed) further down the line */
|
||||||
|
lnumlimit = LLONG_MAX;
|
||||||
|
else
|
||||||
|
/* probably mostly "unsigned long int" (32 or 64 bit unsigned depending on platform),
|
||||||
|
* but may be expected to fit into a "long long" (64-bit signed) */
|
||||||
|
lnumlimit = LLONG_MAX < ULONG_MAX ? LLONG_MAX : ULONG_MAX;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (arg)
|
if (arg)
|
||||||
lnumarg = strtoul(arg, &buff, 0);
|
lnumarg = strtoll(arg, &buff, 0);
|
||||||
else {
|
else {
|
||||||
numarg = 0;
|
numarg = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (errno != ERANGE) {
|
if (errno != ERANGE) {
|
||||||
switch (*buff) {
|
switch (*buff) {
|
||||||
|
case 'G':
|
||||||
|
case 'g':
|
||||||
|
if (lnumarg <= lnumlimit / (1024 * 1024 * 1024))
|
||||||
|
lnumarg *= 1024 * 1024 * 1024;
|
||||||
|
else
|
||||||
|
errno = ERANGE;
|
||||||
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'm':
|
case 'm':
|
||||||
if (lnumarg <= UINT_MAX / (1024 * 1024))
|
if (lnumarg <= lnumlimit / (1024 * 1024))
|
||||||
lnumarg *= 1024 * 1024;
|
lnumarg *= 1024 * 1024;
|
||||||
else
|
else
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
break;
|
break;
|
||||||
case 'K':
|
case 'K':
|
||||||
case 'k':
|
case 'k':
|
||||||
if (lnumarg <= UINT_MAX / 1024)
|
if (lnumarg <= lnumlimit / 1024)
|
||||||
lnumarg *= 1024;
|
lnumarg *= 1024;
|
||||||
else
|
else
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
|
|
|
@ -38,8 +38,9 @@
|
||||||
|
|
||||||
#define CLOPT_TYPE_STRING 1 /* quoted/regular string */
|
#define CLOPT_TYPE_STRING 1 /* quoted/regular string */
|
||||||
#define CLOPT_TYPE_NUMBER 2 /* raw number */
|
#define CLOPT_TYPE_NUMBER 2 /* raw number */
|
||||||
#define CLOPT_TYPE_SIZE 3 /* number possibly followed by modifiers (M/m or K/k) */
|
#define CLOPT_TYPE_SIZE 3 /* number possibly followed by modifiers (K/k, M/m or G/g) */
|
||||||
#define CLOPT_TYPE_BOOL 4 /* boolean */
|
#define CLOPT_TYPE_BOOL 4 /* boolean */
|
||||||
|
#define CLOPT_TYPE_SIZE64 5 /* 64-bit number possibly followed by modifiers (K/k, M/m or G/g) */
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extern char _DATADIR[MAX_PATH];
|
extern char _DATADIR[MAX_PATH];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue