Skip to content

Commit 112ba45

Browse files
author
Felipe Zimmerle
committed
Makes global mutex for collections optional
1 parent c6f6dff commit 112ba45

File tree

5 files changed

+100
-11
lines changed

5 files changed

+100
-11
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
DD MMM YYYY - 2.9.2 - To be released
22
------------------------------------
33

4+
* Uses an optional global lock while manipulating collections.
5+
[Issues #1224 - @mturk and @zimmerle]
46
* Fix collection naming problem while merging collections.
57
[Issue #1274 - Coty Sutherland and @zimmerle]
68
* Fix --enable-docs adding missing Makefile, modifying autoconf and filenames

apache2/modsecurity.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ int modsecurity_init(msc_engine *msce, apr_pool_t *mp) {
170170
}
171171
#endif /* SET_MUTEX_PERMS */
172172

173+
#ifdef GLOBAL_COLLECTION_LOCK
173174
rc = apr_global_mutex_create(&msce->dbm_lock, NULL, APR_LOCK_DEFAULT, mp);
174175
if (rc != APR_SUCCESS) {
175176
return -1;
@@ -185,6 +186,7 @@ int modsecurity_init(msc_engine *msce, apr_pool_t *mp) {
185186
return -1;
186187
}
187188
#endif /* SET_MUTEX_PERMS */
189+
#endif
188190
#endif
189191

190192
return 1;
@@ -211,12 +213,15 @@ void modsecurity_child_init(msc_engine *msce) {
211213
}
212214
}
213215

216+
#ifdef GLOBAL_COLLECTION_LOCK
214217
if (msce->dbm_lock != NULL) {
215218
apr_status_t rc = apr_global_mutex_child_init(&msce->dbm_lock, NULL, msce->mp);
216219
if (rc != APR_SUCCESS) {
217220
// ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to child-init dbm mutex");
218221
}
219222
}
223+
#endif
224+
220225
}
221226

222227
/**

apache2/modsecurity.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,9 @@ struct msc_engine {
657657
apr_pool_t *mp;
658658
apr_global_mutex_t *auditlog_lock;
659659
apr_global_mutex_t *geo_lock;
660+
#ifdef GLOBAL_COLLECTION_LOCK
660661
apr_global_mutex_t *dbm_lock;
662+
#endif
661663
msre_engine *msre;
662664
unsigned int processing_mode;
663665
};

apache2/persist_dbm.c

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,21 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
120120
key.dsize = col_key_len + 1;
121121

122122
if (existing_dbm == NULL) {
123+
#ifdef GLOBAL_COLLECTION_LOCK
123124
rc = apr_global_mutex_lock(msr->modsecurity->dbm_lock);
124125
if (rc != APR_SUCCESS) {
125126
msr_log(msr, 1, "collection_retrieve_ex: Failed to lock proc mutex: %s",
126127
get_apr_error(msr->mp, rc));
127128
goto cleanup;
128129
}
129-
130+
#endif
130131
rc = apr_sdbm_open(&dbm, dbm_filename, APR_READ | APR_SHARELOCK,
131132
CREATEMODE, msr->mp);
132133
if (rc != APR_SUCCESS) {
133134
dbm = NULL;
135+
#ifdef GLOBAL_COLLECTION_LOCK
134136
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
137+
#endif
135138
goto cleanup;
136139
}
137140
}
@@ -165,7 +168,9 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
165168
/* Close after "value" used from fetch or memory may be overwritten. */
166169
if (existing_dbm == NULL) {
167170
apr_sdbm_close(dbm);
171+
#ifdef GLOBAL_COLLECTION_LOCK
168172
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
173+
#endif
169174
dbm = NULL;
170175
}
171176

@@ -212,19 +217,23 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
212217
*/
213218
if (apr_table_get(col, "KEY") == NULL) {
214219
if (existing_dbm == NULL) {
220+
#ifdef GLOBAL_COLLECTION_LOCK
215221
rc = apr_global_mutex_lock(msr->modsecurity->dbm_lock);
216222
if (rc != APR_SUCCESS) {
217223
msr_log(msr, 1, "collection_retrieve_ex: Failed to lock proc mutex: %s",
218224
get_apr_error(msr->mp, rc));
219225
goto cleanup;
220-
}
226+
}
227+
#endif
221228
rc = apr_sdbm_open(&dbm, dbm_filename, APR_CREATE | APR_WRITE | APR_SHARELOCK,
222229
CREATEMODE, msr->mp);
223230
if (rc != APR_SUCCESS) {
224231
msr_log(msr, 1, "collection_retrieve_ex: Failed to access DBM file \"%s\": %s",
225232
log_escape(msr->mp, dbm_filename), get_apr_error(msr->mp, rc));
226233
dbm = NULL;
234+
#ifdef GLOBAL_COLLECTION_LOCK
227235
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
236+
#endif
228237
goto cleanup;
229238
}
230239
}
@@ -247,7 +256,9 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
247256

248257
if (existing_dbm == NULL) {
249258
apr_sdbm_close(dbm);
259+
#ifdef GLOBAL_COLLECTION_LOCK
250260
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
261+
#endif
251262
dbm = NULL;
252263
}
253264

@@ -310,16 +321,20 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
310321
log_escape(msr->mp, col_name), log_escape_ex(msr->mp, col_key, col_key_len));
311322

