diff --git a/clamd/clamd.c b/clamd/clamd.c index df7fc111a..cada1821e 100644 --- a/clamd/clamd.c +++ b/clamd/clamd.c @@ -338,6 +338,9 @@ int main(int argc, char **argv) break; } + if (optget(opts, "disable-cache")->enabled) + cl_engine_set_num(engine, CL_ENGINE_DISABLE_CACHE, 1); + /* load the database(s) */ dbdir = optget(opts, "DatabaseDirectory")->strarg; logg("#Reading databases from %s\n", dbdir); diff --git a/clamscan/manager.c b/clamscan/manager.c index 916797f98..a97ee860d 100644 --- a/clamscan/manager.c +++ b/clamscan/manager.c @@ -567,6 +567,9 @@ int scanmanager(const struct optstruct *opts) return 2; } + if (optget(opts, "disable-cache")->enabled) + cl_engine_set_num(engine, CL_ENGINE_DISABLE_CACHE, 1); + if(optget(opts, "detect-pua")->enabled) { dboptions |= CL_DB_PUA; if((opt = optget(opts, "exclude-pua"))->enabled) { diff --git a/etc/clamd.conf.sample b/etc/clamd.conf.sample index 22f0765f5..4d7d6f943 100644 --- a/etc/clamd.conf.sample +++ b/etc/clamd.conf.sample @@ -246,6 +246,13 @@ Example # when the LeaveTemporaryFiles option is enabled. #ForceToDisk yes +# This option allows you to disable the caching feature of the engine. By +# default, the engine will store an MD5 in a cache of any files that are +# not flagged as virus or that hit limits checks. Disabling the cache will +# have a negative performance impact on large scans. +# Default: no +#DisableCache yes + ## ## Executable files ## diff --git a/libclamav/cache.c b/libclamav/cache.c index ff91b75c9..376273d48 100644 --- a/libclamav/cache.c +++ b/libclamav/cache.c @@ -743,6 +743,11 @@ int cli_cache_init(struct cl_engine *engine) { struct CACHE *cache; unsigned int i, j; + if (engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE) { + cli_dbgmsg("cli_cache_init: Caching disabled.\n"); + return 0; + } + if(!engine) { cli_errmsg("cli_cache_init: mpool malloc fail\n"); return 1; @@ -777,6 +782,10 @@ void cli_cache_destroy(struct cl_engine *engine) { struct CACHE *cache; unsigned int i; + if (engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE) { + return; + } + if(!engine || !(cache = engine->cache)) return; @@ -813,6 +822,11 @@ void cache_add(unsigned char *md5, size_t size, cli_ctx *ctx) { uint32_t level; struct CACHE *c; + if (ctx->engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE) { + cli_dbgmsg("cache_add: Caching disabled. Not adding sample to cache.\n"); + return; + } + if(!ctx || !ctx->engine || !ctx->engine->cache) return; @@ -851,6 +865,11 @@ void cache_remove(unsigned char *md5, size_t size, const struct cl_engine *engin unsigned int key = getkey(md5); struct CACHE *c; + if (engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE) { + cli_dbgmsg("cache_remove: Caching disabled.\n"); + return; + } + if(!engine || !engine->cache) return; @@ -886,6 +905,11 @@ int cache_check(unsigned char *hash, cli_ctx *ctx) { cli_md5_ctx md5; int ret; + if (ctx->engine->engine_options & ENGINE_OPTIONS_DISABLE_CACHE) { + cli_dbgmsg("cache_check: Caching disabled. Returning CL_VIRUS.\n"); + return CL_VIRUS; + } + if(!ctx || !ctx->engine || !ctx->engine->cache) return CL_VIRUS; diff --git a/libclamav/clamav.h b/libclamav/clamav.h index 96c38bd28..2bc75d894 100644 --- a/libclamav/clamav.h +++ b/libclamav/clamav.h @@ -194,7 +194,8 @@ enum cl_engine_field { CL_ENGINE_MAX_HTMLNOTAGS, /* uint64_t */ CL_ENGINE_MAX_SCRIPTNORMALIZE, /* uint64_t */ CL_ENGINE_MAX_ZIPTYPERCG, /* uint64_t */ - CL_ENGINE_FORCETODISK /* uint32_t */ + CL_ENGINE_FORCETODISK, /* uint32_t */ + CL_ENGINE_DISABLE_CACHE /* uint32_t */ }; enum bytecode_security { @@ -232,6 +233,13 @@ extern int cl_engine_addref(struct cl_engine *engine); extern int cl_engine_free(struct cl_engine *engine); +extern void cli_cache_disable(void); + +extern int cli_cache_enable(struct cl_engine *engine); + +/* For the new engine_options bit field in the engine */ +#define ENGINE_OPTIONS_NONE 0 +#define ENGINE_OPTIONS_DISABLE_CACHE 1 /* CALLBACKS */ diff --git a/libclamav/others.c b/libclamav/others.c index 926358b70..4c9b8a52c 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -490,6 +490,15 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long if (num == CL_BYTECODE_MODE_TEST) cli_infomsg(NULL, "bytecode engine in test mode\n"); break; + case CL_ENGINE_DISABLE_CACHE: + if (num) { + engine->engine_options |= ENGINE_OPTIONS_DISABLE_CACHE; + } else { + engine->engine_options &= ~(ENGINE_OPTIONS_DISABLE_CACHE); + if (!(engine->cache)) + cli_cache_init(engine); + } + break; default: cli_errmsg("cl_engine_set_num: Incorrect field number\n"); return CL_EARG; diff --git a/libclamav/others.h b/libclamav/others.h index 90d4631a5..e9c7f0fa7 100644 --- a/libclamav/others.h +++ b/libclamav/others.h @@ -193,6 +193,7 @@ struct cl_engine { uint32_t ac_maxdepth; char *tmpdir; uint32_t keeptmp; + uint64_t engine_options; /* Limits */ uint64_t maxscansize; /* during the scanning of archives this size @@ -307,6 +308,7 @@ struct cl_settings { uint32_t bytecode_timeout; enum bytecode_mode bytecode_mode; char *pua_cats; + uint64_t engine_options; /* callbacks */ clcb_pre_cache cb_pre_cache; diff --git a/shared/optparser.c b/shared/optparser.c index b99a3ff80..fcf087fa1 100644 --- a/shared/optparser.c +++ b/shared/optparser.c @@ -253,6 +253,8 @@ const struct clam_option __clam_options[] = { { "SelfCheck", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 600, NULL, 0, OPT_CLAMD, "This option specifies the time intervals (in seconds) in which clamd\nshould perform a database check.", "600" }, + { "DisableCache", "disable-cache", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option allows you to disable clamd's caching feature.", "no" }, + { "VirusEvent", NULL, 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Execute a command when a virus is found. In the command string %v will be\nreplaced with the virus name. Additionally, two environment variables will\nbe defined: $CLAM_VIRUSEVENT_FILENAME and $CLAM_VIRUSEVENT_VIRUSNAME.", "/usr/bin/mailx -s \"ClamAV VIRUS ALERT: %v\" alert < /dev/null" }, { "ExitOnOOM", NULL, 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Stop the daemon when libclamav reports an out of memory condition.", "yes" },