diff -up nss/lib/pki/tdcache.c.fix_deadlock nss/lib/pki/tdcache.c
--- nss/lib/pki/tdcache.c.fix_deadlock 2017-01-13 17:10:36.055530248 +0100
+++ nss/lib/pki/tdcache.c 2017-01-13 17:14:04.015338438 +0100
@@ -374,13 +374,19 @@ struct token_cert_dtor {
PRUint32 numCerts, arrSize;
};
-static void
-remove_token_certs(const void *k, void *v, void *a)
+static void cert_iter(const void *k, void *v, void *a)
{
+ nssList *certList = (nssList *)a;
NSSCertificate *c = (NSSCertificate *)k;
+ nssList_Add(certList, nssCertificate_AddRef(c));
+}
+
+static void
+remove_token_certs(NSSCertificate *c, struct token_cert_dtor *dtor)
+{
nssPKIObject *object = &c->object;
- struct token_cert_dtor *dtor = a;
PRUint32 i;
+
nssPKIObject_AddRef(object);
nssPKIObject_Lock(object);
for (i = 0; i < object->numInstances; i++) {
@@ -416,6 +422,11 @@ nssTrustDomain_RemoveTokenCertsFromCache
NSSCertificate **certs;
PRUint32 i, arrSize = 10;
struct token_cert_dtor dtor;
+ nssList *certList;
+ PRStatus nspr_rv = PR_FAILURE;
+ nssListIterator *iter;
+ NSSCertificate *c;
+
certs = nss_ZNEWARRAY(NULL, NSSCertificate *, arrSize);
if (!certs) {
return PR_FAILURE;
@@ -425,8 +436,33 @@ nssTrustDomain_RemoveTokenCertsFromCache
dtor.certs = certs;
dtor.numCerts = 0;
dtor.arrSize = arrSize;
+
+ certList = nssList_Create(NULL, PR_FALSE);
+ if (!certList) {
+ goto loser;
+ }
+ /* fetch the list of certs in the cache */
+ PZ_Lock(td->cache->lock);
+ nssHash_Iterate(td->cache->issuerAndSN, cert_iter, (void *)certList);
+ PZ_Unlock(td->cache->lock);
+
+ /* find the certs that match this token without olding the td cache lock */
+ iter=nssList_CreateIterator(certList);
+ if (!iter) {
+ goto loser;
+ }
+ for (c = (NSSCertificate *)nssListIterator_Start(iter);
+ c != (NSSCertificate *)NULL;
+ c = (NSSCertificate *)nssListIterator_Next(iter)) {
+ remove_token_certs( c, &dtor);
+ }
+ nssListIterator_Finish(iter);
+ nssListIterator_Destroy(iter);
+ nssList_Destroy(certList);
+ certList = NULL;
+
+ /* now remove theose certs attached to this token */
PZ_Lock(td->cache->lock);
- nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, &dtor);
for (i = 0; i < dtor.numCerts; i++) {
if (dtor.certs[i]->object.numInstances == 0) {
nssTrustDomain_RemoveCertFromCacheLOCKED(td, dtor.certs[i]);
@@ -437,14 +473,22 @@ nssTrustDomain_RemoveTokenCertsFromCache
}
}
PZ_Unlock(td->cache->lock);
+
+ /* clean up */
for (i = 0; i < dtor.numCerts; i++) {
if (dtor.certs[i]) {
STAN_ForceCERTCertificateUpdate(dtor.certs[i]);
nssCertificate_Destroy(dtor.certs[i]);
}
}
+
+ nspr_rv = PR_SUCCESS;
+loser:
+ if (certList) {
+ nssList_Destroy(certList);
+ }
nss_ZFreeIf(dtor.certs);
- return PR_SUCCESS;
+ return nspr_rv;
}
NSS_IMPLEMENT PRStatus
@@ -1058,14 +1102,6 @@ nssTrustDomain_GetCertByDERFromCache(
return rvCert;
}
-static void
-cert_iter(const void *k, void *v, void *a)
-{
- nssList *certList = (nssList *)a;
- NSSCertificate *c = (NSSCertificate *)k;
- nssList_Add(certList, nssCertificate_AddRef(c));
-}
-
NSS_EXTERN NSSCertificate **
nssTrustDomain_GetCertsFromCache(
NSSTrustDomain *td,