X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fex_data.c;h=6984a1fb2ef232aba3c71a63d56711087b6c815a;hp=5bf8e1e5cd8a8edf975fe00d170ddff55e933fed;hb=de7058241083e9ec80c4ad27e7bb4f2bd79e36f2;hpb=e6390acac925f952cfd06ccdbba0b273b8f71551 diff --git a/crypto/ex_data.c b/crypto/ex_data.c index 5bf8e1e5cd..6984a1fb2e 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -109,23 +109,20 @@ */ #include "internal/cryptlib.h" +#include "internal/threads.h" #include - - /* * Each structure type (sometimes called a class), that supports * exdata has a stack of callbacks for each instance. */ -typedef struct ex_callback_st { - long argl; /* Arbitary long */ - void *argp; /* Arbitary void * */ +struct ex_callback_st { + long argl; /* Arbitrary long */ + void *argp; /* Arbitrary void * */ CRYPTO_EX_new *new_func; CRYPTO_EX_free *free_func; CRYPTO_EX_dup *dup_func; -} EX_CALLBACK; - -DECLARE_STACK_OF(EX_CALLBACK) +}; /* * The state for each class. This could just be a typedef, but @@ -137,6 +134,16 @@ typedef struct ex_callbacks_st { static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT]; +static CRYPTO_RWLOCK *ex_data_lock; +static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT; + +static void do_ex_data_init(void) +{ + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + ex_data_lock = CRYPTO_THREAD_lock_new(); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); +} + /* * Return the EX_CALLBACKS from the |ex_data| array that corresponds to * a given class. On success, *holds the lock.* @@ -146,23 +153,14 @@ static EX_CALLBACKS *get_and_lock(int class_index) EX_CALLBACKS *ip; if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) { - CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE); + CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; } + CRYPTO_THREAD_run_once(&ex_data_init, do_ex_data_init); + ip = &ex_data[class_index]; - CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); - if (ip->meth == NULL) { - ip->meth = sk_EX_CALLBACK_new_null(); - /* We push an initial value on the stack because the SSL - * "app_data" routines use ex_data index zero. See RT 3710. */ - if (ip->meth == NULL - || !sk_EX_CALLBACK_push(ip->meth, NULL)) { - CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE); - CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); - return NULL; - } - } + CRYPTO_THREAD_write_lock(ex_data_lock); return ip; } @@ -229,7 +227,7 @@ int CRYPTO_free_ex_index(int class_index, int idx) a->free_func = dummy_free; toret = 1; err: - CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + CRYPTO_THREAD_unlock(ex_data_lock); return toret; } @@ -246,6 +244,18 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, if (ip == NULL) return -1; + + if (ip->meth == NULL) { + ip->meth = sk_EX_CALLBACK_new_null(); + /* We push an initial value on the stack because the SSL + * "app_data" routines use ex_data index zero. See RT 3710. */ + if (ip->meth == NULL + || !sk_EX_CALLBACK_push(ip->meth, NULL)) { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE); + goto err; + } + } + a = (EX_CALLBACK *)OPENSSL_malloc(sizeof(*a)); if (a == NULL) { CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE); @@ -266,7 +276,7 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, (void)sk_EX_CALLBACK_set(ip->meth, toret, a); err: - CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + CRYPTO_THREAD_unlock(ex_data_lock); return toret; } @@ -300,7 +310,7 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) for (i = 0; i < mx; i++) storage[i] = sk_EX_CALLBACK_value(ip->meth, i); } - CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + CRYPTO_THREAD_unlock(ex_data_lock); if (mx > 0 && storage == NULL) { CRYPTOerr(CRYPTO_F_CRYPTO_NEW_EX_DATA, ERR_R_MALLOC_FAILURE); @@ -350,7 +360,7 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, for (i = 0; i < mx; i++) storage[i] = sk_EX_CALLBACK_value(ip->meth, i); } - CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + CRYPTO_THREAD_unlock(ex_data_lock); if (mx > 0 && storage == NULL) { CRYPTOerr(CRYPTO_F_CRYPTO_DUP_EX_DATA, ERR_R_MALLOC_FAILURE); @@ -395,7 +405,7 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) for (i = 0; i < mx; i++) storage[i] = sk_EX_CALLBACK_value(ip->meth, i); } - CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + CRYPTO_THREAD_unlock(ex_data_lock); if (mx > 0 && storage == NULL) { CRYPTOerr(CRYPTO_F_CRYPTO_FREE_EX_DATA, ERR_R_MALLOC_FAILURE);