diff options
author | Robert Relyea <rrelyea@redhat.com> | 2018-02-14 17:34:27 -0800 |
---|---|---|
committer | Robert Relyea <rrelyea@redhat.com> | 2018-02-14 17:34:27 -0800 |
commit | ebd0d8a7f9b80479a8bf69a41be8626517b3be63 (patch) | |
tree | f8cb79eabf1bd9ad895b87f305fd6dcc4f6766d1 /lib/dev | |
parent | 630d2990d3883722f59aa65c79f13ca1edf5af30 (diff) | |
download | nss-hg-ebd0d8a7f9b80479a8bf69a41be8626517b3be63.tar.gz |
bug 1054373
Crash in PK11_DoesMechanism due to race condition
fix additional race with reset.
r=mt
Diffstat (limited to 'lib/dev')
-rw-r--r-- | lib/dev/devslot.c | 21 | ||||
-rw-r--r-- | lib/dev/devt.h | 11 |
2 files changed, 25 insertions, 7 deletions
diff --git a/lib/dev/devslot.c b/lib/dev/devslot.c index 33cc1c162..2b19e3f90 100644 --- a/lib/dev/devslot.c +++ b/lib/dev/devslot.c @@ -90,20 +90,22 @@ NSS_IMPLEMENT void nssSlot_ResetDelay( NSSSlot *slot) { - slot->lastTokenPing = 0; + PZ_Lock(slot->isPresentLock); + slot->lastTokenPingState = nssSlotLastPingState_Reset; + PZ_Unlock(slot->isPresentLock); } static PRBool within_token_delay_period(const NSSSlot *slot) { - PRIntervalTime time, lastTime; + PRIntervalTime time; + int lastPingState = slot->lastTokenPingState; /* 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); } time = PR_IntervalNow(); - lastTime = slot->lastTokenPing; - if ((lastTime) && ((time - lastTime) < s_token_delay_time)) { + if ((lastPingState == nssSlotLastPingState_Valid) && ((time - slot->lastTokenPingTime) < s_token_delay_time)) { return PR_TRUE; } return PR_FALSE; @@ -156,7 +158,9 @@ 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; + PZ_Unlock(slot->isPresentLock); nssSlot_EnterMonitor(slot); @@ -240,14 +244,19 @@ nssSlot_IsTokenPresent( done: /* Once we've set up the condition variable, * Before returning, it's necessary to: - * 1) Set the lastTokenPing time so that any other threads waiting on this + * 1) Set the lastTokenPingTime so that any other threads waiting on this * initialization and any future calls within the initialization window * return the just-computed status. * 2) Indicate we're complete, waking up all other threads that may still * be waiting on initialization can progress. */ PZ_Lock(slot->isPresentLock); - slot->lastTokenPing = PR_IntervalNow(); + /* don't update the time if we were reset while we were + * getting the token state */ + if (slot->lastTokenPingState == nssSlotLastPingState_Update) { + slot->lastTokenPingTime = PR_IntervalNow(); + slot->lastTokenPingState = nssSlotLastPingState_Valid; + } slot->inIsPresent = PR_FALSE; PR_NotifyAllCondVar(slot->isPresentCondition); PZ_Unlock(slot->isPresentLock); diff --git a/lib/dev/devt.h b/lib/dev/devt.h index e077549ae..268cc9e07 100644 --- a/lib/dev/devt.h +++ b/lib/dev/devt.h @@ -70,6 +70,14 @@ struct nssSlotAuthInfoStr { PRIntervalTime askPasswordTimeout; }; +/* values for lastTokenPingState */ +typedef enum { + nssSlotLastPingState_Reset = 0, /* the state has just been reset, discard + * our cache */ + nssSlotLastPingState_Update = 1, /* we are updating the lastTokenPingTime */ + nssSlotLastPingState_Valid = 2, /* lastTokenPingTime is valid */ +} nssSlotLastPingState; + struct NSSSlotStr { struct nssDeviceBaseStr base; NSSModule *module; /* Parent */ @@ -77,7 +85,8 @@ struct NSSSlotStr { CK_SLOT_ID slotID; CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ struct nssSlotAuthInfoStr authInfo; - PRIntervalTime lastTokenPing; + PRIntervalTime lastTokenPingTime; + nssSlotLastPingState lastTokenPingState; PZLock *lock; void *epv; PK11SlotInfo *pk11slot; |