is krb5_cc_initialize() thread safe

Ken Hornstein kenh at cmf.nrl.navy.mil
Thu Feb 20 18:21:44 EST 2025


>I haven't been able to find in documentation whether or not
>krb5_cc_initialize() is thread safe? From a practical point of view, I
>believe it is not. But a call to "krb5_is_thread_safe() returns true".
>
>In NFS's gssd implementation, while trying to refresh credentials, the
>code tries to store creds and as part of calls into
>krb5_cc_initialize() to initial credential cache (of either FILE or
>MEMORY type). We've observed that if two threads try to update the
>same cache and thus call into krb5_cc_initialize(), one succeeds and
>the other fails with "Internal credentials cache error". Is that
>unexpected?

It sure seems like it's supposed to be thread safe.  On a relatively
modern MIT Kerberos, in krb5_mcc_initialize() (the initialize function
for the MEMORY cache):

    k5_cc_mutex_lock(context, &d->lock);
    ret = init_mcc_cache(context, d, princ);
    k5_cc_mutex_unlock(context, &d->lock);

But digging into this further, the only way init_mcc_cache() can fail
is if krb5_copy_principal() fails, and there's no way that can return
"Internal credential cache error".  So if you're really getting that
from a MEMORY cache, I don't see how that's possible (it doesn't seem
like there is any code in the memory cache that returns that error).

In fcc_initialize() (the equivalent function for the FILE cache) the
whole function has a krb5_cc_mutex_lock()/krb5_cc_mutex_unlock() around
the guts of the function, and the actual cache file is locked as well.
The FILE cache code can return KRB5_FCC_INTERNAL, but only if a system
call returns a set of specific error codes, which right now are:
a
    case EINVAL:
    case EEXIST:
    case EFAULT:
    case EBADF:
#ifdef EWOULDBLOCK
    case EWOULDBLOCK:
#endif
        ret = KRB5_FCC_INTERNAL;

--Ken


More information about the krbdev mailing list