зеркало из https://github.com/mozilla/pjs.git
SSL_ShutdownServerSessionIDCache no longer leaks the cache memory.
Bug 222065. r=wchang0222
This commit is contained in:
Родитель
2584fa08fb
Коммит
f8af4da928
|
@ -32,7 +32,7 @@
|
|||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* $Id: sslsnce.c,v 1.25 2003-03-27 03:07:47 nelsonb%netscape.com Exp $
|
||||
* $Id: sslsnce.c,v 1.26 2003-10-19 01:25:10 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
|
||||
/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
|
||||
|
@ -64,7 +64,7 @@
|
|||
* sidCacheEntry sidCacheData[ numSIDCacheEntries];
|
||||
* certCacheEntry certCacheData[numCertCacheEntries];
|
||||
* SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
|
||||
* } sharedMemCacheData;
|
||||
* } cacheMemCacheData;
|
||||
*/
|
||||
#include "nssrenam.h"
|
||||
#include "seccomon.h"
|
||||
|
@ -183,7 +183,7 @@ typedef struct sidCacheSetStr sidCacheSet;
|
|||
|
||||
struct cacheDescStr {
|
||||
|
||||
PRUint32 sharedMemSize;
|
||||
PRUint32 cacheMemSize;
|
||||
|
||||
PRUint32 numSIDCacheLocks;
|
||||
PRUint32 numSIDCacheSets;
|
||||
|
@ -201,9 +201,12 @@ struct cacheDescStr {
|
|||
PRUint32 ssl2Timeout;
|
||||
PRUint32 ssl3Timeout;
|
||||
|
||||
PRUint32 numSIDCacheLocksInitialized;
|
||||
|
||||
/* These values are volatile, and are accessed through sharedCache-> */
|
||||
PRUint32 nextCertCacheEntry; /* certCacheLock protects */
|
||||
PRBool stopPolling;
|
||||
PRBool everInherited;
|
||||
|
||||
/* The private copies of these values are pointers into shared mem */
|
||||
/* The copies of these values in shared memory are merely offsets */
|
||||
|
@ -216,7 +219,7 @@ struct cacheDescStr {
|
|||
SSLWrappedSymWrappingKey * keyCacheData;
|
||||
|
||||
/* Only the private copies of these pointers are valid */
|
||||
char * sharedMem;
|
||||
char * cacheMem;
|
||||
struct cacheDescStr * sharedCache; /* shared copy of this struct */
|
||||
PRFileMap * cacheMemMap;
|
||||
PRThread * poller;
|
||||
|
@ -263,15 +266,14 @@ static sslPID myPid;
|
|||
static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
|
||||
|
||||
/* forward static function declarations */
|
||||
static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl);
|
||||
static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
|
||||
unsigned nl);
|
||||
static SECStatus LaunchLockPoller(cacheDesc *cache);
|
||||
|
||||
|
||||
|
||||
|
||||
struct inheritanceStr {
|
||||
PRUint32 sharedMemSize;
|
||||
PRUint16 fmStrLen;
|
||||
PRUint32 cacheMemSize;
|
||||
PRUint32 fmStrLen;
|
||||
};
|
||||
|
||||
typedef struct inheritanceStr inheritance;
|
||||
|
@ -881,24 +883,60 @@ long gettid(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
CloseCache(cacheDesc *cache)
|
||||
{
|
||||
int locks_initialized = cache->numSIDCacheLocksInitialized;
|
||||
|
||||
if (cache->cacheMem) {
|
||||
/* If everInherited is true, this shared cache was (and may still
|
||||
** be) in use by multiple processes. We do not wish to destroy
|
||||
** the mutexes while they are still in use.
|
||||
*/
|
||||
if (PR_FALSE == cache->sharedCache->everInherited) {
|
||||
sidCacheLock *pLock = cache->sidCacheLocks;
|
||||
for (; locks_initialized > 0; --locks_initialized, ++pLock ) {
|
||||
sslMutex_Destroy(&pLock->mutex);
|
||||
}
|
||||
}
|
||||
if (cache->shared) {
|
||||
PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
|
||||
} else {
|
||||
PORT_Free(cache->cacheMem);
|
||||
}
|
||||
cache->cacheMem = NULL;
|
||||
}
|
||||
if (cache->cacheMemMap) {
|
||||
PR_CloseFileMap(cache->cacheMemMap);
|
||||
cache->cacheMemMap = NULL;
|
||||
}
|
||||
memset(cache, 0, sizeof *cache);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
|
||||
PRUint32 ssl3_timeout, const char *directory, PRBool shared)
|
||||
{
|
||||
ptrdiff_t ptr;
|
||||
sidCacheLock *pLock;
|
||||
char * sharedMem;
|
||||
char * cacheMem;
|
||||
PRFileMap * cacheMemMap;
|
||||
char * cfn = NULL; /* cache file name */
|
||||
int locks_initialized = 0;
|
||||
int locks_to_initialize = 0;
|
||||
PRUint32 init_time;
|
||||
|
||||
if (cache->sharedMem) {
|
||||
if (cache->cacheMem) {
|
||||
/* Already done */
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* make sure loser can clean up properly */
|
||||
cache->shared = shared;
|
||||
cache->cacheMem = cacheMem = NULL;
|
||||
cache->cacheMemMap = cacheMemMap = NULL;
|
||||
cache->sharedCache = (cacheDesc *)0;
|
||||
|
||||
cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
|
||||
: DEF_SID_CACHE_ENTRIES;
|
||||
cache->numSIDCacheSets =
|
||||
|
@ -915,7 +953,7 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
|
|||
|
||||
/* compute size of shared memory, and offsets of all pointers */
|
||||
ptr = 0;
|
||||
cache->sharedMem = (char *)ptr;
|
||||
cache->cacheMem = (char *)ptr;
|
||||
ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
|
||||
|
||||
cache->sidCacheLocks = (sidCacheLock *)ptr;
|
||||
|
@ -951,7 +989,7 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
|
|||
ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
|
||||
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
|
||||
|
||||
cache->sharedMemSize = ptr;
|
||||
cache->cacheMemSize = ptr;
|
||||
|
||||
cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
|
||||
|
||||
|
@ -979,6 +1017,7 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
|
|||
cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
|
||||
}
|
||||
|
||||
if (shared) {
|
||||
/* Create file names */
|
||||
#if defined(XP_UNIX) || defined(XP_BEOS)
|
||||
/* there's some confusion here about whether PR_OpenAnonFileMap wants
|
||||
|
@ -986,60 +1025,52 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
|
|||
cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
|
||||
*/
|
||||
cfn = PR_smprintf("%s", directory);
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN32
|
||||
#elif defined(XP_WIN32)
|
||||
cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
|
||||
GetCurrentThreadId());
|
||||
#endif
|
||||
|
||||
#ifdef XP_OS2
|
||||
#elif defined(XP_OS2)
|
||||
cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
|
||||
gettid());
|
||||
#else
|
||||
#error "Don't know how to create file name for this platform!"
|
||||
#endif
|
||||
if (!cfn) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
cache->shared = shared;
|
||||
/* Create cache */
|
||||
if (PR_TRUE == shared) {
|
||||
cacheMemMap = PR_OpenAnonFileMap(cfn, cache->sharedMemSize,
|
||||
cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
|
||||
PR_PROT_READWRITE);
|
||||
} else {
|
||||
cacheMemMap = NULL;
|
||||
}
|
||||
|
||||
PR_smprintf_free(cfn);
|
||||
if( (PR_TRUE == shared) && (!cacheMemMap) ) {
|
||||
if(!cacheMemMap) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (PR_TRUE == shared) {
|
||||
sharedMem = PR_MemMap(cacheMemMap, 0, cache->sharedMemSize);
|
||||
cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
|
||||
} else {
|
||||
sharedMem = PORT_Alloc(cache->sharedMemSize);
|
||||
cacheMem = PORT_Alloc(cache->cacheMemSize);
|
||||
}
|
||||
|
||||
if (! sharedMem) {
|
||||
if (! cacheMem) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Initialize shared memory. This may not be necessary on all platforms */
|
||||
memset(sharedMem, 0, cache->sharedMemSize);
|
||||
memset(cacheMem, 0, cache->cacheMemSize);
|
||||
|
||||
/* Copy cache descriptor header into shared memory */
|
||||
memcpy(sharedMem, cache, sizeof *cache);
|
||||
memcpy(cacheMem, cache, sizeof *cache);
|
||||
|
||||
/* save private copies of these values */
|
||||
cache->cacheMemMap = cacheMemMap;
|
||||
cache->sharedMem = sharedMem;
|
||||
cache->sharedCache = (cacheDesc *)sharedMem;
|
||||
cache->cacheMem = cacheMem;
|
||||
cache->sharedCache = (cacheDesc *)cacheMem;
|
||||
|
||||
/* Fix pointers in our private copy of cache descriptor to point to
|
||||
** spaces in shared memory
|
||||
*/
|
||||
ptr = (ptrdiff_t)cache->sharedMem;
|
||||
ptr = (ptrdiff_t)cache->cacheMem;
|
||||
*(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
|
||||
*(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
|
||||
*(ptrdiff_t *)(&cache->certCacheLock) += ptr;
|
||||
|
@ -1055,36 +1086,20 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
|
|||
locks_initialized < locks_to_initialize;
|
||||
++locks_initialized, ++pLock ) {
|
||||
|
||||
SECStatus err = sslMutex_Init(&pLock->mutex, isMultiProcess);
|
||||
if (err)
|
||||
SECStatus err = sslMutex_Init(&pLock->mutex, shared);
|
||||
if (err) {
|
||||
cache->numSIDCacheLocksInitialized = locks_initialized;
|
||||
goto loser;
|
||||
}
|
||||
pLock->timeStamp = init_time;
|
||||
pLock->pid = 0;
|
||||
}
|
||||
cache->numSIDCacheLocksInitialized = locks_initialized;
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
if (cache->cacheMemMap) {
|
||||
if (cache->sharedMem) {
|
||||
if (locks_initialized > 0) {
|
||||
pLock = cache->sidCacheLocks;
|
||||
for (; locks_initialized > 0; --locks_initialized, ++pLock ) {
|
||||
sslMutex_Destroy(&pLock->mutex);
|
||||
}
|
||||
}
|
||||
if (shared) {
|
||||
PR_MemUnmap(cache->sharedMem, cache->sharedMemSize);
|
||||
cache->sharedMem = NULL;
|
||||
}
|
||||
}
|
||||
if (shared) {
|
||||
PR_CloseFileMap(cache->cacheMemMap);
|
||||
} else {
|
||||
PORT_Free(sharedMem);
|
||||
}
|
||||
cache->cacheMemMap = NULL;
|
||||
}
|
||||
CloseCache(cache);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
|
@ -1161,9 +1176,7 @@ SSL_ConfigServerSessionIDCache( int maxCacheEntries,
|
|||
SECStatus
|
||||
SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
|
||||
{
|
||||
/* if single process, close down, clean up.
|
||||
** if multi-process, TBD.
|
||||
*/
|
||||
CloseCache(cache);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
@ -1206,7 +1219,7 @@ SSL_ConfigMPServerSIDCache( int maxCacheEntries,
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
inherit.sharedMemSize = cache->sharedMemSize;
|
||||
inherit.cacheMemSize = cache->cacheMemSize;
|
||||
inherit.fmStrLen = fmStrLen;
|
||||
|
||||
inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
|
||||
|
@ -1240,6 +1253,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
|
|||
{
|
||||
unsigned char * decoString = NULL;
|
||||
char * fmString = NULL;
|
||||
char * myEnvString = NULL;
|
||||
unsigned int decoLen;
|
||||
ptrdiff_t ptr;
|
||||
inheritance inherit;
|
||||
|
@ -1256,9 +1270,12 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
|
|||
** then isMultiProcess will already be set.
|
||||
** If not, we'll set it below.
|
||||
*/
|
||||
if (isMultiProcess)
|
||||
if (isMultiProcess) {
|
||||
if (cache && cache->sharedCache) {
|
||||
cache->sharedCache->everInherited = PR_TRUE;
|
||||
}
|
||||
return SECSuccess; /* already done. */
|
||||
|
||||
}
|
||||
ssl_sid_lookup = ServerSessionIDLookup;
|
||||
ssl_sid_cache = ServerSessionIDCache;
|
||||
ssl_sid_uncache = ServerSessionIDUncache;
|
||||
|
@ -1270,15 +1287,15 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
|
|||
return SECFailure;
|
||||
}
|
||||
}
|
||||
envString = PORT_Strdup(envString);
|
||||
if (!envString)
|
||||
myEnvString = PORT_Strdup(envString);
|
||||
if (!myEnvString)
|
||||
return SECFailure;
|
||||
fmString = strchr(envString, ',');
|
||||
fmString = strchr(myEnvString, ',');
|
||||
if (!fmString)
|
||||
goto loser;
|
||||
*fmString++ = 0;
|
||||
|
||||
decoString = ATOB_AsciiToData(envString, &decoLen);
|
||||
decoString = ATOB_AsciiToData(myEnvString, &decoLen);
|
||||
if (!decoString) {
|
||||
SET_ERROR_CODE
|
||||
goto loser;
|
||||
|
@ -1294,34 +1311,39 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
|
|||
goto loser;
|
||||
}
|
||||
|
||||
memset(&my, 0, sizeof my);
|
||||
my.sharedMemSize = inherit.sharedMemSize;
|
||||
memset(cache, 0, sizeof *cache);
|
||||
cache->cacheMemSize = inherit.cacheMemSize;
|
||||
|
||||
/* Create cache */
|
||||
my.cacheMemMap = PR_ImportFileMapFromString(fmString);
|
||||
if(! my.cacheMemMap) {
|
||||
cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
|
||||
if(! cache->cacheMemMap) {
|
||||
goto loser;
|
||||
}
|
||||
my.sharedMem = PR_MemMap(my.cacheMemMap, 0, my.sharedMemSize);
|
||||
if (! my.sharedMem) {
|
||||
cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
|
||||
if (! cache->cacheMem) {
|
||||
goto loser;
|
||||
}
|
||||
my.sharedCache = (cacheDesc *)my.sharedMem;
|
||||
cache->sharedCache = (cacheDesc *)cache->cacheMem;
|
||||
|
||||
if (my.sharedCache->sharedMemSize != my.sharedMemSize) {
|
||||
if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
|
||||
SET_ERROR_CODE
|
||||
goto loser;
|
||||
}
|
||||
|
||||
memcpy(cache, my.sharedCache, sizeof *cache);
|
||||
cache->cacheMemMap = my.cacheMemMap;
|
||||
cache->sharedMem = my.sharedMem;
|
||||
cache->sharedCache = my.sharedCache;
|
||||
/* We're now going to overwrite the local cache instance with the
|
||||
** shared copy of the cache struct, then update several values in
|
||||
** the local cache using the values for cache->cacheMemMap and
|
||||
** cache->cacheMem computed just above. So, we copy cache into
|
||||
** the automatic variable "my", to preserve the variables while
|
||||
** cache is overwritten.
|
||||
*/
|
||||
my = *cache; /* save values computed above. */
|
||||
memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
|
||||
|
||||
/* Fix pointers in our private copy of cache descriptor to point to
|
||||
** spaces in shared memory
|
||||
** spaces in shared memory, whose address is now in "my".
|
||||
*/
|
||||
ptr = (ptrdiff_t)cache->sharedMem;
|
||||
ptr = (ptrdiff_t)my.cacheMem;
|
||||
*(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
|
||||
*(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
|
||||
*(ptrdiff_t *)(&cache->certCacheLock) += ptr;
|
||||
|
@ -1330,49 +1352,66 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
|
|||
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
|
||||
*(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
|
||||
|
||||
cache->cacheMemMap = my.cacheMemMap;
|
||||
cache->cacheMem = my.cacheMem;
|
||||
cache->sharedCache = (cacheDesc *)cache->cacheMem;
|
||||
|
||||
#ifdef WINNT
|
||||
/* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
|
||||
When NT fibers are used in a multi-process server, a second level of
|
||||
locking is needed to prevent a deadlock, in case a fiber acquires the
|
||||
cross-process mutex, yields, and another fiber is later scheduled on
|
||||
the same native thread and tries to acquire the cross-process mutex.
|
||||
We do this by using a PRLock in the sslMutex. However, it is stored in
|
||||
shared memory as part of sidCacheLocks, and we don't want to overwrite
|
||||
the PRLock of the parent process. So we need to make new, private
|
||||
copies of sidCacheLocks before modifying the sslMutex with our own
|
||||
PRLock
|
||||
** When NT fibers are used in a multi-process server, a second level of
|
||||
** locking is needed to prevent a deadlock, in case a fiber acquires the
|
||||
** cross-process mutex, yields, and another fiber is later scheduled on
|
||||
** the same native thread and tries to acquire the cross-process mutex.
|
||||
** We do this by using a PRLock in the sslMutex. However, it is stored in
|
||||
** shared memory as part of sidCacheLocks, and we don't want to overwrite
|
||||
** the PRLock of the parent process. So we need to make new, private
|
||||
** copies of sidCacheLocks before modifying the sslMutex with our own
|
||||
** PRLock
|
||||
*/
|
||||
|
||||
newLocks = (sidCacheLock*)PORT_Alloc(sizeof(sidCacheLock)*(cache->numSIDCacheLocks + 2));
|
||||
/* note from jpierre : this should be free'd in child processes when
|
||||
a function is added to delete the SSL session cache in the future */
|
||||
/* fix the locks */
|
||||
for (locks_to_initialize = cache->numSIDCacheLocks + 2;
|
||||
locks_initialized < locks_to_initialize;
|
||||
++locks_initialized) {
|
||||
/* copy the old lock */
|
||||
memcpy(&newLocks[locks_initialized], &cache->sidCacheLocks[locks_initialized], sizeof(sidCacheLock));
|
||||
/* now, make a local PRLock in this sslMutex for this child process */
|
||||
sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
|
||||
}
|
||||
|
||||
/* then, make our cache object point to our new private sidCacheLocks */
|
||||
/* first the session cache */
|
||||
** a function is added to delete the SSL session cache in the future.
|
||||
*/
|
||||
locks_to_initialize = cache->numSIDCacheLocks + 2;
|
||||
newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
|
||||
cache->sidCacheLocks = newLocks;
|
||||
if (!newLocks)
|
||||
goto loser;
|
||||
/* copy the old locks */
|
||||
memcpy(newLocks, cache->sidCacheLocks,
|
||||
locks_to_initialize * sizeof(sidCacheLock));
|
||||
/* fix the locks */
|
||||
for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
|
||||
/* now, make a local PRLock in this sslMutex for this child process */
|
||||
SECStatus err;
|
||||
err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
|
||||
if (err != SECSuccess) {
|
||||
cache->numSIDCacheLocksInitialized = locks_initialized;
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
cache->numSIDCacheLocksInitialized = locks_initialized;
|
||||
|
||||
/* also fix the key and cert cache which use the last 2 lock entries */
|
||||
cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
|
||||
cache->certCacheLock = cache->keyCacheLock + 1;
|
||||
#endif
|
||||
|
||||
PORT_Free(myEnvString);
|
||||
PORT_Free(decoString);
|
||||
|
||||
/* mark that we have inherited this. */
|
||||
cache->sharedCache->everInherited = PR_TRUE;
|
||||
isMultiProcess = PR_TRUE;
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
PORT_Free(myEnvString);
|
||||
if (decoString)
|
||||
PORT_Free(decoString);
|
||||
CloseCache(cache);
|
||||
return SECFailure;
|
||||
|
||||
}
|
||||
|
||||
SECStatus
|
||||
|
|
Загрузка…
Ссылка в новой задаче