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>
Tue, 7 Aug 2018 07:08:31 +0000 (09:08 +0200)
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6786)

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

index 124cc533bc562c6258cf842513d876dbcb7b7e8a..1638de4c32556467a9242deb70beac4f545fd39a 100644 (file)
@@ -182,6 +182,7 @@ struct x509_st {
     unsigned char sha1_hash[SHA_DIGEST_LENGTH];
     X509_CERT_AUX *aux;
     CRYPTO_RWLOCK *lock;
+    volatile int ex_cached;
 } /* X509 */ ;
 
 /*
index d804106788e3748c32fe1cad4f5a0473814feecc..5a535e2adeb6f39f9202f2770bc9a4b15a09bece 100644 (file)
@@ -13,6 +13,7 @@
 #include <openssl/x509v3.h>
 #include <openssl/x509_vfy.h>
 #include "internal/x509_int.h"
+#include "internal/tsan_assist.h"
 
 static void x509v3_cache_extensions(X509 *x);
 
@@ -353,6 +354,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 (tsan_load((TSAN_QUALIFIER int *)&x->ex_cached))
+        return;
+
     CRYPTO_THREAD_write_lock(x->lock);
     if (x->ex_flags & EXFLAG_SET) {
         CRYPTO_THREAD_unlock(x->lock);
@@ -494,6 +499,12 @@ static void x509v3_cache_extensions(X509 *x)
     x509_init_sig_info(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.
+     */
+    tsan_store((TSAN_QUALIFIER int *)&x->ex_cached, 1);
 }
 
 /*-