312323
apr_sdbm_close(dbm);
313-
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
324+
#ifdef GLOBAL_COLLECTION_LOCK
325+
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
326+
#endif
314327
}
315-
328+
316329
return col;
317330

318331
cleanup:
319332

320333
if ((existing_dbm == NULL) && dbm) {
321334
apr_sdbm_close(dbm);
322-
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
335+
#ifdef GLOBAL_COLLECTION_LOCK
336+
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
337+
#endif
323338
}
324339

325340
return NULL;
@@ -384,13 +399,15 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
384399
log_escape(msr->mp, dbm_filename));
385400
}
386401

402+
#ifdef GLOBAL_COLLECTION_LOCK
387403
/* Need to lock to pull in the stored data again and apply deltas. */
388404
rc = apr_global_mutex_lock(msr->modsecurity->dbm_lock);
389405
if (rc != APR_SUCCESS) {
390406
msr_log(msr, 1, "collection_store: Failed to lock proc mutex: %s",
391407
get_apr_error(msr->mp, rc));
392408
goto error;
393409
}
410+
#endif
394411

395412
/* Delete IS_NEW on store. */
396413
apr_table_unset(col, "IS_NEW");
@@ -439,7 +456,7 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
439456
var->value = apr_psprintf(msr->mp, "%d", counter + 1);
440457
var->value_len = strlen(var->value);
441458
}
442-
459+
443460
/* ENH Make the expiration timestamp accessible in blob form so that
444461
* it is easier/faster to determine expiration without having to
445462
* convert back to table form
@@ -448,13 +465,24 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
448465
rc = apr_sdbm_open(&dbm, dbm_filename, APR_CREATE | APR_WRITE | APR_SHARELOCK,
449466
CREATEMODE, msr->mp);
450467
if (rc != APR_SUCCESS) {
468+
#ifdef GLOBAL_COLLECTION_LOCK
451469
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
470+
#endif
452471
msr_log(msr, 1, "collection_store: Failed to access DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
453472
get_apr_error(msr->mp, rc));
454473
dbm = NULL;
455474
goto error;
456475
}
457-
476+
477+
#ifndef GLOBAL_COLLECTION_LOCK
478+
/* Need to lock to pull in the stored data again and apply deltas. */
479+
rc = apr_sdbm_lock(dbm, APR_FLOCK_EXCLUSIVE);
480+
if (rc != APR_SUCCESS) {
481+
msr_log(msr, 1, "collection_store: Failed to exclusivly lock DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
482+
get_apr_error(msr->mp, rc));
483+
goto error;
484+
}
485+
#endif
458486

459487
/* If there is an original value, then create a delta and
460488
* apply the delta to the current value */
@@ -519,8 +547,13 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
519547
blob = apr_pcalloc(msr->mp, blob_size);
520548
if (blob == NULL) {
521549
if (dbm != NULL) {
550+
#ifdef GLOBAL_COLLECTION_LOCK
522551
apr_sdbm_close(dbm);
523552
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
553+
#else
554+
apr_sdbm_unlock(dbm);
555+
apr_sdbm_close(dbm);
556+
#endif
524557
}
525558

526559
return -1;
@@ -577,16 +610,26 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
577610
msr_log(msr, 1, "collection_store: Failed to write to DBM file \"%s\": %s", dbm_filename,
578611
get_apr_error(msr->mp, rc));
579612
if (dbm != NULL) {
613+
#ifdef GLOBAL_COLLECTION_LOCK
614+
apr_sdbm_close(dbm);
615+
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
616+
#else
617+
apr_sdbm_unlock(dbm);
580618
apr_sdbm_close(dbm);
581-
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
619+
#endif
582620
}
583621

584622
return -1;
585623
}
586624

