diff options
author | Matt Caswell <matt@openssl.org> | 2021-04-26 11:35:17 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2021-05-11 14:56:55 +0100 |
commit | a16d21744df686a7c005d1f129915d9083476e14 (patch) | |
tree | 1ea4d25a974b2f7cfcaafe65a03f9557b8ddc780 /crypto/ex_data.c | |
parent | d07af736de592602f2831f8559d0302cb116e190 (diff) |
Add the ability for ex_data to have a priority
Where an object has multiple ex_data associated with it, then we free that
ex_data in order of priority (high priority first).
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14991)
Diffstat (limited to 'crypto/ex_data.c')
-rw-r--r-- | crypto/ex_data.c | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/crypto/ex_data.c b/crypto/ex_data.c index 4a0efbdb18..40223f06e4 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include <stdlib.h> #include "crypto/cryptlib.h" #include "internal/thread_once.h" @@ -141,7 +142,8 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, - CRYPTO_EX_free *free_func) + CRYPTO_EX_free *free_func, + int priority) { int toret = -1; EX_CALLBACK *a; @@ -176,6 +178,7 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, a->new_func = new_func; a->dup_func = dup_func; a->free_func = free_func; + a->priority = priority; if (!sk_EX_CALLBACK_push(ip->meth, NULL)) { ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); @@ -195,7 +198,7 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_free *free_func) { return ossl_crypto_get_ex_new_index_ex(NULL, class_index, argl, argp, - new_func, dup_func, free_func); + new_func, dup_func, free_func, 0); } /* @@ -331,6 +334,27 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, return toret; } +struct ex_callback_entry { + const EX_CALLBACK *excb; + int index; +}; + +static int ex_callback_compare(const void *a, const void *b) +{ + const struct ex_callback_entry *ap = (const struct ex_callback_entry *)a; + const struct ex_callback_entry *bp = (const struct ex_callback_entry *)b; + + if (ap->excb == bp->excb) + return 0; + + if (ap->excb == NULL) + return 1; + if (bp->excb == NULL) + return -1; + if (ap->excb->priority == bp->excb->priority) + return 0; + return ap->excb->priority > bp->excb->priority ? -1 : 1; +} /* * Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for @@ -341,9 +365,9 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) int mx, i; EX_CALLBACKS *ip; void *ptr; - EX_CALLBACK *f; - EX_CALLBACK *stack[10]; - EX_CALLBACK **storage = NULL; + const EX_CALLBACK *f; + struct ex_callback_entry stack[10]; + struct ex_callback_entry *storage = NULL; OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ad->ctx); if (global == NULL) @@ -360,23 +384,23 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) else storage = OPENSSL_malloc(sizeof(*storage) * mx); if (storage != NULL) - for (i = 0; i < mx; i++) - storage[i] = sk_EX_CALLBACK_value(ip->meth, i); + for (i = 0; i < mx; i++) { + storage[i].excb = sk_EX_CALLBACK_value(ip->meth, i); + storage[i].index = i; + } } CRYPTO_THREAD_unlock(global->ex_data_lock); - for (i = 0; i < mx; i++) { - if (storage != NULL) - f = storage[i]; - else { - if (!CRYPTO_THREAD_write_lock(global->ex_data_lock)) - continue; - f = sk_EX_CALLBACK_value(ip->meth, i); - CRYPTO_THREAD_unlock(global->ex_data_lock); - } - if (f != NULL && f->free_func != NULL) { - ptr = CRYPTO_get_ex_data(ad, i); - f->free_func(obj, ptr, ad, i, f->argl, f->argp); + if (storage != NULL) { + /* Sort according to priority. High priority first */ + qsort(storage, mx, sizeof(*storage), ex_callback_compare); + for (i = 0; i < mx; i++) { + f = storage[i].excb; + + if (f != NULL && f->free_func != NULL) { + ptr = CRYPTO_get_ex_data(ad, storage[i].index); + f->free_func(obj, ptr, ad, storage[i].index, f->argl, f->argp); + } } } |