@@ -101,6 +101,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
101101int expired = 0 ;
102102int i ;
103103
104+
104105if (msr -> txcfg -> data_dir == NULL ) {
105106msr_log (msr ,1 ,"collection_retrieve_ex: Unable to retrieve collection (name \"%s\", key \"%s\"). Use "
106107"SecDataDir to define data directory first." ,log_escape (msr -> mp ,col_name ),
@@ -119,10 +120,18 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
119120key .dsize = col_key_len + 1 ;
120121
121122if (existing_dbm == NULL ) {
123+ rc = apr_global_mutex_lock (msr -> modsecurity -> dbm_lock );
124+ if (rc != APR_SUCCESS ) {
125+ msr_log (msr ,1 ,"collection_retrieve_ex: Failed to lock proc mutex: %s" ,
126+ get_apr_error (msr -> mp ,rc ));
127+ gotocleanup ;
128+ }
129+
122130rc = apr_sdbm_open (& dbm ,dbm_filename ,APR_READ |APR_SHARELOCK ,
123131CREATEMODE ,msr -> mp );
124132if (rc != APR_SUCCESS ) {
125133dbm = NULL ;
134+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
126135 gotocleanup ;
127136 }
128137 }
@@ -156,6 +165,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
156165/* Close after "value" used from fetch or memory may be overwritten. */
157166if (existing_dbm == NULL ) {
158167apr_sdbm_close (dbm );
168+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
159169dbm = NULL ;
160170 }
161171
@@ -202,12 +212,19 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
202212 */
203213if (apr_table_get (col ,"KEY" )== NULL ) {
204214if (existing_dbm == NULL ) {
215+ rc = apr_global_mutex_lock (msr -> modsecurity -> dbm_lock );
216+ if (rc != APR_SUCCESS ) {
217+ msr_log (msr ,1 ,"collection_retrieve_ex: Failed to lock proc mutex: %s" ,
218+ get_apr_error (msr -> mp ,rc ));
219+ gotocleanup ;
220+ }
205221rc = apr_sdbm_open (& dbm ,dbm_filename ,APR_CREATE |APR_WRITE |APR_SHARELOCK ,
206222CREATEMODE ,msr -> mp );
207223if (rc != APR_SUCCESS ) {
208224msr_log (msr ,1 ,"collection_retrieve_ex: Failed to access DBM file \"%s\": %s" ,
209225log_escape (msr -> mp ,dbm_filename ),get_apr_error (msr -> mp ,rc ));
210226dbm = NULL ;
227+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
211228 gotocleanup ;
212229 }
213230 }
@@ -230,6 +247,7 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
230247
231248if (existing_dbm == NULL ) {
232249apr_sdbm_close (dbm );
250+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
233251dbm = NULL ;
234252 }
235253
@@ -292,14 +310,16 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
292310log_escape (msr -> mp ,col_name ),log_escape_ex (msr -> mp ,col_key ,col_key_len ));
293311
294312apr_sdbm_close (dbm );
313+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
295314 }
296-
315+
297316return col ;
298317
299318cleanup :
300319
301320if ((existing_dbm == NULL )&& dbm ) {
302321apr_sdbm_close (dbm );
322+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
303323 }
304324
305325return NULL ;
@@ -412,6 +432,14 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
412432var -> value_len = strlen (var -> value );
413433 }
414434
435+ /* Need to lock to pull in the stored data again and apply deltas. */
436+ rc = apr_global_mutex_lock (msr -> modsecurity -> dbm_lock );
437+ if (rc != APR_SUCCESS ) {
438+ msr_log (msr ,1 ,"collection_store: Failed to lock proc mutex: %s" ,
439+ get_apr_error (msr -> mp ,rc ));
440+ gotoerror ;
441+ }
442+
415443/* ENH Make the expiration timestamp accessible in blob form so that
416444 * it is easier/faster to determine expiration without having to
417445 * convert back to table form
@@ -420,19 +448,13 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
420448rc = apr_sdbm_open (& dbm ,dbm_filename ,APR_CREATE |APR_WRITE |APR_SHARELOCK ,
421449CREATEMODE ,msr -> mp );
422450if (rc != APR_SUCCESS ) {
451+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
423452msr_log (msr ,1 ,"collection_store: Failed to access DBM file \"%s\": %s" ,log_escape (msr -> mp ,dbm_filename ),
424453get_apr_error (msr -> mp ,rc ));
425454dbm = NULL ;
426455 gotoerror ;
427456 }
428-
429- /* Need to lock to pull in the stored data again and apply deltas. */
430- rc = apr_sdbm_lock (dbm ,APR_FLOCK_EXCLUSIVE );
431- if (rc != APR_SUCCESS ) {
432- msr_log (msr ,1 ,"collection_store: Failed to exclusivly lock DBM file \"%s\": %s" ,log_escape (msr -> mp ,dbm_filename ),
433- get_apr_error (msr -> mp ,rc ));
434- gotoerror ;
435- }
457+
436458
437459/* If there is an original value, then create a delta and
438460 * apply the delta to the current value */
@@ -497,8 +519,8 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
497519blob = apr_pcalloc (msr -> mp ,blob_size );
498520if (blob == NULL ) {
499521if (dbm != NULL ) {
500- apr_sdbm_unlock (dbm );
501522apr_sdbm_close (dbm );
523+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
502524 }
503525
504526return -1 ;
@@ -555,16 +577,16 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
555577msr_log (msr ,1 ,"collection_store: Failed to write to DBM file \"%s\": %s" ,dbm_filename ,
556578get_apr_error (msr -> mp ,rc ));
557579if (dbm != NULL ) {
558- apr_sdbm_unlock (dbm );
559580apr_sdbm_close (dbm );
581+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
560582 }
561583
562584return -1 ;
563585 }
564586
565- apr_sdbm_unlock (dbm );
566587apr_sdbm_close (dbm );
567-
588+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
589+
568590if (msr -> txcfg -> debuglog_level >=4 ) {
569591msr_log (msr ,4 ,"collection_store: Persisted collection (name \"%s\", key \"%s\")." ,
570592log_escape_ex (msr -> mp ,var_name -> value ,var_name -> value_len ),
@@ -608,9 +630,17 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
608630log_escape (msr -> mp ,dbm_filename ));
609631 }
610632
633+ rc = apr_global_mutex_lock (msr -> modsecurity -> dbm_lock );
634+ if (rc != APR_SUCCESS ) {
635+ msr_log (msr ,1 ,"collections_remove_stale: Failed to lock proc mutex: %s" ,
636+ get_apr_error (msr -> mp ,rc ));
637+ gotoerror ;
638+ }
639+
611640rc = apr_sdbm_open (& dbm ,dbm_filename ,APR_CREATE |APR_WRITE |APR_SHARELOCK ,
612641CREATEMODE ,msr -> mp );
613642if (rc != APR_SUCCESS ) {
643+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
614644msr_log (msr ,1 ,"collections_remove_stale: Failed to access DBM file \"%s\": %s" ,log_escape (msr -> mp ,dbm_filename ),
615645get_apr_error (msr -> mp ,rc ));
616646dbm = NULL ;
@@ -619,12 +649,6 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
619649
620650/* First get a list of all keys. */
621651keys_arr = apr_array_make (msr -> mp ,256 ,sizeof (char * ));
622- rc = apr_sdbm_lock (dbm ,APR_FLOCK_SHARED );
623- if (rc != APR_SUCCESS ) {
624- msr_log (msr ,1 ,"collections_remove_stale: Failed to lock DBM file \"%s\": %s" ,log_escape (msr -> mp ,dbm_filename ),
625- get_apr_error (msr -> mp ,rc ));
626- gotoerror ;
627- }
628652
629653/* No one can write to the file while doing this so
630654 * do it as fast as possible.
@@ -637,7 +661,6 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
637661 }
638662rc = apr_sdbm_nextkey (dbm ,& key );
639663 }
640- apr_sdbm_unlock (dbm );
641664
642665if (msr -> txcfg -> debuglog_level >=9 ) {
643666msr_log (msr ,9 ,"collections_remove_stale: Found %d record(s) in file \"%s\"." ,keys_arr -> nelts ,
@@ -706,13 +729,14 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
706729 }
707730
708731apr_sdbm_close (dbm );
709-
732+ apr_global_mutex_unlock ( msr -> modsecurity -> dbm_lock );
710733return 1 ;
711734
712735error :
713736
714737if (dbm ) {
715738apr_sdbm_close (dbm );
739+ apr_global_mutex_unlock (msr -> modsecurity -> dbm_lock );
716740 }
717741
718742return -1 ;