Skip to content

Commit 3a5d5de

Browse files
wangpkdudka
authored andcommitted
nss: work around race condition in PK11_FindSlotByName()
Serialise the call to PK11_FindSlotByName() to avoid spurious errors in a multi-threaded environment. The underlying cause is a race condition in nssSlot_IsTokenPresent(). Bug: https://bugzilla.mozilla.org/1297397 Closes #985
1 parent 7700fcb commit 3a5d5de

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

RELEASE-NOTES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ This release includes the following bugfixes:
3838
o sasl: Don't use GSSAPI authentication when domain name not specified [16]
3939
o win: Basic support for Universal Windows Platform apps [17]
4040
o nss: fix incorrect use of a previously loaded certificate from file
41+
o nss: work around race condition in PK11_FindSlotByName() [18]
4142

4243
This release includes the following known bugs:
4344

@@ -75,3 +76,4 @@ References to bug reports and discussions on issues:
7576
[15] = https://curl.haxx.se/bug/?i=970
7677
[16] = https://curl.haxx.se/bug/?i=718
7778
[17] = https://curl.haxx.se/bug/?i=820
79+
[18] = https://bugzilla.mozilla.org/1297397

lib/vtls/nss.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
8181
static PRLock *nss_initlock = NULL;
8282
static PRLock *nss_crllock = NULL;
83+
static PRLock *nss_findslot_lock = NULL;
8384
static struct curl_llist *nss_crl_list = NULL;
8485
static NSSInitContext *nss_context = NULL;
8586
static volatile int initialized = 0;
@@ -338,6 +339,19 @@ static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
338339
return NULL;
339340
}
340341

342+
/* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
343+
* in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more
344+
* details, go to <https://bugzilla.mozilla.org/1297397>.
345+
*/
346+
static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
347+
{
348+
PK11SlotInfo *slot;
349+
PR_Lock(nss_initlock);
350+
slot = PK11_FindSlotByName(slot_name);
351+
PR_Unlock(nss_initlock);
352+
return slot;
353+
}
354+
341355
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
342356
* the call succeeds, append the object handle to the list of objects so that
343357
* the object can be destroyed in Curl_nss_close(). */
@@ -360,7 +374,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
360374
if(!slot_name)
361375
return CURLE_OUT_OF_MEMORY;
362376

363-
slot = PK11_FindSlotByName(slot_name);
377+
slot = nss_find_slot_by_name(slot_name);
364378
free(slot_name);
365379
if(!slot)
366380
return result;
@@ -561,7 +575,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
561575
return result;
562576
}
563577

564-
slot = PK11_FindSlotByName("PEM Token #1");
578+
slot = nss_find_slot_by_name("PEM Token #1");
565579
if(!slot)
566580
return CURLE_SSL_CERTPROBLEM;
567581

@@ -1011,7 +1025,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
10111025
struct CERTCertificateStr *cert;
10121026
struct SECKEYPrivateKeyStr *key;
10131027

1014-
PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
1028+
PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname);
10151029
if(NULL == slot) {
10161030
failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
10171031
return SECFailure;
@@ -1247,6 +1261,7 @@ int Curl_nss_init(void)
12471261
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
12481262
nss_initlock = PR_NewLock();
12491263
nss_crllock = PR_NewLock();
1264+
nss_findslot_lock = PR_NewLock();
12501265
}
12511266

12521267
/* We will actually initialize NSS later */
@@ -1301,6 +1316,7 @@ void Curl_nss_cleanup(void)
13011316

13021317
PR_DestroyLock(nss_initlock);
13031318
PR_DestroyLock(nss_crllock);
1319+
PR_DestroyLock(nss_findslot_lock);
13041320
nss_initlock = NULL;
13051321

13061322
initialized = 0;

0 commit comments

Comments
 (0)