[20529] in Kerberos_V5_Development

home help back first fref pref prev next nref lref last post

Re: is krb5_cc_initialize() thread safe

daemon@ATHENA.MIT.EDU (Olga Kornievskaia)
Mon Feb 24 02:03:09 2025

MIME-Version: 1.0
In-Reply-To: <9d7a1726-4f53-4d2f-9b4e-5b859f9d1a82@mit.edu>
From: Olga Kornievskaia <aglo@umich.edu>
Date: Sun, 23 Feb 2025 16:03:12 -0500
Message-ID: <CAN-5tyGTwHsCe9gxE8L4MC3hLhtBmtd67UafE7+87eQCrfcYRw@mail.gmail.com>
To: Greg Hudson <ghudson@mit.edu>
Cc: krbdev@mit.edu
Content-Type: text/plain; charset="utf-8"
Errors-To: krbdev-bounces@mit.edu
Content-Transfer-Encoding: 8bit

On Sat, Feb 22, 2025 at 3:04 AM Greg Hudson <ghudson@mit.edu> wrote:
>
> 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.

Thanks Greg. We'll work on changing gssd as you suggest.

> 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             krbdev@mit.edu
https://mailman.mit.edu/mailman/listinfo/krbdev


home help back first fref pref prev next nref lref last post