Multi-access database race condition patches. These changes are already checked
into NSS 3.6.1.
This commit is contained in:
Родитель
46d9576a06
Коммит
faebb28e1e
|
@ -34,7 +34,7 @@
|
|||
* cdbhdl.h - certificate database handle
|
||||
* private to the certdb module
|
||||
*
|
||||
* $Id: cdbhdl.h,v 1.7 2002-11-04 19:31:57 relyea%netscape.com Exp $
|
||||
* $Id: cdbhdl.h,v 1.8 2002-11-11 22:00:01 relyea%netscape.com Exp $
|
||||
*/
|
||||
#ifndef _CDBHDL_H_
|
||||
#define _CDBHDL_H_
|
||||
|
@ -64,15 +64,19 @@ struct NSSLOWCERTCertDBHandleStr {
|
|||
|
||||
typedef DB * (*rdbfunc)(const char *appName, const char *prefix,
|
||||
const char *type, int flags);
|
||||
typedef int (*rdbstatusfunc)(void);
|
||||
|
||||
#define RDB_FAIL 1
|
||||
#define RDB_RETRY 2
|
||||
|
||||
DB * rdbopen(const char *appName, const char *prefix,
|
||||
const char *type, int flags);
|
||||
const char *type, int flags, int *status);
|
||||
|
||||
DB *dbsopen (const char *dbname , int flags, int mode, DBTYPE type,
|
||||
const void * appData);
|
||||
SECStatus db_Copy(DB *dest,DB *src);
|
||||
int db_BeginTransaction(DB *db);
|
||||
int db_FinishTransaction(DB *db, PRBool abort);
|
||||
|
||||
int db_InitComplete(DB *db);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
# $Id: dbinit.c,v 1.18 2002-11-04 19:31:57 relyea%netscape.com Exp $
|
||||
# $Id: dbinit.c,v 1.19 2002-11-11 22:00:02 relyea%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -275,19 +275,23 @@ pk11_DBShutdown(NSSLOWCERTCertDBHandle *certHandle,
|
|||
}
|
||||
|
||||
static int rdbmapflags(int flags);
|
||||
static rdbfunc pk11_rdbfunc;
|
||||
static rdbfunc pk11_rdbfunc = NULL;
|
||||
static rdbstatusfunc pk11_rdbstatusfunc = NULL;
|
||||
|
||||
/* NOTE: SHLIB_SUFFIX is defined on the command line */
|
||||
#define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
|
||||
|
||||
DB * rdbopen(const char *appName, const char *prefix,
|
||||
const char *type, int flags)
|
||||
const char *type, int flags, int *status)
|
||||
{
|
||||
PRLibrary *lib;
|
||||
DB *db;
|
||||
|
||||
if (pk11_rdbfunc) {
|
||||
db = (*pk11_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
|
||||
if (!db && status && pk11_rdbstatusfunc) {
|
||||
*status = (*pk11_rdbstatusfunc)();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
|
@ -300,10 +304,14 @@ DB * rdbopen(const char *appName, const char *prefix,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* get the entry point */
|
||||
/* get the entry points */
|
||||
pk11_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
|
||||
pk11_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
|
||||
if (pk11_rdbfunc) {
|
||||
db = (*pk11_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
|
||||
if (!db && status && pk11_rdbstatusfunc) {
|
||||
*status = (*pk11_rdbstatusfunc)();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
|
@ -319,6 +327,8 @@ struct RDBStr {
|
|||
DB db;
|
||||
int (*xactstart)(DB *db);
|
||||
int (*xactdone)(DB *db, PRBool abort);
|
||||
int version;
|
||||
int (*dbinitcomplete)(DB *db);
|
||||
};
|
||||
|
||||
#define DB_RDB ((DBTYPE) 0xff)
|
||||
|
@ -370,6 +380,23 @@ db_FinishTransaction(DB *db, PRBool abort)
|
|||
return rdb->xactdone(db, abort);
|
||||
}
|
||||
|
||||
int
|
||||
db_InitComplete(DB *db)
|
||||
{
|
||||
struct RDBStr *rdb = (struct RDBStr *)db;
|
||||
if (db->type != DB_RDB) {
|
||||
return 0;
|
||||
}
|
||||
/* we should have addes a version number to the RDBS structure. Since we
|
||||
* didn't, we detect that we have and 'extended' structure if the rdbstatus
|
||||
* func exists */
|
||||
if (!pk11_rdbstatusfunc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdb->dbinitcomplete(db);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SECStatus
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
*
|
||||
* Private Key Database code
|
||||
*
|
||||
* $Id: keydb.c,v 1.31 2002-09-27 17:46:35 relyea%netscape.com Exp $
|
||||
* $Id: keydb.c,v 1.32 2002-11-11 22:00:03 relyea%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "lowkeyi.h"
|
||||
|
@ -830,23 +830,25 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
|
|||
NSSLOWKEYDBHandle *handle, NSSLOWKEYDBNameFunc namecb, void *cbarg)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
int status = RDB_FAIL;
|
||||
char *updname = NULL;
|
||||
DB *updatedb = NULL;
|
||||
PRBool updated = PR_FALSE;
|
||||
int ret;
|
||||
|
||||
if (appName) {
|
||||
handle->db = rdbopen( appName, prefix, "key", NO_CREATE);
|
||||
handle->db = rdbopen( appName, prefix, "key", NO_CREATE, &status);
|
||||
} else {
|
||||
handle->db = dbopen( dbname, NO_CREATE, 0600, DB_HASH, 0 );
|
||||
}
|
||||
/* if create fails then we lose */
|
||||
if ( handle->db == NULL ) {
|
||||
return SECFailure;
|
||||
return (status == RDB_RETRY) ? SECWouldBlock: SECFailure;
|
||||
}
|
||||
|
||||
rv = db_BeginTransaction(handle->db);
|
||||
if (rv != SECSuccess) {
|
||||
db_InitComplete(handle->db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -855,6 +857,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
|
|||
if (nsslowkey_version(handle->db) == NSSLOWKEY_DB_FILE_VERSION) {
|
||||
/* someone else has already updated the database for us */
|
||||
db_FinishTransaction(handle->db, PR_FALSE);
|
||||
db_InitComplete(handle->db);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
@ -872,6 +875,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
|
|||
db_Copy(handle->db, updatedb);
|
||||
(updatedb->close)(updatedb);
|
||||
db_FinishTransaction(handle->db,PR_FALSE);
|
||||
db_InitComplete(handle->db);
|
||||
return SECSuccess;
|
||||
}
|
||||
}
|
||||
|
@ -924,9 +928,34 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
|
|||
|
||||
loser:
|
||||
db_FinishTransaction(handle->db, rv != SECSuccess);
|
||||
db_InitComplete(handle->db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static DB *
|
||||
openOldDB(const char *appName, const char *prefix, const char *dbname,
|
||||
PRBool openflags, int *version) {
|
||||
DB *db = NULL;
|
||||
|
||||
if (appName) {
|
||||
db = rdbopen( appName, prefix, "key", openflags, NULL);
|
||||
} else {
|
||||
db = dbopen( dbname, openflags, 0600, DB_HASH, 0 );
|
||||
}
|
||||
|
||||
/* check for correct version number */
|
||||
if (db != NULL) {
|
||||
*version = nsslowkey_version(db);
|
||||
if (*version != NSSLOWKEY_DB_FILE_VERSION ) {
|
||||
/* bogus version number record, reset the database */
|
||||
(* db->close)( db );
|
||||
db = NULL;
|
||||
}
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
NSSLOWKEYDBHandle *
|
||||
nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
|
||||
NSSLOWKEYDBNameFunc namecb, void *cbarg)
|
||||
|
@ -953,25 +982,14 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
|
|||
handle->dbname = (appName == NULL) ? PORT_Strdup(dbname) :
|
||||
(prefix ? PORT_Strdup(prefix) : NULL);
|
||||
handle->readOnly = readOnly;
|
||||
|
||||
if (appName) {
|
||||
handle->db = rdbopen( appName, prefix, "key", openflags);
|
||||
} else {
|
||||
handle->db = dbopen( dbname, openflags, 0600, DB_HASH, 0 );
|
||||
}
|
||||
|
||||
/* check for correct version number */
|
||||
if (handle->db != NULL) {
|
||||
handle->version = nsslowkey_version(handle->db);
|
||||
if (handle->version == 255) {
|
||||
goto loser;
|
||||
}
|
||||
if (handle->version != NSSLOWKEY_DB_FILE_VERSION ) {
|
||||
/* bogus version number record, reset the database */
|
||||
(* handle->db->close)( handle->db );
|
||||
handle->db = NULL;
|
||||
}
|
||||
|
||||
handle->db = openOldDB(appName, prefix, dbname, openflags,
|
||||
&handle->version);
|
||||
if (handle->version == 255) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
|
||||
/* if first open fails, try to create a new DB */
|
||||
if ( handle->db == NULL ) {
|
||||
|
@ -980,7 +998,16 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
|
|||
}
|
||||
|
||||
rv = openNewDB(appName, prefix, dbname, handle, namecb, cbarg);
|
||||
if (rv != SECSuccess) {
|
||||
/* two processes started to initialize the database at the same time.
|
||||
* The multiprocess code blocked the second one, then had it retry to
|
||||
* see if it can just open the database normally */
|
||||
if (rv == SECWouldBlock) {
|
||||
handle->db = openOldDB(appName,prefix,dbname,
|
||||
openflags, &handle->version);
|
||||
if (handle->db == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
} else if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
|
@ -2453,7 +2480,8 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
|
|||
|
||||
(* handle->db->close)(handle->db);
|
||||
if (handle->appname) {
|
||||
handle->db=rdbopen(handle->appname, handle->dbname, "key", NO_CREATE);
|
||||
handle->db=
|
||||
rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL);
|
||||
} else {
|
||||
handle->db = dbopen( handle->dbname, NO_CREATE, 0600, DB_HASH, 0 );
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
/*
|
||||
* Permanent Certificate database handling code
|
||||
*
|
||||
* $Id: pcertdb.c,v 1.33 2002-11-04 19:31:58 relyea%netscape.com Exp $
|
||||
* $Id: pcertdb.c,v 1.34 2002-11-11 22:00:03 relyea%netscape.com Exp $
|
||||
*/
|
||||
#include "prtime.h"
|
||||
|
||||
|
@ -3903,20 +3903,22 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
|
|||
certDBEntryVersion *versionEntry = NULL;
|
||||
DB *updatedb = NULL;
|
||||
char *tmpname;
|
||||
int status = RDB_FAIL;
|
||||
|
||||
if (appName) {
|
||||
handle->permCertDB=rdbopen( appName, prefix, "cert", NO_CREATE);
|
||||
handle->permCertDB=rdbopen( appName, prefix, "cert", NO_CREATE, &status);
|
||||
} else {
|
||||
handle->permCertDB=dbsopen(certdbname, NO_CREATE, 0600, DB_HASH, 0);
|
||||
}
|
||||
|
||||
/* if create fails then we lose */
|
||||
if ( handle->permCertDB == 0 ) {
|
||||
return SECFailure;
|
||||
return status == RDB_RETRY ? SECWouldBlock : SECFailure;
|
||||
}
|
||||
|
||||
rv = db_BeginTransaction(handle->permCertDB);
|
||||
if (rv != SECSuccess) {
|
||||
db_InitComplete(handle->permCertDB);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
|
@ -3927,6 +3929,7 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
|
|||
if (updatedb) {
|
||||
rv = UpdateV8DB(handle, updatedb);
|
||||
db_FinishTransaction(handle->permCertDB,PR_FALSE);
|
||||
db_InitComplete(handle->permCertDB);
|
||||
return(rv);
|
||||
}
|
||||
}
|
||||
|
@ -3965,6 +3968,7 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
|
|||
|
||||
loser:
|
||||
db_FinishTransaction(handle->permCertDB,rv != SECSuccess);
|
||||
db_InitComplete(handle->permCertDB);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -4008,7 +4012,7 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
|
|||
* first open the permanent file based database.
|
||||
*/
|
||||
if (appName) {
|
||||
handle->permCertDB = rdbopen( appName, prefix, "cert", openflags);
|
||||
handle->permCertDB = rdbopen( appName, prefix, "cert", openflags, NULL);
|
||||
} else {
|
||||
handle->permCertDB = dbsopen( certdbname, openflags, 0600, DB_HASH, 0 );
|
||||
}
|
||||
|
@ -4033,7 +4037,21 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
|
|||
} else {
|
||||
/* if first open fails, try to create a new DB */
|
||||
rv = openNewCertDB(appName,prefix,certdbname,handle,namecb,cbarg);
|
||||
if (rv != SECSuccess) {
|
||||
if (rv == SECWouldBlock) {
|
||||
/* only the rdb version can fail with wouldblock */
|
||||
handle->permCertDB =
|
||||
rdbopen( appName, prefix, "cert", openflags, NULL);
|
||||
|
||||
/* check for correct version number */
|
||||
if ( !handle->permCertDB ) {
|
||||
goto loser;
|
||||
}
|
||||
version = nsslowcert_GetVersionNumber(handle);
|
||||
if ((version != CERT_DB_FILE_VERSION) &&
|
||||
!(appName && version == CERT_DB_V7_FILE_VERSION)) {
|
||||
goto loser;
|
||||
}
|
||||
} else if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -652,18 +652,24 @@ secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
|
|||
if (appName) {
|
||||
char *secname = PORT_Strdup(filename);
|
||||
int len = strlen(secname);
|
||||
int status = RDB_FAIL;
|
||||
|
||||
if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
|
||||
secname[len-3] = 0;
|
||||
}
|
||||
pkcs11db=rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_CREATE);
|
||||
pkcs11db=
|
||||
rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
|
||||
if (update && !pkcs11db) {
|
||||
DB *updatedb;
|
||||
|
||||
pkcs11db = rdbopen(appName, "", secname, NO_CREATE);
|
||||
pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
|
||||
if (!pkcs11db) {
|
||||
if (status == RDB_RETRY) {
|
||||
pkcs11db= rdbopen(appName, "", secname,
|
||||
readOnly ? NO_RDONLY:NO_RDWR, NULL);
|
||||
}
|
||||
PORT_Free(secname);
|
||||
return NULL;
|
||||
return pkcs11db;
|
||||
}
|
||||
updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
|
||||
if (updatedb) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче