diff --git a/CHANGES b/CHANGES index 4be4bc8f..16d12fef 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ DD MMM YYYY - 2.9.2 - To be released ------------------------------------ + * Added SecCollectionGCFrequency option for configuring frequncy + at which garbage collection runs for persistent collections + [Issue #1298 - Robert Bost] * Uses an optional global lock while manipulating collections. [Issues #1224 - @mturk and @zimmerle] * Fix collection naming problem while merging collections. diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c index ce97950f..611c36d4 100644 --- a/apache2/apache2_config.c +++ b/apache2/apache2_config.c @@ -140,6 +140,7 @@ void *create_directory_config(apr_pool_t *mp, char *path) /* Collection timeout */ dcfg->col_timeout = NOT_SET; + dcfg->col_gc_freq = NOT_SET; dcfg->crypto_key = NOT_SET_P; dcfg->crypto_key_len = NOT_SET; @@ -588,6 +589,9 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) merged->col_timeout = (child->col_timeout == NOT_SET ? parent->col_timeout : child->col_timeout); + merged->col_gc_freq = (child->col_gc_freq == NOT_SET) + ? parent->col_gc_freq : child->col_gc_freq; + /* Hash */ merged->crypto_key = (child->crypto_key == NOT_SET_P ? parent->crypto_key : child->crypto_key); @@ -730,6 +734,7 @@ void init_directory_config(directory_config *dcfg) if (dcfg->disable_backend_compression == NOT_SET) dcfg->disable_backend_compression = 0; if (dcfg->col_timeout == NOT_SET) dcfg->col_timeout = 3600; + if (dcfg->col_gc_freq == NOT_SET) dcfg->col_gc_freq = .01; /* Hash */ if (dcfg->crypto_key == NOT_SET_P) dcfg->crypto_key = getkey(dcfg->mp); @@ -1204,7 +1209,7 @@ static const char *cmd_audit_log(cmd_parms *cmd, void *_dcfg, const char *p1) else { const char *file_name = ap_server_root_relative(cmd->pool, dcfg->auditlog_name); apr_status_t rc; - + if (dcfg->auditlog_fileperms == NOT_SET) { dcfg->auditlog_fileperms = CREATEMODE; } @@ -1492,6 +1497,32 @@ static const char *cmd_collection_timeout(cmd_parms *cmd, void *_dcfg, return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecCollectionTimeout: %s", p1); } +static const char *cmd_collection_gc_freq(cmd_parms *cmd, void *_dcfg, + const char *p1, const char *p2) +{ + directory_config *dcfg = (directory_config *)_dcfg; + float freq; + + if (sscanf(p1, "%f", &freq) != 1) { + return "ModSecurity: Invalid value for SecCollectionGCFrequency. Value must be a float."; + } + + if (freq <= 0) { + // <= 0 would mean GC would never run. + return "ModSecurity: Invalid value for SecCollectionGCFrequency. Value must be greater than 0."; + } + + if (freq > 100) { + // >100 would make no sense. + return "ModSecurity: Invalid value for SecCollectionGCFrequency. Value must be less than 100."; + } + + // Convert to percentage + dcfg->col_gc_freq = freq / 100; + + return NULL; +} + static const char *cmd_debug_log_level(cmd_parms *cmd, void *_dcfg, const char *p1) { @@ -3384,6 +3415,14 @@ const command_rec module_directives[] = { "set default collections timeout. default it 3600" ), + AP_INIT_TAKE12 ( + "SecCollectionGCFrequency", + cmd_collection_gc_freq, + NULL, + CMD_SCOPE_ANY, + "set garbage collection frequency. default is to run during roughly 1% of requests." + ), + AP_INIT_TAKE1 ( "SecDefaultAction", cmd_default_action, diff --git a/apache2/modsecurity.c b/apache2/modsecurity.c index dcdb4859..f29ac9a8 100644 --- a/apache2/modsecurity.c +++ b/apache2/modsecurity.c @@ -265,9 +265,9 @@ static void modsecurity_persist_data(modsec_rec *msr) { /* Remove stale collections. */ #if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 3 - if (ap_random_pick(0, RAND_MAX) < RAND_MAX/100) { + if (ap_random_pick(0, RAND_MAX) < (RAND_MAX * msr->txcfg->col_gc_freq)) { #else - if (rand() < RAND_MAX/100) { + if (rand() < (RAND_MAX * msr->txcfg->col_gc_freq)) { #endif arr = apr_table_elts(msr->collections); te = (apr_table_entry_t *)arr->elts; diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index f170034c..c5318e20 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -610,6 +610,7 @@ struct directory_config { /* Collection timeout */ int col_timeout; + float col_gc_freq; /* hash of ids */ apr_hash_t *rule_id_htab;