Re: is krb5_cc_initialize() thread safe
"Greg Hudson" <[email protected]> Sat, 22 Feb 2025 03:04:24 -0500
| Newsgroups | gmane.comp.encryption.kerberos.devel |
|---|---|
| Message-ID | <[email protected]> |
On 2/20/25 19:41, Olga Kornievskaia wrote: > Does this sound like there might be a (solvable) problem in the > krb5_cc_initiatize() that can guarantee that multiple threads can call > it simultaneously (on as you noted their own pointer of the > krb5_ccache structure that they have gotten from doing > krb5_cc_resolve() and both threads would get a non-error return from > the function? Maybe, but (1) it would be awkward, and (2) there are better solutions on the gssd end. Elaborating on (1): POSIX allows you to advisory-lock a file but not a pathname. krb5_cc_initialize() wants to replace the cache file, not truncate it, so that it doesn't invalidate iterations over the previous generation of the cache. Without adding a second persistent filesystem artifact to hang advisory locks onto, you can't lock around a file replacement. So we would be trying to work around races like: T1: unlink T1: open-exclusive (success) T1: lock new file T2: unlink T1: writes header (to a no-longer-linked file), unlocks, and returns T1 caller: thinks initialization is done, but the file doesn't exist! T2: locks file, writes header, unlocks file, and returns Elaborating on (2): gssd does krb5_get_init_creds_keytab() to get a TGT into memory, then krb5_cc_resolve(), krb5_cc_initialize(), and krb5_cc_store_cred(), similar to how kinit worked about fifteen years ago. According to the historical semantics of the ccache interface, there is inherently a window between the last two steps of this sequence where the cache exists but is useless because it contains no TGT. The sequence used by kinit -k since krb5-1.8 is: krb5_cc_resolve(), krb5_get_init_creds_opt_set_out_ccache(), krb5_get_init_creds_keytab(). (No krb5_cc_initialize() or krb5_cc_store_cred() calls; that is done by krb5_get_init_creds_keytab().) In krb5-1.20 or later, that will automatically use the atomic cache replacement mechanism I described in my first reply. This method also correctly saves some FAST-related cache config entries that otherwise get lost. It might also be possible to use gss_acquire_cred_from() and client keytab support to get rid of the whole process of explicitly acquiring credentials. But that would be a more expansive change. > And I'm also wondering what about other krb5_* functions are they > "safe" under concurrency or should gssd be doing any krb* api call > under a lock? I don't think you need to embark on a project of adding mutex locking around libkrb5 API calls. This is a very specific concurrency issue arising from the historic semantics of the libkrb5 credential cache API. _______________________________________________ krbdev mailing list [email protected] https://mailman.mit.edu/mailman/listinfo/krbdev