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
On Tue, Aug 6, 2019 at 9:44 PM Howard Chu hyc@symas.com wrote:
sachidananda sahu wrote:
Hi All,
Any one can give a thought on this ?
Your problem description makes no sense. Unless you're explicitly calling ldap_set_option in multiple threads, the option structure is read-only.
The default libldap is not threadsafe, nor is it meant to be. You should probably be using libldap_r.
On Thu, Aug 1, 2019 at 7:55 PM sachidananda sahu <sachi059@gmail.com
mailto:sachi059@gmail.com> wrote:
Hi All, I recently upgraded to openldap 2.4.47, it's working with single
threaded connection but with multi threaded getting problem due to global structure of
ldapoptions in init.c ------------------------- init.c ------------------------- *struct* ldapoptions ldap_int_global_options = { LDAP_UNINITIALIZED , LDAP_DEBUG_NONE, LDAP_LDO_NULLARG , LDAP_LDO_CONNECTIONLESS_NULLARG, LDAP_LDO_TLS_NULLARG, LDAP_LDO_SASL_NULLARG , LDAP_LDO_GSSAPI_NULLARG, LDAP_LDO_MUTEX_NULLARG };, This global structure is accessed at multiple places (such as
ldap_pvt_tls_init_def_ctx , alloc_handle, ldap_int_tls_connect , *ldap_pvt_tls_destroy , ldap_ld_free*)
in tls2.c using the macro lo = LDAP_INT_GLOBAL_OPT (); So in case of multi threaded application multiple ldap connection
will be using this global structure, for example ldo_tls_ctx of lapoptions will be used.
In one thread it can be creating a tls connection and in one it can
be destroying the connection. As it's global so it is getting corrupted.
Is openldap library thread safe completely ? Because this variable
seems to be not for this tls context variable, is there any other way of using this
context . As i can see a local variable ldo_tls_ctx exist in dap
ld->ldc->ldap_options->ldo_tls_ctx structure, but it's just got assigned with the same
address of global structure in ldap_int_tls_connect. So can someone share some thoughts on it ? -- Regards, Sachidananda Sahu
-- Regards, Sachidananda Sahu +91-9035265767
-- -- Howard Chu CTO, Symas Corp. http://www.symas.com Director, Highland Sun http://highlandsun.com/hyc/ Chief Architect, OpenLDAP http://www.openldap.org/project/