Changeset c005645 in mod_gnutls for src


Ignore:
Timestamp:
Jun 8, 2016, 3:31:29 PM (3 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
debian/master, debian/stretch-backports, master, upstream
Children:
c55902b
Parents:
eb63377
Message:

Mutex for DBM cache access

I noticed that with a DBM cache enabled and session tickets disabled
even a handful of parallel connections trashed the cache database, and
consequently the error log. According to comments and documentation on
mod_socache_dbm the APR DBM module is not thread or multi-process
safe, so a global mutex is necessary. With the mutex the cache
corruption disappears in my benchmarks.

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_cache.c

    reb63377 rc005645  
    2929
    3030#include "ap_mpm.h"
     31#include <util_mutex.h>
    3132
    3233#include <unistd.h>
     
    3637#include "unixd.h"
    3738#endif
     39
     40/* default cache timeout */
     41#define MGS_DEFAULT_CACHE_TIMEOUT 300
    3842
    3943/* it seems the default has some strange errors. Use SDBM
     
    354358    deleted = 0;
    355359
     360    apr_global_mutex_lock(sc->cache_mutex);
     361
    356362    rv = apr_dbm_open_ex(&dbm, db_type(sc),
    357363            sc->cache_config, APR_DBM_RWCREATE,
     
    359365    if (rv != APR_SUCCESS) {
    360366        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s,
    361                 "[gnutls_cache] error opening cache searcher '%s'",
     367                "[gnutls_cache] error opening cache '%s'",
    362368                sc->cache_config);
     369        apr_global_mutex_unlock(sc->cache_mutex);
    363370        apr_pool_destroy(spool);
    364371        return;
     
    386393    apr_dbm_close(dbm);
    387394
     395    rv = apr_global_mutex_unlock(sc->cache_mutex);
     396
    388397    ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
    389398            "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d",
     
    403412    apr_status_t rv;
    404413
     414    apr_global_mutex_lock(ctxt->sc->cache_mutex);
     415
    405416    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
    406417            ctxt->sc->cache_config, APR_DBM_READONLY,
     
    410421                      "error opening cache '%s'",
    411422                      ctxt->sc->cache_config);
     423        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    412424        return data;
    413425    }
     
    417429    if (rv != APR_SUCCESS) {
    418430        apr_dbm_close(dbm);
     431        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    419432        return data;
    420433    }
     
    423436        apr_dbm_freedatum(dbm, dbmval);
    424437        apr_dbm_close(dbm);
     438        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    425439        return data;
    426440    }
     
    432446        apr_dbm_freedatum(dbm, dbmval);
    433447        apr_dbm_close(dbm);
     448        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    434449        return data;
    435450    }
     
    443458    apr_dbm_freedatum(dbm, dbmval);
    444459    apr_dbm_close(dbm);
     460    apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    445461
    446462    return data;
     
    484500    memcpy((char *) dbmval.dptr + sizeof (apr_time_t),
    485501            data.data, data.size);
     502
     503    apr_global_mutex_lock(sc->cache_mutex);
    486504
    487505    rv = apr_dbm_open_ex(&dbm, db_type(sc),
     
    493511                     "error opening cache '%s'",
    494512                     sc->cache_config);
     513        apr_global_mutex_unlock(sc->cache_mutex);
    495514        apr_pool_destroy(spool);
    496515        return -1;
     
    504523                     sc->cache_config);
    505524        apr_dbm_close(dbm);
     525        apr_global_mutex_unlock(sc->cache_mutex);
    506526        apr_pool_destroy(spool);
    507527        return -1;
    508528    }
     529
     530    apr_dbm_close(dbm);
     531    apr_global_mutex_unlock(sc->cache_mutex);
    509532
    510533    ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
    511534                 "stored %ld bytes of data (%ld byte key) in cache '%s'",
    512535                 dbmval.dsize, dbmkey.dsize, sc->cache_config);
    513 
    514     apr_dbm_close(dbm);
    515536
    516537    apr_pool_destroy(spool);
     
    543564    apr_datum_t dbmkey = {(char*) tmpkey.data, tmpkey.size};
    544565
     566    apr_global_mutex_lock(ctxt->sc->cache_mutex);
     567
    545568    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
    546569            ctxt->sc->cache_config, APR_DBM_RWCREATE,
     
    551574                "[gnutls_cache] error opening cache '%s'",
    552575                ctxt->sc->cache_config);
     576        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    553577        return -1;
    554578    }
     
    562586                ctxt->sc->cache_config);
    563587        apr_dbm_close(dbm);
     588        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    564589        return -1;
    565590    }
    566591
    567592    apr_dbm_close(dbm);
     593    apr_global_mutex_unlock(ctxt->sc->cache_mutex);
    568594
    569595    return 0;
     
    620646    /* if GnuTLSCacheTimeout was never explicitly set: */
    621647    if (sc->cache_timeout == -1)
    622         sc->cache_timeout = apr_time_from_sec(300);
     648        sc->cache_timeout = apr_time_from_sec(MGS_DEFAULT_CACHE_TIMEOUT);
     649
     650    /* initialize mutex only once */
     651    if (sc->cache_mutex == NULL)
     652    {
     653        apr_status_t rv = ap_global_mutex_create(&sc->cache_mutex, NULL,
     654                                                 MGS_CACHE_MUTEX_NAME,
     655                                                 NULL, s, p, 0);
     656        if (rv != APR_SUCCESS)
     657            return rv;
     658    }
    623659
    624660    if (sc->cache_type == mgs_cache_dbm
     
    626662        return dbm_cache_post_config(p, s, sc);
    627663    }
    628     return 0;
     664
     665    return APR_SUCCESS;
    629666}
    630667
  • src/gnutls_cache.h

    reb63377 rc005645  
    2323#include "mod_gnutls.h"
    2424#include <httpd.h>
     25
     26#define MGS_CACHE_MUTEX_NAME "gnutls-cache"
    2527
    2628/**
  • src/gnutls_config.c

    reb63377 rc005645  
    958958    sc->cache_type = mgs_cache_unset;
    959959    sc->cache_config = NULL;
     960    sc->cache_mutex = NULL;
    960961    sc->tickets = GNUTLS_ENABLED_UNSET;
    961962    sc->priorities = NULL;
  • src/gnutls_hooks.c

    reb63377 rc005645  
    2626#include "ap_mpm.h"
    2727#include "mod_status.h"
     28#include <util_mutex.h>
    2829
    2930#ifdef ENABLE_MSVA
     
    124125    AP_OPTIONAL_HOOK(status_hook, mgs_status_hook, NULL, NULL, APR_HOOK_MIDDLE);
    125126
    126         /* Register a pool clean-up function */
     127    ap_mutex_register(pconf, MGS_CACHE_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0);
     128
     129    /* Register a pool clean-up function */
    127130    apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, apr_pool_cleanup_null);
    128131
     
    331334
    332335    rv = mgs_cache_post_config(pconf, s, sc_base);
    333     if (rv != 0) {
     336    if (rv != APR_SUCCESS)
     337    {
    334338        ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s,
    335                 "GnuTLS: Post Config for GnuTLSCache Failed."
    336                 " Shutting Down.");
     339                     "Post config for cache failed.");
    337340        return HTTP_INSUFFICIENT_STORAGE;
    338341    }
     
    371374        sc->cache_config = sc_base->cache_config;
    372375        sc->cache_timeout = sc_base->cache_timeout;
     376        sc->cache_mutex = sc_base->cache_mutex;
    373377
    374378        rv = mgs_load_files(pconf, s);
     
    495499}
    496500
    497 void mgs_hook_child_init(apr_pool_t * p, server_rec *s) {
     501void mgs_hook_child_init(apr_pool_t *p, server_rec *s)
     502{
    498503    apr_status_t rv = APR_SUCCESS;
    499     mgs_srvconf_rec *sc =
    500         (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
     504    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     505        ap_get_module_config(s->module_config, &gnutls_module);
    501506
    502507    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
     508
    503509    /* if we use PKCS #11 reinitialize it */
    504 
    505510    if (mgs_pkcs11_reinit(s) < 0) {
    506511            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
     
    516521        }
    517522    }
     523
     524    /* reinit cache mutex */
     525    if (sc->cache_mutex != NULL)
     526    {
     527        const char *lockfile = apr_global_mutex_lockfile(sc->cache_mutex);
     528        rv = apr_global_mutex_child_init(&sc->cache_mutex, lockfile, p);
     529        if (rv != APR_SUCCESS)
     530            ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
     531                         "Failed to reinit mutex '%s'", MGS_CACHE_MUTEX_NAME);
     532    }
     533
    518534    /* Block SIGPIPE Signals */
    519535    rv = apr_signal_block(SIGPIPE);
Note: See TracChangeset for help on using the changeset viewer.