mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2026-05-07 07:06:20 -04:00
Fix ability to disable filesize limit with libclamav C API
You should be able to disable the maxfilesize limit by setting it to zero. When "disabled", ClamAV should defer to inherent limitations, which at this time is INT_MAX - 2 bytes. This works okay for ClamScan and ClamD because our option parser converts max-filesize=0 to 4294967295 (4GB). But it is presently broken for other applications using the libclamav C API, like this: ```c cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, 0); ``` The limit checks added for cl_scanmap_callback and cl_scanfile_callback in 0.103.4 and 0.104.1 broke this ability because we forgot to check if the `maxfilesize > 0` before enforcing it. This commit adds that guard so you can disable by setting to `0`. While working on this, I also found that the `max_size` variables in our libmspack scanner code are using an `off_t` type, which is a SIGNED integer that may be 32bit width even on some 64bit platforms, or may be a 64bit width. AND the default `max_size` when `maxfilesize == 0` was being set to UINT_MAX (0xffffffff), aka `-1` when `off_t` is 32bits. This commit addresses this related issue by: - changing the `max_size` to use `uint64_t`, like our other limits. - verifying that `maxfilesize > 0` before using it. - checking that using `UINT32_MAX` as a backup will not exceed the max-scansize in the same way that we do with the maxfilesize.
This commit is contained in:
@@ -34,7 +34,7 @@ struct mspack_name {
|
||||
|
||||
struct mspack_system_ex {
|
||||
struct mspack_system ops;
|
||||
off_t max_size;
|
||||
uint64_t max_size;
|
||||
};
|
||||
|
||||
struct mspack_handle {
|
||||
@@ -45,7 +45,7 @@ struct mspack_handle {
|
||||
off_t offset;
|
||||
|
||||
FILE *f;
|
||||
off_t max_size;
|
||||
uint64_t max_size;
|
||||
};
|
||||
|
||||
static struct mspack_file *mspack_fmap_open(struct mspack_system *self,
|
||||
@@ -170,7 +170,7 @@ static int mspack_fmap_write(struct mspack_file *file, void *buffer, int bytes)
|
||||
{
|
||||
struct mspack_handle *mspack_handle = (struct mspack_handle *)file;
|
||||
size_t count;
|
||||
off_t max_size;
|
||||
uint64_t max_size;
|
||||
|
||||
if (bytes < 0 || !mspack_handle) {
|
||||
cli_dbgmsg("%s() err %d\n", __func__, __LINE__);
|
||||
@@ -189,7 +189,7 @@ static int mspack_fmap_write(struct mspack_file *file, void *buffer, int bytes)
|
||||
if (!max_size)
|
||||
return bytes;
|
||||
|
||||
max_size = max_size < (off_t)bytes ? max_size : (off_t)bytes;
|
||||
max_size = max_size < (uint64_t)bytes ? max_size : (uint64_t)bytes;
|
||||
|
||||
mspack_handle->max_size -= max_size;
|
||||
|
||||
@@ -366,7 +366,7 @@ int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset)
|
||||
}
|
||||
files = 0;
|
||||
for (cab_f = cab_h->files; cab_f; cab_f = cab_f->next) {
|
||||
off_t max_size;
|
||||
uint64_t max_size;
|
||||
char *tmp_fname = NULL;
|
||||
|
||||
ret = cli_matchmeta(ctx, cab_f->filename, 0, cab_f->length, 0,
|
||||
@@ -387,13 +387,27 @@ int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->engine->maxscansize &&
|
||||
ctx->scansize + ctx->engine->maxfilesize >=
|
||||
ctx->engine->maxscansize)
|
||||
max_size = ctx->engine->maxscansize -
|
||||
ctx->scansize;
|
||||
else
|
||||
max_size = ctx->engine->maxfilesize ? ctx->engine->maxfilesize : 0xffffffff;
|
||||
if (ctx->engine->maxfilesize > 0) {
|
||||
// max filesize has been set
|
||||
if ((ctx->engine->maxscansize > 0) &&
|
||||
(ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)) {
|
||||
// ... but would exceed max scansize, shrink it.
|
||||
max_size = ctx->engine->maxscansize - ctx->scansize;
|
||||
} else {
|
||||
// ... and will work
|
||||
max_size = ctx->engine->maxfilesize;
|
||||
}
|
||||
} else {
|
||||
// max filesize not specified
|
||||
if ((ctx->engine->maxscansize > 0) &&
|
||||
(ctx->scansize + UINT32_MAX >= ctx->engine->maxscansize)) {
|
||||
// ... but UINT32_MAX would exceed max scansize, shrink it.
|
||||
max_size = ctx->engine->maxscansize - ctx->scansize;
|
||||
} else {
|
||||
// ... use UINT32_MAX
|
||||
max_size = UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
tmp_fname = cli_gentemp(ctx->sub_tmpdir);
|
||||
if (!tmp_fname) {
|
||||
@@ -468,7 +482,7 @@ int cli_scanmschm(cli_ctx *ctx)
|
||||
}
|
||||
files = 0;
|
||||
for (mschm_f = mschm_h->files; mschm_f; mschm_f = mschm_f->next) {
|
||||
off_t max_size;
|
||||
uint64_t max_size;
|
||||
char *tmp_fname;
|
||||
|
||||
ret = cli_matchmeta(ctx, mschm_f->filename, 0, mschm_f->length,
|
||||
@@ -489,13 +503,27 @@ int cli_scanmschm(cli_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->engine->maxscansize &&
|
||||
ctx->scansize + ctx->engine->maxfilesize >=
|
||||
ctx->engine->maxscansize)
|
||||
max_size = ctx->engine->maxscansize -
|
||||
ctx->scansize;
|
||||
else
|
||||
max_size = ctx->engine->maxfilesize ? ctx->engine->maxfilesize : 0xffffffff;
|
||||
if (ctx->engine->maxfilesize > 0) {
|
||||
// max filesize has been set
|
||||
if ((ctx->engine->maxscansize > 0) &&
|
||||
(ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)) {
|
||||
// ... but would exceed max scansize, shrink it.
|
||||
max_size = ctx->engine->maxscansize - ctx->scansize;
|
||||
} else {
|
||||
// ... and will work
|
||||
max_size = ctx->engine->maxfilesize;
|
||||
}
|
||||
} else {
|
||||
// max filesize not specified
|
||||
if ((ctx->engine->maxscansize > 0) &&
|
||||
(ctx->scansize + UINT32_MAX >= ctx->engine->maxscansize)) {
|
||||
// ... but UINT32_MAX would exceed max scansize, shrink it.
|
||||
max_size = ctx->engine->maxscansize - ctx->scansize;
|
||||
} else {
|
||||
// ... use UINT32_MAX
|
||||
max_size = UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
ops_ex.max_size = max_size;
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ typedef struct cli_ctx_tag {
|
||||
unsigned long int *scanned;
|
||||
const struct cli_matcher *root;
|
||||
const struct cl_engine *engine;
|
||||
unsigned long scansize;
|
||||
uint64_t scansize;
|
||||
struct cl_scan_options *options;
|
||||
unsigned int scannedfiles;
|
||||
unsigned int found_possibly_unwanted;
|
||||
|
||||
@@ -5462,7 +5462,7 @@ cl_error_t cl_scandesc_callback(int desc, const char *filename, const char **vir
|
||||
status = CL_CLEAN;
|
||||
goto done;
|
||||
}
|
||||
if ((uint64_t)sb.st_size > engine->maxfilesize) {
|
||||
if ((engine->maxfilesize > 0) && ((uint64_t)sb.st_size > engine->maxfilesize)) {
|
||||
cli_dbgmsg("cl_scandesc_callback: File too large (" STDu64 " bytes), ignoring\n", (uint64_t)sb.st_size);
|
||||
if (scanoptions->heuristic & CL_SCAN_HEURISTIC_EXCEEDS_MAX) {
|
||||
if (engine->cb_virus_found)
|
||||
@@ -5499,7 +5499,7 @@ done:
|
||||
|
||||
cl_error_t cl_scanmap_callback(cl_fmap_t *map, const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, struct cl_scan_options *scanoptions, void *context)
|
||||
{
|
||||
if (map->len > engine->maxfilesize) {
|
||||
if ((engine->maxfilesize > 0) && (map->len > engine->maxfilesize)) {
|
||||
cli_dbgmsg("cl_scandesc_callback: File too large (%zu bytes), ignoring\n", map->len);
|
||||
if (scanoptions->heuristic & CL_SCAN_HEURISTIC_EXCEEDS_MAX) {
|
||||
if (engine->cb_virus_found)
|
||||
|
||||
Reference in New Issue
Block a user