From: Neil Horman Date: Sun, 26 Jul 2026 02:23:25 +0000 (-0400) Subject: oqs noted a double free recently: X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=77f492f29f882e07d57e16920138d991dc9af018;p=thirdparty%2Fopenssl.git oqs noted a double free recently: https://github.com/open-quantum-safe/oqs-provider/pull/805#issuecomment-5034437500 Its happening because, recently we made some fixes to account for providers that request no-caching fetches, which all seems to work reasonably well. Except for the corner case oqs recently exposed, in which the provider may request the caching of some algorithms, but not others. When this occurs, the core libcrypto creates a temporary store for those requested, but stored the cachable ones in the libctx store. inner_evp_generic_fetch treats the presence of an allocated tmp store as implying that all algorithms fetched are non-cacheable, even if some are. The result is that, for those cacheable items, they also get treated as non-cacheable, missing the extra ref count taken when they are added to the method store cache. As a result, they get freed while still in use, and you get the issue referenced above. Instead of assuming that a tmp_store means all algorithms are non-cacheable, instead, try to look the method up in the tmp_store cache, and cache it if its not found (i.e. its not in the temp store) Fixes https://github.com/open-quantum-safe/oqs-provider/pull/805 Reviewed-by: Saša Nedvědický Reviewed-by: Andrew Dinh MergeDate: Sat Aug 1 14:30:49 2026 (Merged from https://github.com/openssl/openssl/pull/32077) --- diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index 15204628db9..15478f91517 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -274,6 +274,9 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, uint32_t meth_id = 0; void *method = NULL; int unsupported, name_id; + int set_in_cache = 1; + void *tmp_method; + const OSSL_PROVIDER *tmp_prov = prov; if (store == NULL || namemap == NULL) { ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT); @@ -364,7 +367,34 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, * cached end up in ->tmp_store when provider asks not * to cache the result (see ossl_method_construct_reserve_store()) */ - if (meth_id != 0 && methdata->tmp_store == NULL) { + if (meth_id != 0) { + /* + * If the method doesn't exist in the tmp_store, either the tmp_store doesn't exist + * or the algorithm doesn't exist there, in either case, this is a cacheable entry + */ + if (!ossl_method_store_fetch(methdata->tmp_store, meth_id, propq, &tmp_prov, &tmp_method)) { + set_in_cache = 1; + } else { + /* + * We found a matching method in the temp store, don't cache this entry + */ + if (tmp_method == method) { + set_in_cache = 0; + } else { + set_in_cache = 1; + } + +#ifdef OPENSSL_NO_CACHED_FETCH + /* + * ossl_method_store_fetch takes a reference on the fetched method + * when using NO_CACHED_FETCH, so we need to free it here + */ + free_method(tmp_method); +#endif + } + } + + if (set_in_cache == 1) { ossl_method_store_cache_set(store, prov, meth_id, propq, method, up_ref_method, free_method); } else {