зеркало из https://github.com/mozilla/gecko-dev.git
Bugzilla bug 121523: checked in Kirk Erickson's session lock fix.
Modified Files: lib/pk11wrap/pk11slot.c lib/softoken/pkcs11.c lib/softoken/pkcs11i.h lib/softoken/pkcs11u.c
This commit is contained in:
Родитель
527087c717
Коммит
7d12a23186
|
@ -3632,10 +3632,10 @@ PK11_GenerateRandom(unsigned char *data,int len) {
|
|||
slot = PK11_GetBestSlot(CKM_FAKE_RANDOM,NULL);
|
||||
if (slot == NULL) return SECFailure;
|
||||
|
||||
PK11_EnterSlotMonitor(slot);
|
||||
if (!slot->isInternal) PK11_EnterSlotMonitor(slot);
|
||||
crv = PK11_GETTAB(slot)->C_GenerateRandom(slot->session,data,
|
||||
(CK_ULONG)len);
|
||||
PK11_ExitSlotMonitor(slot);
|
||||
if (!slot->isInternal) PK11_ExitSlotMonitor(slot);
|
||||
PK11_FreeSlot(slot);
|
||||
return (crv != CKR_OK) ? SECFailure : SECSuccess;
|
||||
}
|
||||
|
|
|
@ -1983,12 +1983,19 @@ PK11_SlotInit(char *configdir,pk11_token_parameters *params)
|
|||
}
|
||||
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
slot->sessionLock = PZ_NewLock(nssILockSession);
|
||||
if (slot->sessionLock == NULL) return CKR_HOST_MEMORY;
|
||||
slot->slotLock = PZ_NewLock(nssILockSession);
|
||||
if (slot->slotLock == NULL) return CKR_HOST_MEMORY;
|
||||
for (i=0; i < NUMBER_OF_SESSION_LOCKS; i++) {
|
||||
slot->sessionLock[i] = PZ_NewLock(nssILockSession);
|
||||
if (slot->sessionLock[i] == NULL) return CKR_HOST_MEMORY;
|
||||
}
|
||||
slot->objectLock = PZ_NewLock(nssILockObject);
|
||||
if (slot->objectLock == NULL) return CKR_HOST_MEMORY;
|
||||
#else
|
||||
slot->sessionLock = NULL;
|
||||
slot->slotLock = NULL;
|
||||
for (i=0; i < NUMBER_OF_SESSION_LOCKS; i++) {
|
||||
slot->sessionLock[i] = NULL;
|
||||
}
|
||||
slot->objectLock = NULL;
|
||||
#endif
|
||||
for(i=0; i < SESSION_HASH_SIZE; i++) {
|
||||
|
@ -2067,9 +2074,15 @@ pk11_DestroySlotData(PK11Slot *slot)
|
|||
int i;
|
||||
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
if (slot->sessionLock) {
|
||||
PZ_DestroyLock(slot->sessionLock);
|
||||
slot->sessionLock = NULL;
|
||||
if (slot->slotLock) {
|
||||
PZ_DestroyLock(slot->slotLock);
|
||||
slot->slotLock = NULL;
|
||||
}
|
||||
for (i=0; i < NUMBER_OF_SESSION_LOCKS; i++) {
|
||||
if (slot->sessionLock[i]) {
|
||||
PZ_DestroyLock(slot->sessionLock[i]);
|
||||
slot->sessionLock[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (slot->objectLock) {
|
||||
PZ_DestroyLock(slot->objectLock);
|
||||
|
@ -2665,21 +2678,23 @@ CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
|
|||
flags | CKF_SERIAL_SESSION);
|
||||
if (session == NULL) return CKR_HOST_MEMORY;
|
||||
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(slot->slotLock);)
|
||||
sessionID = slot->sessionIDCount++ | (slot->index << 24);
|
||||
if (slot->readOnly && (flags & CKF_RW_SESSION)) {
|
||||
/* NETSCAPE_SLOT_ID is Read ONLY */
|
||||
session->info.flags &= ~CKF_RW_SESSION;
|
||||
}
|
||||
|
||||
session->handle = sessionID;
|
||||
pk11_update_state(slot, session);
|
||||
pk11queue_add(session, sessionID, slot->head, SESSION_HASH_SIZE);
|
||||
slot->sessionCount++;
|
||||
if (session->info.flags & CKF_RW_SESSION) {
|
||||
slot->rwSessionCount++;
|
||||
}
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->slotLock);)
|
||||
|
||||
PK11_USE_THREADS(PZ_Lock(PK11_SESSION_LOCK(slot,sessionID));)
|
||||
session->handle = sessionID;
|
||||
pk11_update_state(slot, session);
|
||||
pk11queue_add(session, sessionID, slot->head, SESSION_HASH_SIZE);
|
||||
PK11_USE_THREADS(PZ_Unlock(PK11_SESSION_LOCK(slot,sessionID));)
|
||||
|
||||
*phSession = sessionID;
|
||||
return CKR_OK;
|
||||
|
@ -2692,16 +2707,25 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
|
|||
PK11Slot *slot;
|
||||
PK11Session *session;
|
||||
SECItem *pw = NULL;
|
||||
PRBool sessionFound;
|
||||
|
||||
session = pk11_SessionFromHandle(hSession);
|
||||
if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
|
||||
slot = pk11_SlotFromSession(session);
|
||||
sessionFound = PR_FALSE;
|
||||
|
||||
/* lock */
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(PK11_SESSION_LOCK(slot,hSession));)
|
||||
if (pk11queue_is_queued(session,hSession,slot->head,SESSION_HASH_SIZE)) {
|
||||
sessionFound = PR_TRUE;
|
||||
pk11queue_delete(session,hSession,slot->head,SESSION_HASH_SIZE);
|
||||
session->refCount--; /* can't go to zero while we hold the reference */
|
||||
PORT_Assert(session->refCount > 0);
|
||||
}
|
||||
PK11_USE_THREADS(PZ_Unlock(PK11_SESSION_LOCK(slot,hSession));)
|
||||
|
||||
PK11_USE_THREADS(PZ_Lock(slot->slotLock);)
|
||||
if (sessionFound) {
|
||||
slot->sessionCount--;
|
||||
if (session->info.flags & CKF_RW_SESSION) {
|
||||
slot->rwSessionCount--;
|
||||
|
@ -2712,7 +2736,7 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
|
|||
slot->isLoggedIn = PR_FALSE;
|
||||
slot->password = NULL;
|
||||
}
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->slotLock);)
|
||||
|
||||
pk11_FreeSession(session);
|
||||
if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
|
||||
|
@ -2732,11 +2756,11 @@ CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID)
|
|||
if (slot == NULL) return CKR_SLOT_ID_INVALID;
|
||||
|
||||
/* first log out the card */
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(slot->slotLock);)
|
||||
pw = slot->password;
|
||||
slot->isLoggedIn = PR_FALSE;
|
||||
slot->password = NULL;
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->slotLock);)
|
||||
if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
|
||||
|
||||
/* now close all the current sessions */
|
||||
|
@ -2746,7 +2770,7 @@ CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID)
|
|||
* will guarrenteed be close, and no session will be partially closed */
|
||||
for (i=0; i < SESSION_HASH_SIZE; i++) {
|
||||
do {
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(PK11_SESSION_LOCK(slot,i));)
|
||||
session = slot->head[i];
|
||||
/* hand deque */
|
||||
/* this duplicates function of NSC_close session functions, but
|
||||
|
@ -2756,12 +2780,16 @@ CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID)
|
|||
slot->head[i] = session->next;
|
||||
if (session->next) session->next->prev = NULL;
|
||||
session->next = session->prev = NULL;
|
||||
PK11_USE_THREADS(PZ_Unlock(PK11_SESSION_LOCK(slot,i));)
|
||||
PK11_USE_THREADS(PZ_Lock(slot->slotLock);)
|
||||
slot->sessionCount--;
|
||||
if (session->info.flags & CKF_RW_SESSION) {
|
||||
slot->rwSessionCount--;
|
||||
}
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->slotLock);)
|
||||
} else {
|
||||
PK11_USE_THREADS(PZ_Unlock(PK11_SESSION_LOCK(slot,i));)
|
||||
}
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
if (session) pk11_FreeSession(session);
|
||||
} while (session != NULL);
|
||||
}
|
||||
|
@ -2836,12 +2864,12 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
|
|||
/* should this be a fixed password? */
|
||||
if (ulPinLen == 0) {
|
||||
SECItem *pw;
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(slot->slotLock);)
|
||||
pw = slot->password;
|
||||
slot->password = NULL;
|
||||
slot->isLoggedIn = PR_TRUE;
|
||||
slot->ssoLoggedIn = (PRBool)(userType == CKU_SO);
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->slotLock);)
|
||||
pk11_update_all_states(slot);
|
||||
SECITEM_ZfreeItem(pw,PR_TRUE);
|
||||
return CKR_OK;
|
||||
|
@ -2861,11 +2889,11 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
|
|||
|
||||
if (nsslowkey_CheckKeyDBPassword(handle,pin) == SECSuccess) {
|
||||
SECItem *tmp;
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(slot->slotLock);)
|
||||
tmp = slot->password;
|
||||
slot->isLoggedIn = PR_TRUE;
|
||||
slot->password = pin;
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->slotLock);)
|
||||
if (tmp) SECITEM_ZfreeItem(tmp, PR_TRUE);
|
||||
|
||||
/* update all sessions */
|
||||
|
@ -2891,12 +2919,12 @@ CK_RV NSC_Logout(CK_SESSION_HANDLE hSession)
|
|||
|
||||
if (!slot->isLoggedIn) return CKR_USER_NOT_LOGGED_IN;
|
||||
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(slot->slotLock);)
|
||||
pw = slot->password;
|
||||
slot->isLoggedIn = PR_FALSE;
|
||||
slot->ssoLoggedIn = PR_FALSE;
|
||||
slot->password = NULL;
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->slotLock);)
|
||||
if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
|
||||
|
||||
pk11_update_all_states(slot);
|
||||
|
|
|
@ -107,13 +107,35 @@
|
|||
#define ATTRIBUTE_HASH_SIZE 32
|
||||
#define SESSION_OBJECT_HASH_SIZE 32
|
||||
#define TOKEN_OBJECT_HASH_SIZE 1024
|
||||
#define SESSION_HASH_SIZE 512
|
||||
#define SESSION_HASH_SIZE 1024
|
||||
#define MAX_OBJECT_LIST_SIZE 800 /* how many objects to keep on the free list
|
||||
* before we start freeing them */
|
||||
#endif
|
||||
#define MAX_KEY_LEN 256
|
||||
|
||||
|
||||
/*
|
||||
* LOG2_BUCKETS_PER_SESSION_LOCK must be a prime number.
|
||||
* With SESSION_HASH_SIZE=1024, LOG2 can be 9, 5, 1, or 0.
|
||||
* With SESSION_HASH_SIZE=4096, LOG2 can be 11, 9, 5, 1, or 0.
|
||||
*
|
||||
* HASH_SIZE LOG2_BUCKETS_PER BUCKETS_PER_LOCK NUMBER_OF_BUCKETS
|
||||
* 1024 9 512 2
|
||||
* 1024 5 32 32
|
||||
* 1024 1 2 512
|
||||
* 1024 0 1 1024
|
||||
* 4096 11 2048 2
|
||||
* 4096 9 512 8
|
||||
* 4096 5 32 128
|
||||
* 4096 1 2 2048
|
||||
* 4096 0 1 4096
|
||||
*/
|
||||
#define LOG2_BUCKETS_PER_SESSION_LOCK 1
|
||||
#define BUCKETS_PER_SESSION_LOCK (1 << (LOG2_BUCKETS_PER_SESSION_LOCK))
|
||||
#define NUMBER_OF_SESSION_LOCKS (SESSION_HASH_SIZE/BUCKETS_PER_SESSION_LOCK)
|
||||
/* NOSPREAD sessionID to hash table index macro has been slower. */
|
||||
#if 0
|
||||
#define NOSPREAD
|
||||
#endif
|
||||
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
#define PK11_USE_THREADS(x) x
|
||||
|
@ -304,7 +326,6 @@ struct PK11SessionStr {
|
|||
PK11Session *prev;
|
||||
CK_SESSION_HANDLE handle;
|
||||
int refCount;
|
||||
PZLock *refLock;
|
||||
PZLock *objectLock;
|
||||
int objectIDCount;
|
||||
CK_SESSION_INFO info;
|
||||
|
@ -323,7 +344,8 @@ struct PK11SessionStr {
|
|||
*/
|
||||
struct PK11SlotStr {
|
||||
CK_SLOT_ID slotID;
|
||||
PZLock *sessionLock;
|
||||
PZLock *slotLock;
|
||||
PZLock *sessionLock[NUMBER_OF_SESSION_LOCKS];
|
||||
PZLock *objectLock;
|
||||
SECItem *password;
|
||||
PRBool hasTokens;
|
||||
|
@ -428,6 +450,18 @@ struct PK11SSLMACInfoStr {
|
|||
(element)->next = NULL; \
|
||||
(element)->prev = NULL; \
|
||||
|
||||
/* sessionID (handle) is used to determine session lock bucket */
|
||||
#ifdef NOSPREAD
|
||||
/* NOSPREAD: (ID>>L2LPB) & (perbucket-1) */
|
||||
#define PK11_SESSION_LOCK(slot,handle) \
|
||||
((slot)->sessionLock[((handle) >> LOG2_BUCKETS_PER_SESSION_LOCK) \
|
||||
& (NUMBER_OF_SESSION_LOCKS-1)])
|
||||
#else
|
||||
/* SPREAD: ID & (perbucket-1) */
|
||||
#define PK11_SESSION_LOCK(slot,handle) \
|
||||
((slot)->sessionLock[(handle) & (NUMBER_OF_SESSION_LOCKS-1)])
|
||||
#endif
|
||||
|
||||
/* expand an attribute & secitem structures out */
|
||||
#define pk11_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen
|
||||
#define pk11_item_expand(ip) (ip)->data,(ip)->len
|
||||
|
|
|
@ -2320,11 +2320,11 @@ pk11_update_all_states(PK11Slot *slot)
|
|||
PK11Session *session;
|
||||
|
||||
for (i=0; i < SESSION_HASH_SIZE; i++) {
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(PK11_SESSION_LOCK(slot,i));)
|
||||
for (session = slot->head[i]; session; session = session->next) {
|
||||
pk11_update_state(slot,session);
|
||||
}
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(PK11_SESSION_LOCK(slot,i));)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2371,19 +2371,12 @@ pk11_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
|
|||
session->search = NULL;
|
||||
session->objectIDCount = 1;
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
session->refLock = PZ_NewLock(nssILockRefLock);
|
||||
if (session->refLock == NULL) {
|
||||
PORT_Free(session);
|
||||
return NULL;
|
||||
}
|
||||
session->objectLock = PZ_NewLock(nssILockObject);
|
||||
if (session->objectLock == NULL) {
|
||||
PK11_USE_THREADS(PZ_DestroyLock(session->refLock);)
|
||||
PORT_Free(session);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
session->refLock = NULL;
|
||||
session->objectLock = NULL;
|
||||
#endif
|
||||
session->objects[0] = NULL;
|
||||
|
@ -2415,7 +2408,6 @@ pk11_DestroySession(PK11Session *session)
|
|||
pk11_DeleteObject(session,op->parent);
|
||||
}
|
||||
PK11_USE_THREADS(PZ_DestroyLock(session->objectLock);)
|
||||
PK11_USE_THREADS(PZ_DestroyLock(session->refLock);)
|
||||
if (session->enc_context) {
|
||||
pk11_FreeContext(session->enc_context);
|
||||
}
|
||||
|
@ -2442,10 +2434,10 @@ pk11_SessionFromHandle(CK_SESSION_HANDLE handle)
|
|||
PK11Slot *slot = pk11_SlotFromSessionHandle(handle);
|
||||
PK11Session *session;
|
||||
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(PK11_SESSION_LOCK(slot,handle));)
|
||||
pk11queue_find(session,handle,slot->head,SESSION_HASH_SIZE);
|
||||
if (session) session->refCount++;
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(PK11_SESSION_LOCK(slot,handle));)
|
||||
|
||||
return (session);
|
||||
}
|
||||
|
@ -2459,10 +2451,10 @@ pk11_FreeSession(PK11Session *session)
|
|||
PRBool destroy = PR_FALSE;
|
||||
PK11_USE_THREADS(PK11Slot *slot = pk11_SlotFromSession(session);)
|
||||
|
||||
PK11_USE_THREADS(PZ_Lock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Lock(PK11_SESSION_LOCK(slot,session->handle));)
|
||||
if (session->refCount == 1) destroy = PR_TRUE;
|
||||
session->refCount--;
|
||||
PK11_USE_THREADS(PZ_Unlock(slot->sessionLock);)
|
||||
PK11_USE_THREADS(PZ_Unlock(PK11_SESSION_LOCK(slot,session->handle));)
|
||||
|
||||
if (destroy) pk11_DestroySession(session);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче