[openldap] fix: NSS_Init* functions are not thread safe

jvcelak jvcelak at fedoraproject.org
Wed Aug 24 17:35:47 UTC 2011


commit 67c9630d50c7129ffced2b9739431b6cb7e770c4
Author: Jan Vcelak <jvcelak at redhat.com>
Date:   Wed Aug 24 18:18:33 2011 +0200

    fix: NSS_Init* functions are not thread safe
    
    Resolves: #731112

 openldap-nss-init-threadsafe.patch |  217 ++++++++++++++++++++++++++++++++++++
 openldap.spec                      |    3 +
 2 files changed, 220 insertions(+), 0 deletions(-)
---
diff --git a/openldap-nss-init-threadsafe.patch b/openldap-nss-init-threadsafe.patch
new file mode 100644
index 0000000..6ef0976
--- /dev/null
+++ b/openldap-nss-init-threadsafe.patch
@@ -0,0 +1,217 @@
+NSS_Init* functions are not thread safe
+
+The NSS_InitContext et. al, and their corresponding shutdown functions,
+are not thread safe.  There can only be one thread at a time calling
+these functions.  Protect the calls with a mutex.  Create the mutex
+using a PR_CallOnce to ensure that the mutex is only created once and
+not used before created.  Move the registration of the nss shutdown
+callback to also use a PR_CallOnce.  Removed the call to
+SSL_ClearSessionCache() because it is always called at shutdown, and we must
+not call it more than once.
+
+Resolves: #731112
+Author: Rich Megginson <rmeggins at redhat.com>
+Upstream ITS: #7022
+---
+ libraries/libldap/tls_m.c |   98 +++++++++++++++++++++++++++++++++++++++++---
+ 1 files changed, 91 insertions(+), 7 deletions(-)
+
+diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
+index 997b3eb..30c8a76 100644
+--- a/libraries/libldap/tls_m.c
++++ b/libraries/libldap/tls_m.c
+@@ -130,9 +130,29 @@ static int tlsm_init( void );
+ 
+ #ifdef LDAP_R_COMPILE
+ 
++/* it doesn't seem guaranteed that a client will call
++   tlsm_thr_init in a non-threaded context - so we have
++   to wrap the mutex creation in a prcallonce
++*/
++static ldap_pvt_thread_mutex_t tlsm_init_mutex;
++static PRCallOnceType tlsm_init_mutex_callonce = {0,0};
++
++static PRStatus PR_CALLBACK
++tlsm_thr_init_callonce( void )
++{
++	if ( ldap_pvt_thread_mutex_init( &tlsm_init_mutex ) ) {
++		Debug( LDAP_DEBUG_ANY,
++			   "TLS: could not create mutex for moznss initialization: %d\n", errno, 0, 0 );
++		return PR_FAILURE;
++	}
++
++	return PR_SUCCESS;
++}
++
+ static void
+ tlsm_thr_init( void )
+ {
++    ( void )PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce );
+ }
+ 
+ #endif /* LDAP_R_COMPILE */
+@@ -1079,7 +1099,6 @@ tlsm_nss_shutdown_cb( void *appData, void *nssData )
+ 	SECStatus rc = SECSuccess;
+ 
+ 	SSL_ShutdownServerSessionIDCache();
+-	SSL_ClearSessionCache();
+ 
+ 	if ( pem_module ) {
+ 		SECMOD_UnloadUserModule( pem_module );
+@@ -1089,6 +1108,24 @@ tlsm_nss_shutdown_cb( void *appData, void *nssData )
+ 	return rc;
+ }
+ 
++static PRCallOnceType tlsm_register_shutdown_callonce = {0,0};
++static PRStatus PR_CALLBACK
++tlsm_register_nss_shutdown_cb( void )
++{
++	if ( SECSuccess == NSS_RegisterShutdown( tlsm_nss_shutdown_cb,
++											 NULL ) ) {
++		return PR_SUCCESS;
++	}
++	return PR_FAILURE;
++}
++
++static PRStatus
++tlsm_register_nss_shutdown( void )
++{
++	return PR_CallOnce( &tlsm_register_shutdown_callonce,
++						tlsm_register_nss_shutdown_cb );
++}
++
+ static int
+ tlsm_init_pem_module( void )
+ {
+@@ -1529,6 +1566,12 @@ tlsm_deferred_init( void *arg )
+ 	initParams.length = sizeof( initParams );
+ #endif /* HAVE_NSS_INITCONTEXT */
+ 
++#ifdef LDAP_R_COMPILE
++	if ( PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce ) ) {
++		return -1;
++	}
++#endif /* LDAP_R_COMPILE */
++
+ #ifndef HAVE_NSS_INITCONTEXT
+ 	if ( !NSS_IsInitialized() ) {
+ #endif /* HAVE_NSS_INITCONTEXT */
+@@ -1556,6 +1599,10 @@ tlsm_deferred_init( void *arg )
+ 			}
+ 
+ 			tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
++#ifdef LDAP_R_COMPILE
++			LDAP_MUTEX_LOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
++
+ #ifdef HAVE_NSS_INITCONTEXT
+ #ifdef INITCONTEXT_HACK
+ 			if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
+@@ -1574,6 +1621,10 @@ tlsm_deferred_init( void *arg )
+ 			rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
+ #endif
+ 
++#ifdef LDAP_R_COMPILE
++			LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
++
+ 			if ( rc != SECSuccess ) {
+ 				errcode = PORT_GetError();
+ 				if ( securitydirs[ii] != lt->lt_cacertdir) {
+@@ -1597,6 +1648,9 @@ tlsm_deferred_init( void *arg )
+ 		}
+ 
+ 		if ( errcode ) { /* no moznss db found, or not using moznss db */
++#ifdef LDAP_R_COMPILE
++			LDAP_MUTEX_LOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
+ #ifdef HAVE_NSS_INITCONTEXT
+ 			int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
+ #ifdef INITCONTEXT_HACK
+@@ -1615,6 +1669,9 @@ tlsm_deferred_init( void *arg )
+ #else
+ 			rc = NSS_NoDB_Init( NULL );
+ #endif
++#ifdef LDAP_R_COMPILE
++			LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
+ 			if ( rc != SECSuccess ) {
+ 				errcode = PORT_GetError();
+ 				Debug( LDAP_DEBUG_ANY,
+@@ -1628,13 +1685,22 @@ tlsm_deferred_init( void *arg )
+ #endif
+ 
+ 			/* initialize the PEM module */
++#ifdef LDAP_R_COMPILE
++			LDAP_MUTEX_LOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
+ 			if ( tlsm_init_pem_module() ) {
++#ifdef LDAP_R_COMPILE
++				LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
+ 				errcode = PORT_GetError();
+ 				Debug( LDAP_DEBUG_ANY,
+ 					   "TLS: could not initialize moznss PEM module - error %d:%s.\n",
+ 					   errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
+ 				return -1;
+ 			}
++#ifdef LDAP_R_COMPILE
++			LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
+ 
+ 			if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) {
+ 				/* if we tried to use lt->lt_cacertdir as an NSS key/cert db, errcode 
+@@ -1669,10 +1735,13 @@ tlsm_deferred_init( void *arg )
+ 		PK11_SetPasswordFunc( tlsm_pin_prompt );
+ 
+ 		/* register cleanup function */
+-		/* delete the old one, if any */
+-		NSS_UnregisterShutdown( tlsm_nss_shutdown_cb, NULL );
+-		NSS_RegisterShutdown( tlsm_nss_shutdown_cb, NULL );
+-
++		if ( tlsm_register_nss_shutdown() ) {
++			errcode = PORT_GetError();
++			Debug( LDAP_DEBUG_ANY,
++				   "TLS: could not register NSS shutdown function: %d:%s\n",
++				   errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
++			return -1;
++		}
+ #ifndef HAVE_NSS_INITCONTEXT
+ 	}
+ #endif /* HAVE_NSS_INITCONTEXT */
+@@ -1884,6 +1953,9 @@ tlsm_clientauth_init( tlsm_ctx *ctx )
+ static void
+ tlsm_destroy( void )
+ {
++#ifdef LDAP_R_COMPILE
++	ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex );
++#endif
+ }
+ 
+ static tls_ctx *
+@@ -1949,8 +2021,20 @@ tlsm_ctx_free ( tls_ctx *ctx )
+ 	PL_strfree( c->tc_slotname );		
+ 	tlsm_free_pem_objs( c );
+ #ifdef HAVE_NSS_INITCONTEXT
+-	if (c->tc_initctx)
+-		NSS_ShutdownContext( c->tc_initctx );
++	if ( c->tc_initctx ) {
++#ifdef LDAP_R_COMPILE
++		LDAP_MUTEX_LOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
++		if ( NSS_ShutdownContext( c->tc_initctx ) ) {
++			PRErrorCode errcode = PR_GetError();
++			Debug( LDAP_DEBUG_ANY,
++				   "TLS: could not shutdown NSS - error %d:%s.\n",
++				   errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
++ 		}
++#ifdef LDAP_R_COMPILE
++		LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
++#endif /* LDAP_R_COMPILE */
++	}
+ 	c->tc_initctx = NULL;
+ #endif /* HAVE_NSS_INITCONTEXT */
+ #ifdef LDAP_R_COMPILE
+-- 
+1.7.1
+
diff --git a/openldap.spec b/openldap.spec
index 27ef48f..2228687 100644
--- a/openldap.spec
+++ b/openldap.spec
@@ -30,6 +30,7 @@ Patch4: openldap-smbk5pwd-overlay.patch
 Patch5: openldap-ldaprc-currentdir.patch
 Patch6: openldap-userconfig-setgid.patch
 Patch7: openldap-nss-free-peer-cert.patch
+Patch8: openldap-nss-init-threadsafe.patch
 
 # patches for the evolution library (see README.evolution)
 Patch200: openldap-evolution-ntlm.patch
@@ -130,6 +131,7 @@ pushd openldap-%{version}
 %patch5 -p1 -b .ldaprc-currentdir
 %patch6 -p1 -b .userconfig-setgid
 %patch7 -p1 -b .nss-free-peer-cert
+%patch8 -p1 -b .nss-init-threadsafe
 
 cp %{_datadir}/libtool/config/config.{sub,guess} build/
 
@@ -655,6 +657,7 @@ exit 0
 %changelog
 * Wed Aug 24 2011 Jan Vcelak <jvcelak at redhat.com> 2.4.26-2
 - security hardening: library needs partial RELRO support added (#733071)
+- fix: NSS_Init* functions are not thread safe (#731112)
 
 * Sun Aug 14 2011 Rex Dieter <rdieter at fedoraproject.org> - 2.4.26-1.1
 - Rebuilt for rpm (#728707)


More information about the scm-commits mailing list