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 <[email protected]> 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 <[email protected]
> <mailto:[email protected]>> 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/
>
--
Regards,
Sachidananda Sahu
+91-9035265767