Commit 16be8273ad for openssl.org

commit 16be8273addbb7c667e9ff12fdb6bf892c43d161
Author: Neil Horman <nhorman@openssl.org>
Date:   Fri Jun 26 13:06:20 2026 -0400

    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 <kurt@roeckx.be>
    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Norbert Pocs <norbertp@openssl.org>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    Reviewed-by: Bob Beck <beck@openssl.org>
    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 b7d4bc549e..dbd55c8b2f 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;
     }
 }