diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | dbd/apr_dbd.c | 11 | ||||
-rw-r--r-- | dbm/apr_dbm.c | 13 | ||||
-rw-r--r-- | util-misc/apu_dso.c | 11 |
4 files changed, 34 insertions, 4 deletions
@@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes for APR 2.0.0 + *) Fix race conditions in initialisation of DBD, DBM and DSO. + [Bojan Smojver] + *) SECURITY: CVE-2009-0023 (cve.mitre.org) Fix underflow in apr_strmatch_precompile. [Matthew Palmer <mpalmer debian.org>] diff --git a/dbd/apr_dbd.c b/dbd/apr_dbd.c index 05ee604f9..c9496b2cd 100644 --- a/dbd/apr_dbd.c +++ b/dbd/apr_dbd.c @@ -26,6 +26,7 @@ #include "apr_hash.h" #include "apr_thread_mutex.h" #include "apr_lib.h" +#include "apr_atomic.h" #include "apu_internal.h" #include "apr_dbd_internal.h" @@ -33,6 +34,7 @@ #include "apu_version.h" static apr_hash_t *drivers = NULL; +static apr_uint32_t initialised = 0, in_init = 1; #define CLEANUP_CAST (apr_status_t (*)(void*)) @@ -90,7 +92,12 @@ APU_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool) apr_status_t ret = APR_SUCCESS; apr_pool_t *parent; - if (drivers != NULL) { + if (apr_atomic_inc32(&initialised)) { + apr_atomic_set32(&initialised, 1); /* prevent wrap-around */ + + while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */ + ; + return APR_SUCCESS; } @@ -141,6 +148,8 @@ APU_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool) apr_pool_cleanup_register(pool, NULL, apr_dbd_term, apr_pool_cleanup_null); + apr_atomic_dec32(&in_init); + return ret; } diff --git a/dbm/apr_dbm.c b/dbm/apr_dbm.c index 8484fa0c1..bbe937d81 100644 --- a/dbm/apr_dbm.c +++ b/dbm/apr_dbm.c @@ -24,6 +24,7 @@ #define APR_WANT_STRFUNC #include "apr_want.h" #include "apr_general.h" +#include "apr_atomic.h" #include "apu_config.h" #include "apu.h" @@ -59,6 +60,7 @@ #if APR_HAVE_MODULAR_DSO static apr_hash_t *drivers = NULL; +static apr_uint32_t initialised = 0, in_init = 1; static apr_status_t dbm_term(void *ptr) { @@ -117,8 +119,13 @@ static apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable, } else usertype = 1; - if (!drivers) - { + if (apr_atomic_inc32(&initialised)) { + apr_atomic_set32(&initialised, 1); /* prevent wrap-around */ + + while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */ + ; + } + else { apr_pool_t *parent; /* Top level pool scope, need process-scope lifetime */ @@ -133,6 +140,8 @@ static apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable, apr_pool_cleanup_register(pool, NULL, dbm_term, apr_pool_cleanup_null); + + apr_atomic_dec32(&in_init); } rv = apu_dso_mutex_lock(); diff --git a/util-misc/apu_dso.c b/util-misc/apu_dso.c index 0a7a26ca2..d543b46d2 100644 --- a/util-misc/apu_dso.c +++ b/util-misc/apu_dso.c @@ -27,6 +27,7 @@ #include "apr_hash.h" #include "apr_file_io.h" #include "apr_env.h" +#include "apr_atomic.h" #include "apu_internal.h" #include "apu_version.h" @@ -37,6 +38,7 @@ static apr_thread_mutex_t* mutex = NULL; #endif static apr_hash_t *dsos = NULL; +static apr_uint32_t initialised = 0, in_init = 1; #if APR_HAS_THREADS apr_status_t apu_dso_mutex_lock() @@ -76,7 +78,12 @@ apr_status_t apu_dso_init(apr_pool_t *pool) apr_pool_t *global; apr_pool_t *parent; - if (dsos != NULL) { + if (apr_atomic_inc32(&initialised)) { + apr_atomic_set32(&initialised, 1); /* prevent wrap-around */ + + while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */ + ; + return APR_SUCCESS; } @@ -94,6 +101,8 @@ apr_status_t apu_dso_init(apr_pool_t *pool) apr_pool_cleanup_register(global, NULL, apu_dso_term, apr_pool_cleanup_null); + apr_atomic_dec32(&in_init); + return ret; } |