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,