Hi Howard,
Thanks for your response. I may be missing something, but let me share my thoughts based on code.
ldap_set_option called from many threads, not only that even ldap_int_tls_connect, ldap_pvt_tls_init_def_ctx as multiple thread can connect to LDAP server.
Based on code lookup, i feel not every members of option structure is read only.
Let's consider ldapoptions->ldo_tls_ctx which is global and can be used by many threads. Suppose there is two threads and thread A may be at point 1 and thread B may be at point 2, based on scheduling chances of getting it messed is more, which problem i am facing now. Have a look and please share in case my assumptions are wrong or i am missing something.
tls2.c
---------------------------
1. Let's see where ldo_tls_ctx get allocated.
ldap_pvt_tls_init_def_ctx( int is_server )
{
struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); // Accessed global option structure
int rc;
LDAP_MUTEX_LOCK( &tls_def_ctx_mutex );
rc = ldap_int_tls_init_ctx( lo, is_server ); // Inside this function lo->ldo_tls_ctx is allocated.
LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex );
return rc;
}
static int
ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
{
...
lo->ldo_tls_ctx = ti->ti_ctx_new( lo ); //The same global variable is allocated with memory
if ( lo->ldo_tls_ctx == NULL ) {
Debug( LDAP_DEBUG_ANY,
"TLS: could not allocate default ctx.\n",
0,0,0);
rc = -1;
goto error_exit;
}
...
}
2. Let's see where it's getting freed. ldo_tls_ctx the same from global option context.
ldap_pvt_tls_destroy( void )
{
struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
//Accessed the global structure
ldap_int_tls_destroy( lo );
...
}
void
ldap_int_tls_destroy( struct ldapoptions *lo )
{
if ( lo->ldo_tls_ctx ) {
ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); //Freeing the global tls context
lo->ldo_tls_ctx = NULL;
}
}
So if thread 1 where allocation done, and scheduling thread 2 at destroy part, thread 1 again got chance to access and fill some data , it's already freed by thread 2. If the tls context is part of global option structure and all threads will be viewing the same.
I can see a local ldo_tls_ctx exists per ld, but it's again being assigned with same global option ldo_tls_ctx.
static int
ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
{
...
Sockbuf *sb = conn->lconn_sb;
int err;
tls_session *ssl = NULL;
if ( HAS_TLS( sb )) {
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
} else {
struct ldapoptions *lo;
tls_ctx *ctx;
ctx = ld->ld_options.ldo_tls_ctx; //Accessing the local ldo_tls_ctx.
ssl = alloc_handle( ctx, 0 );
if ( ssl == NULL ) return -1;
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
#endif
ber_sockbuf_add_io( sb, tls_imp->ti_sbio,
LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
lo = LDAP_INT_GLOBAL_OPT();
if( ctx == NULL ) {
ctx = lo->ldo_tls_ctx; //Getting the ldo_tls_ctx from context from global context which was allocated inside alloc_handle further functions.
ld->ld_options.ldo_tls_ctx = ctx; // Assigned the same global context to local variable.
tls_ctx_ref( ctx );
}
...
Thanks
Sachidananda