rewrite gss_krb5_ccache_name

Jeffrey Hutzelman jhutz at cmu.edu
Fri Nov 21 22:28:54 EST 2008


--On Friday, November 21, 2008 08:44:04 PM -0500 Jeffrey Altman 
<jaltman at secure-endpoints.com> wrote:

> For thread safety reasons the gss library uses thread local storage
> (TLS) to store a number of values including ccache name and error
> messages.  The TLS stored value must be a copy in order to prevent
> corruption when the original source string is deallocated or altered.

In the example Stephen posted, he does the following:

    krb5_lock();
    if( neg_ctx->context == GSS_C_NO_CONTEXT){
        major_status =gss_krb5_ccache_name(&minor_status,krb5->ccache_name,
&old_name);
   :
   }
    major_status = gss_init_sec_context(&minor_status,
  :
    if(old_name)gss_krb5_ccache_name(&minor_status,old_name, NULL);
    krb5_unlock();


In this example, when the first call to gss_krb5_ccache_name() is called, 
the library makes a copy of krb5->ccache_name and stores it in TLS, as Jeff 
describes above.  It must make a copy, because, as Jeff hints, the library 
doesn't know that you aren't going to do something to that string after the 
call returns which changes it or makes it invalid, or do something like 
pass the same pointer to gss_krb5_ccache_name() in multiple threads.  It 
would be possible to have an alternative interface in which you pass 
&krb5->ccache_name and the library zeroes it, but that would likely be less 
convenient for this caller, and a number of others.  It would also mean 
that krb5->ccache_name would have to have been dynamically allocated by the 
caller, because the library's thread destructor has to free it if the 
thread exits or is cancelled without explicitly reclaiming the TLS.

The first call to gss_krb5_ccache_name() also returns in old_name the 
previous ccache name (or a dynamically-allocated copy, with the library's 
copy being freed).  Once the call returns, this value belongs to the 
caller; the library guarantees it no longer has a copy of it.  That also 
means it's the caller's to free.

The second call to gss_krb5_ccache_name() behaves exactly as the first.  It 
stores a copy of old_name, not the original, for the same reasons as 
before.  It also frees the previously-set value without returning it, since 
the third argument was given as NULL.


After the second call to gss_krb5_ccache_name(), old_name STILL belongs to 
the caller.  In this case it is the calling thread which is failing to free 
storage.



> If that is the case, the real bug here is that the gssapi32.dll
> does not implement a DLL_THREAD_DETACH routine which would free
> any allocated memory stored under the registered TLS keys.

Well, if you're not doing that, you certainly should...

-- Jeff



More information about the krbdev mailing list