x509v3/v3_purp.c: re-implement lock-free check for extensions cache validity.
authorAndy Polyakov <appro@openssl.org>
Sun, 29 Jul 2018 12:37:17 +0000 (14:37 +0200)
committerAndy Polyakov <appro@openssl.org>
Fri, 10 Aug 2018 19:53:05 +0000 (21:53 +0200)
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6891)

(back-ported from commit f21b5b64cbbc279ef31389e6ae312690575187da)

crypto/include/internal/x509_int.h
crypto/x509v3/v3_purp.c

index 2845026dd82f0b028bbabaa5912c6094b9099e7c..9a6322c0c7aacd8d607ef39fa2c2264bb92465cd 100644 (file)
@@ -166,6 +166,7 @@ struct x509_st {
     unsigned char sha1_hash[SHA_DIGEST_LENGTH];
     X509_CERT_AUX *aux;
     CRYPTO_RWLOCK *lock;
+    volatile int ex_cached;
 } /* X509 */ ;
 
 /*
index 47ca7da5ec8998b12662dc0aac1c1226d32647a4..7ac067229fbb7de21a90cb9b5dbc73ba3600a17b 100644 (file)
@@ -352,6 +352,10 @@ static void x509v3_cache_extensions(X509 *x)
     X509_EXTENSION *ex;
     int i;
 
+    /* fast lock-free check, see end of the function for details. */
+    if (x->ex_cached)
+        return;
+
     CRYPTO_THREAD_write_lock(x->lock);
     if (x->ex_flags & EXFLAG_SET) {
         CRYPTO_THREAD_unlock(x->lock);
@@ -492,6 +496,12 @@ static void x509v3_cache_extensions(X509 *x)
     }
     x->ex_flags |= EXFLAG_SET;
     CRYPTO_THREAD_unlock(x->lock);
+    /*
+     * It has to be placed after memory barrier, which is implied by unlock.
+     * Worst thing that can happen is that another thread proceeds to lock
+     * and checks x->ex_flags & EXFLAGS_SET. See beginning of the function.
+     */
+    x->ex_cached = 1;
 }
 
 /*-