[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#6018) TLS memory leak



I see at least two issues in your code.  See below for specific comments.

ling qing wrote:
> The sample code is as follows.
> Make command:
> g++ testmem.C lib/libldap-2.4.so.2 lib/libsasl2.so.2 lib/liblber-2.4.so.2
> -Iinclude/ -Llib/ -DLDAP_DEPRECATED -g -lpthread
> If mode is normal, it's ok. If mode is TLS, there is memory leak even if you
> don't input bind dn. If mode is SSL, memory leak only happens when you input
> bind dn and password.
> The openLDAP lib is the latest release version 2.4.15.
> 
> I am sure that this is a bug of openLDAP.
> 
> #include "ldap.h"
> #include <string>
> #include <unistd.h>
> 
> using namespace std;
> 
> typedef enum LDAP_TRANS_METHOD {LDAP_TRANS_NORMAL, LDAP_TRANS_TLS,
> LDAP_TRANS_SSL};
> 
> LDAP_TRANS_METHOD transMethod = LDAP_TRANS_NORMAL;
> const char * host = NULL;
> const char * binddn = NULL;
> const char * bindpwd = NULL;
> int connectnum = 0;
> 
> void * connectLDAP(void * param)
> {
>     LDAP * ld;
> 
>   int rc;
>   string url;
>   if( transMethod == LDAP_TRANS_SSL )
>       url = "ldaps://";
>   else
>       url = "ldap://";;
>   if( host == NULL )
>       return NULL;
>   url.append(host);
> 
>   struct timeval tvout;
>   tvout.tv_sec = 10;
>   tvout.tv_usec = 0;
> 
>     if( ldap_set_option( NULL, LDAP_OPT_NETWORK_TIMEOUT, &tvout ) !=
> LDAP_OPT_SUCCESS )
>     {
>         printf("ldap_set_option LDAP_OPT_NETWORK_TIMEOUT failed\n");
>         return NULL;
>     }
> 
>   rc = ldap_initialize(&ld, url.c_str());
>   if( rc != LDAP_SUCCESS || ld == NULL )
>   {
>       printf("ldap_initialize failed!\n");
>     return NULL;
>   }
> 
>   if( transMethod == LDAP_TRANS_TLS || transMethod == LDAP_TRANS_SSL )
>   {
>         int protocol = 3;
>     if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) !=
> LDAP_OPT_SUCCESS )
>     {
>             printf("ldap_set_option LDAP_OPT_PROTOCOL_VERSION failed\n");
>         return NULL;
>     }
>     int cert = 0;
>     if( ldap_set_option( NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &cert ) !=
> LDAP_OPT_SUCCESS )

You're not supposed to call ldap_set_option() with NULL handler from 
within a threaded program, as libldap is thread-safe only when a 
specific handler is only used from within a single thread.  I'm not 
discussing the case of this specific option, nor of its side-effects, if 
any, as I didn't investigate it and I'm not specifically familiar with 
that portion of code.

>     {
>           printf("ldap_set_option LDAP_OPT_X_TLS_REQUIRE_CERT failed\n");
>         return NULL;
>     }
>   }
> 
>   if( transMethod == LDAP_TRANS_TLS )
>   {
>     rc = ldap_start_tls_s( ld, NULL, NULL );
>     if( rc != LDAP_SUCCESS )
>     {
>           printf("ldap_start_tls_s failed\n");
>         return NULL;
>     }
>   }
> 
>     if( binddn != NULL && bindpwd != NULL )
>     {
>         rc = ldap_bind_s(ld,  binddn, bindpwd, LDAP_AUTH_SIMPLE);
>       if ( LDAP_SUCCESS != rc )
>       {
>           printf("ldap_bind_s failed\n");
>       return NULL;
>       }
>     }

This code is filled with "return NULL;" without cleaning up memory if 
anything goes wrong.  Are you sure everything is always going fine for 
all your threads during your tests?

> 
>     ldap_unbind_s(ld);
>     connectnum++;
>     printf("%d connect ok\n", connectnum);
>     return NULL;
> }
> 
> int main(int argc, char ** argv)
> {
>     if(argc < 2)
>     {
>         printf("Usage: testmem <host> [mode] [bind dn] [bind pwd]\n");
>         printf("mode: default: NORMAL; SSL;TLS\n");
>         return 0;
>     }
>     string mode="NORMAL";
>     if( argc > 2 )
>         mode = argv[2];
> 
>     if( mode == "SSL" )
>         transMethod = LDAP_TRANS_SSL;
>   if( mode == "TLS" )
>     transMethod = LDAP_TRANS_TLS;
>   host = argv[1];
> 
>     if( argc > 4 )
>     {
>       binddn = argv[3];
>       bindpwd = argv[4];
>      }
> 
>   do
>   {
>     pthread_t instance_thread ;
>       pthread_attr_t attr;
>       pthread_attr_init(&attr);
>       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
>       int rc = pthread_create(&instance_thread, &attr, connectLDAP, NULL) ;
>       pthread_attr_destroy(&attr);
>     if (rc)
>     {
>         printf("Fail to create policy server instance thread\n") ;
>         break;
>     }
>     sleep(1);
>     }while(1);
>     return 0;
> }
> 



Ing. Pierangelo Masarati
OpenLDAP Core Team

SysNet s.r.l.
via Dossi, 8 - 27100 Pavia - ITALIA
http://www.sys-net.it
-----------------------------------
Office:  +39 02 23998309
Mobile:  +39 333 4963172
Fax:     +39 0382 476497
Email:   ando@sys-net.it
-----------------------------------