From: Neil Horman Date: Fri, 26 Jun 2026 17:06:20 +0000 (-0400) Subject: Replace use of CRYPTO_GET_REF in bio_lib X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=16be8273addbb7c667e9ff12fdb6bf892c43d161;p=thirdparty%2Fopenssl.git Replace use of CRYPTO_GET_REF in bio_lib BIO_free_all makes use of CRYPTO_GET_REF to determine if there is another user of a BIO chain at some artibrary point within the chain. But CRYPTO_GET_REF is begging for a TOCTOU error, and so we're deprecating it. replace the use of GET_REF with an internal version of BIO_free that returns the value of the resultant ref count, and use that instead, so we are TOCTOU free Reviewed-by: Kurt Roeckx Reviewed-by: Paul Dale Reviewed-by: Norbert Pocs Reviewed-by: Nikola Pajkovsky Reviewed-by: Bob Beck MergeDate: Sat Jul 4 16:47:13 2026 (Merged from https://github.com/openssl/openssl/pull/31750) --- diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index b7d4bc549e8..dbd55c8b2f0 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -116,24 +116,22 @@ BIO *BIO_new(const BIO_METHOD *method) return BIO_new_ex(NULL, method); } -int BIO_free(BIO *a) +static int BIO_free_int(BIO *a, int *ret) { - int ret; if (a == NULL) return 0; - if (CRYPTO_DOWN_REF(&a->references, &ret) <= 0) + if (CRYPTO_DOWN_REF(&a->references, ret) <= 0) return 0; - REF_PRINT_COUNT("BIO", ret, a); - if (ret > 0) + REF_PRINT_COUNT("BIO", *ret, a); + if (*ret > 0) return 1; - REF_ASSERT_ISNT(ret < 0); + REF_ASSERT_ISNT(*ret < 0); if (HAS_CALLBACK(a)) { - ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL); - if (ret <= 0) + if ((int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL) <= 0) return 0; } @@ -149,6 +147,13 @@ int BIO_free(BIO *a) return 1; } +int BIO_free(BIO *b) +{ + int ref; + + return BIO_free_int(b, &ref); +} + void BIO_set_data(BIO *a, void *ptr) { a->ptr = ptr; @@ -874,11 +879,11 @@ void BIO_free_all(BIO *bio) while (bio != NULL) { b = bio; - CRYPTO_GET_REF(&b->references, &ref); bio = bio->next_bio; - BIO_free(b); - /* Since ref count > 1, don't free anyone else. */ - if (ref > 1) + ref = 0; + BIO_free_int(b, &ref); + /* Since ref count > 0, don't free anyone else. */ + if (ref > 0) break; } }