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:
wtc%netscape.com 2002-02-05 23:41:36 +00:00
Родитель 527087c717
Коммит 7d12a23186
4 изменённых файлов: 98 добавлений и 44 удалений

Просмотреть файл

@ -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);
}