summaryrefslogtreecommitdiff
path: root/lib/dev
diff options
context:
space:
mode:
authorRobert Relyea <rrelyea@redhat.com>2018-02-14 17:34:27 -0800
committerRobert Relyea <rrelyea@redhat.com>2018-02-14 17:34:27 -0800
commitebd0d8a7f9b80479a8bf69a41be8626517b3be63 (patch)
treef8cb79eabf1bd9ad895b87f305fd6dcc4f6766d1 /lib/dev
parent630d2990d3883722f59aa65c79f13ca1edf5af30 (diff)
downloadnss-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.c21
-rw-r--r--lib/dev/devt.h11
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;