summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorian.mcgreer%sun.com <devnull@localhost>2002-02-15 01:10:07 +0000
committerian.mcgreer%sun.com <devnull@localhost>2002-02-15 01:10:07 +0000
commit1afdd9d0ceedd2baea95a9e439bbfc7835c8c791 (patch)
tree2f10e173410fafac66d5acad3e4a09db7be532a4
parent956e715009e33d4598ea9fea6ebefdd1849638b1 (diff)
downloadnss-hg-1afdd9d0ceedd2baea95a9e439bbfc7835c8c791.tar.gz
bug 125263, race condition destroying temp certs
-rw-r--r--security/nss/lib/pki/pkistore.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/security/nss/lib/pki/pkistore.c b/security/nss/lib/pki/pkistore.c
index f3d130ac9..d2568a875 100644
--- a/security/nss/lib/pki/pkistore.c
+++ b/security/nss/lib/pki/pkistore.c
@@ -322,6 +322,32 @@ nssCertificateStore_Remove
{
certificate_hash_entry *entry;
PZ_Lock(store->lock);
+#ifdef NSS_3_4_CODE
+ if (cert->object.refCount > 2) {
+ /* This continues the hack described in CERT_DestroyCertificate.
+ * Because NSS 3.4 maintains a single, global, crypto context,
+ * certs must be explicitly removed from it when there are no
+ * more references to them. This is done by destroying the cert
+ * when there are two references left, the one being destroyed,
+ * and the one here (read: temp db).
+ * However, there is a race condition with timing the removal
+ * of the cert from the temp store and deleting the last
+ * reference. In CERT_DestroyCertificate, the refCount is checked,
+ * and if it is two, a call is made here to remove the temp cert.
+ * But by the time it gets here (and within the safety of the
+ * store's lock), another thread could have grabbed a reference
+ * to it. Removing it now will wreak havoc.
+ * Therefore, it is necessary to check the refCount again,
+ * after obtaining the store's lock, to make sure the cert is
+ * actually ready to be deleted. This check is safe, because
+ * within the store's lock a cert that has only two references
+ * *must* have one in the store, and the one being deleted.
+ * See bug 125263.
+ */
+ PZ_Unlock(store->lock);
+ return;
+ }
+#endif
entry = (certificate_hash_entry *)
nssHash_Lookup(store->issuer_and_serial, cert);
if (entry && entry->cert == cert) {