diff options
author | Daiki Ueno <dueno@redhat.com> | 2018-03-22 16:08:16 +0100 |
---|---|---|
committer | Daiki Ueno <dueno@redhat.com> | 2018-03-22 16:08:16 +0100 |
commit | 52eb56eb27de1abf8e871ea5e35bd97fefbed1a3 (patch) | |
tree | 4eeeeba4cf2982971d04ce28932d107073bc3be5 /lib | |
parent | 9eb3bed595dbd8e39f8dd3c88a2136cea29b01ce (diff) | |
download | nss-hg-52eb56eb27de1abf8e871ea5e35bd97fefbed1a3.tar.gz |
Bug 1447628, devslot: avoid deadlock when re-inserting a token, r=rrelyea
Diffstat (limited to 'lib')
-rw-r--r-- | lib/dev/devslot.c | 18 | ||||
-rw-r--r-- | lib/dev/devt.h | 2 | ||||
-rw-r--r-- | lib/pk11wrap/dev3hack.c | 2 |
3 files changed, 14 insertions, 8 deletions
diff --git a/lib/dev/devslot.c b/lib/dev/devslot.c index 2b19e3f90..ef941f9ed 100644 --- a/lib/dev/devslot.c +++ b/lib/dev/devslot.c @@ -96,10 +96,16 @@ nssSlot_ResetDelay( } static PRBool -within_token_delay_period(const NSSSlot *slot) +token_status_checked(const NSSSlot *slot) { PRIntervalTime time; int lastPingState = slot->lastTokenPingState; + /* When called from the same thread, that means + * nssSlot_IsTokenPresent() is called recursively through + * nssSlot_Refresh(). Return immediately in that case. */ + if (slot->isPresentThread == PR_GetCurrentThread()) { + return PR_TRUE; + } /* Set the delay time for checking the token presence */ if (s_token_delay_time == 0) { s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME); @@ -130,7 +136,7 @@ nssSlot_IsTokenPresent( /* avoid repeated calls to check token status within set interval */ PZ_Lock(slot->isPresentLock); - if (within_token_delay_period(slot)) { + if (token_status_checked(slot)) { CK_FLAGS ckFlags = slot->ckFlags; PZ_Unlock(slot->isPresentLock); return ((ckFlags & CKF_TOKEN_PRESENT) != 0); @@ -146,12 +152,12 @@ nssSlot_IsTokenPresent( /* set up condition so only one thread is active in this part of the code at a time */ PZ_Lock(slot->isPresentLock); - while (slot->inIsPresent) { + while (slot->isPresentThread) { PR_WaitCondVar(slot->isPresentCondition, 0); } /* if we were one of multiple threads here, the first thread will have * given us the answer, no need to make more queries of the token. */ - if (within_token_delay_period(slot)) { + if (token_status_checked(slot)) { CK_FLAGS ckFlags = slot->ckFlags; PZ_Unlock(slot->isPresentLock); return ((ckFlags & CKF_TOKEN_PRESENT) != 0); @@ -159,7 +165,7 @@ nssSlot_IsTokenPresent( /* this is the winning thread, block all others until we've determined * if the token is present and that it needs initialization. */ slot->lastTokenPingState = nssSlotLastPingState_Update; - slot->inIsPresent = PR_TRUE; + slot->isPresentThread = PR_GetCurrentThread(); PZ_Unlock(slot->isPresentLock); @@ -257,7 +263,7 @@ done: slot->lastTokenPingTime = PR_IntervalNow(); slot->lastTokenPingState = nssSlotLastPingState_Valid; } - slot->inIsPresent = PR_FALSE; + slot->isPresentThread = NULL; PR_NotifyAllCondVar(slot->isPresentCondition); PZ_Unlock(slot->isPresentLock); return isPresent; diff --git a/lib/dev/devt.h b/lib/dev/devt.h index 268cc9e07..0f6d9e49a 100644 --- a/lib/dev/devt.h +++ b/lib/dev/devt.h @@ -92,7 +92,7 @@ struct NSSSlotStr { PK11SlotInfo *pk11slot; PZLock *isPresentLock; PRCondVar *isPresentCondition; - PRBool inIsPresent; + PRThread *isPresentThread; }; struct nssSessionStr { diff --git a/lib/pk11wrap/dev3hack.c b/lib/pk11wrap/dev3hack.c index b272e4564..3fb0cb0aa 100644 --- a/lib/pk11wrap/dev3hack.c +++ b/lib/pk11wrap/dev3hack.c @@ -122,7 +122,7 @@ nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock; rvSlot->isPresentLock = PZ_NewLock(nssiLockOther); rvSlot->isPresentCondition = PR_NewCondVar(rvSlot->isPresentLock); - rvSlot->inIsPresent = PR_FALSE; + rvSlot->isPresentThread = NULL; rvSlot->lastTokenPingState = nssSlotLastPingState_Reset; return rvSlot; } |