Improvements to adhere to scan time limit

Error handling for bytecode sig evaluation, as well as logical and yara
sig evaluation only consider CL_VIRUS or CL_SUCCESS and fail to
consider terminal errors such as CL_ETIMEOUT.

This commit fixes the error handling in those functions so we properly
abort instead of continuing to evaluate more sigs.

This commit also adds some a scan time limit checks:
1. shortly after a bytecode time limit exceeded.
2. after evaluating each lsig or yara sig.
3. when processing unzip central directory file headers.
pull/727/head
Micah Snyder 3 years ago committed by Micah Snyder
parent bbcd4c275b
commit df99364c3c
  1. 6
      libclamav/bytecode.c
  2. 38
      libclamav/matcher.c
  3. 2
      libclamav/scanners.c
  4. 7
      libclamav/unzip.c

@ -2851,6 +2851,12 @@ cl_error_t cli_bytecode_runlsig(cli_ctx *cctx, struct cli_target_info *tinfo,
if (ret != CL_SUCCESS) {
cli_warnmsg("Bytecode '%s' (id: %u) failed to run: %s\n", bc_name, bc->id, cl_strerror(ret));
bytecode_context_reset(&ctx);
if (cli_checktimelimit(cctx) != CL_SUCCESS) {
cli_dbgmsg("Exceeded scan timeout during bytecode run (max: %u)\n", cctx->engine->maxscantime);
return CL_ETIMEOUT;
}
return CL_SUCCESS;
}
if (ctx.virname) {

@ -912,9 +912,11 @@ static cl_error_t lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_a
if (status != CL_SUCCESS) {
goto done;
}
} else if (CL_VIRUS == cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, ac_lsig->bc_idx, acdata->lsigcnt[lsid], acdata->lsigsuboff_first[lsid], ctx->fmap)) {
status = CL_VIRUS;
goto done;
} else {
status = cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, ac_lsig->bc_idx, acdata->lsigcnt[lsid], acdata->lsigsuboff_first[lsid], ctx->fmap);
if (CL_SUCCESS != status) {
goto done;
}
}
}
goto done;
@ -925,8 +927,8 @@ static cl_error_t lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_a
goto done;
}
}
if (CL_VIRUS == cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, ac_lsig->bc_idx, acdata->lsigcnt[lsid], acdata->lsigsuboff_first[lsid], ctx->fmap)) {
status = CL_VIRUS;
status = cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, ac_lsig->bc_idx, acdata->lsigcnt[lsid], acdata->lsigsuboff_first[lsid], ctx->fmap);
if (CL_SUCCESS != status) {
goto done;
}
}
@ -972,24 +974,30 @@ static cl_error_t yara_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_a
cl_error_t cli_exp_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *acdata, struct cli_target_info *target_info, const char *hash)
{
uint32_t i;
cl_error_t rc = CL_SUCCESS;
cl_error_t status = CL_SUCCESS;
for (i = 0; i < root->ac_lsigs; i++) {
if (root->ac_lsigtable[i]->type == CLI_LSIG_NORMAL)
rc = lsig_eval(ctx, root, acdata, target_info, hash, i);
if (root->ac_lsigtable[i]->type == CLI_LSIG_NORMAL) {
status = lsig_eval(ctx, root, acdata, target_info, hash, i);
}
#ifdef HAVE_YARA
else if (root->ac_lsigtable[i]->type == CLI_YARA_NORMAL || root->ac_lsigtable[i]->type == CLI_YARA_OFFSET)
rc = yara_eval(ctx, root, acdata, target_info, hash, i);
else if (root->ac_lsigtable[i]->type == CLI_YARA_NORMAL || root->ac_lsigtable[i]->type == CLI_YARA_OFFSET) {
status = yara_eval(ctx, root, acdata, target_info, hash, i);
}
#endif
if (rc == CL_VIRUS) {
if (CL_SUCCESS != status) {
break;
}
}
if (rc == CL_VIRUS) {
return CL_VIRUS;
if (cli_checktimelimit(ctx) != CL_SUCCESS) {
cli_dbgmsg("Exceeded scan time limit while evaluating logical and yara signatures (max: %u)\n", ctx->engine->maxscantime);
status = CL_ETIMEOUT;
break;
}
}
return CL_CLEAN;
return status;
}
cl_error_t cli_scan_fmap(cli_ctx *ctx, cli_file_t ftype, bool filetype_only, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, unsigned char *refhash)

@ -1537,7 +1537,7 @@ static cl_error_t vba_scandata(const unsigned char *data, size_t len, cli_ctx *c
must_pop_stack = true;
ret = cli_exp_eval(ctx, target_ac_root, &tmdata, NULL, NULL);
if (ret == CL_VIRUS) {
if (CL_SUCCESS != ret) {
goto done;
}

@ -817,6 +817,13 @@ parse_central_directory_file_header(
*ret = CL_EPARSE;
if (cli_checktimelimit(ctx) != CL_SUCCESS) {
cli_dbgmsg("cli_unzip: central header - Time limit reached (max: %u)\n", ctx->engine->maxscantime);
last = 1;
*ret = CL_ETIMEOUT;
goto done;
}
if (!(central_header = fmap_need_off(map, coff, SIZEOF_CENTRAL_HEADER)) || CENTRAL_HEADER_magic != ZIP_MAGIC_CENTRAL_DIRECTORY_RECORD_BEGIN) {
if (central_header) {
fmap_unneed_ptr(map, central_header, SIZEOF_CENTRAL_HEADER);

Loading…
Cancel
Save