625+
#ifdef GLOBAL_COLLECTION_LOCK
587626
apr_sdbm_close(dbm);
588627
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
589-
628+
#else
629+
apr_sdbm_unlock(dbm);
630+
apr_sdbm_close(dbm);
631+
#endif
632+
590633
if (msr->txcfg->debuglog_level >= 4) {
591634
msr_log(msr, 4, "collection_store: Persisted collection (name \"%s\", key \"%s\").",
592635
log_escape_ex(msr->mp, var_name->value, var_name->value_len),
@@ -630,17 +673,21 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
630673
log_escape(msr->mp, dbm_filename));
631674
}
632675

676+
#ifdef GLOBAL_COLLECTION_LOCK
633677
rc = apr_global_mutex_lock(msr->modsecurity->dbm_lock);
634678
if (rc != APR_SUCCESS) {
635679
msr_log(msr, 1, "collections_remove_stale: Failed to lock proc mutex: %s",
636680
get_apr_error(msr->mp, rc));
637681
goto error;
638682
}
639-
683+
#endif
684+
640685
rc = apr_sdbm_open(&dbm, dbm_filename, APR_CREATE | APR_WRITE | APR_SHARELOCK,
641686
CREATEMODE, msr->mp);
642687
if (rc != APR_SUCCESS) {
688+
#ifdef GLOBAL_COLLECTION_LOCK
643689
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
690+
#endif
644691
msr_log(msr, 1, "collections_remove_stale: Failed to access DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
645692
get_apr_error(msr->mp, rc));
646693
dbm = NULL;
@@ -650,6 +697,15 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
650697
/* First get a list of all keys. */
651698
keys_arr = apr_array_make(msr->mp, 256, sizeof(char *));
652699

700+
#ifndef GLOBAL_COLLECTION_LOCK
701+
rc = apr_sdbm_lock(dbm, APR_FLOCK_SHARED);
702+
if (rc != APR_SUCCESS) {
703+
msr_log(msr, 1, "collections_remove_stale: Failed to lock DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
704+
get_apr_error(msr->mp, rc));
705+
goto error;
706+
}
707+
#endif
708+
653709
/* No one can write to the file while doing this so
654710
* do it as fast as possible.
655711
*/
@@ -661,6 +717,9 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
661717
}
662718
rc = apr_sdbm_nextkey(dbm, &key);
663719
}
720+
#ifndef GLOBAL_COLLECTION_LOCK
721+
apr_sdbm_unlock(dbm);
722+
#endif
664723

665724
if (msr->txcfg->debuglog_level >= 9) {
666725
msr_log(msr, 9, "collections_remove_stale: Found %d record(s) in file \"%s\".", keys_arr->nelts,
@@ -729,14 +788,18 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
729788
}
730789

731790
apr_sdbm_close(dbm);
791+
#ifdef GLOBAL_COLLECTION_LOCK
732792
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
793+
#endif
733794
return 1;
734795

735796
error:
736797

737798
if (dbm) {
738799
apr_sdbm_close(dbm);
800+
#ifdef GLOBAL_COLLECTION_LOCK
739801
apr_global_mutex_unlock(msr->modsecurity->dbm_lock);
802+
#endif
740803
}
741804

742805
return -1;

configure.ac

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,23 @@ AC_ARG_ENABLE(server-context-logging,
545545
log_server_context=''
546546
])
547547

548+
549+
# Enable collection's global lock
550+
AC_ARG_ENABLE(collection-global-lock,
551+
AS_HELP_STRING([--enable-collection-global-lock],
552+
[Enable collection correctness by using a global lock. May reduce performance significatively. This is disabled by default]),
553+
[
554+
if test "$enableval" != "yes"; then
555+
collection_global_lock=""
556+
else
557+
collection_global_lock="-DGLOBAL_COLLECTION_LOCK"
558+
fi
559+
],
560+
[
561+
collection_global_lock=''
562+
])
563+
564+
548565
# Ignore configure errors
549566
AC_ARG_ENABLE(errors,
550567
AS_HELP_STRING([--disable-errors],
@@ -795,7 +812,7 @@ else
795812
fi
796813
fi
797814

798-
MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $request_early $htaccess_config $lua_cache $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api $cpu_type $unique_id $log_filename $log_server $log_collection_delete_problem $log_dechunk $log_stopwatch $log_handler $log_server_contex"
815+
MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $request_early $htaccess_config $lua_cache $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api $cpu_type $unique_id $log_filename $log_server $log_collection_delete_problem $log_dechunk $log_stopwatch $log_handler $log_server_contex $collection_global_lock"
799816

800817
APXS_WRAPPER=build/apxs-wrapper
801818
APXS_EXTRA_CFLAGS=""

0 commit comments

Comments
 (0)