]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Replace use of CRYPTO_GET_REF in bio_lib
authorNeil Horman <nhorman@openssl.org>
Fri, 26 Jun 2026 17:06:20 +0000 (13:06 -0400)
committerNeil Horman <nhorman@openssl.org>
Sat, 4 Jul 2026 16:47:07 +0000 (12:47 -0400)
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)

crypto/bio/bio_lib.c

index b7d4bc549e88363499611499529b2904347916bb..dbd55c8b2f0aae03014a3288a346f2f94a8ca01f 100644 (file)
@@ -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;
     }
 }