From e2156e69cc87850cac455c1e16776bbd64cacf10 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Wed, 14 Aug 2024 18:08:17 +0200 Subject: [PATCH] LU-18145 gss: fix key unlink for regular user In case a key is unlinked for a regular user, it can be necessary to switch credentials to find a valid keyring for that user, which implies changing the user namespace as well. This needs a reference drop on the original namespace, as a ref was taken by prepare_creds(), and also to take a reference on the newly set namespace, as a ref will be dropped when put_cred() is finally called. Because of the user switch, calling get_user_keyring() also adds one more ref on the user keyring, for kernel implementation based on user keyring pinned from the user_struct struct. This extra ref needs to be dropped, but just for this specific case. Test-Parameters: trivial Test-Parameters: testgroup=review-dne-selinux-ssk-part-1 Test-Parameters: testgroup=review-dne-selinux-ssk-part-2 Test-Parameters: kerberos=true testlist=sanity-krb5 Fixes: bc740feeaa ("LU-17714 gss: support revoked session keyring") Signed-off-by: Sebastien Buisson Change-Id: I4d8fb354394a9f97dedf8aca84e4e3381a98fc60 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56053 Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Reviewed-by: Bruno Faccini Tested-by: jenkins Tested-by: Maloo --- lustre/ptlrpc/gss/gss_keyring.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lustre/ptlrpc/gss/gss_keyring.c b/lustre/ptlrpc/gss/gss_keyring.c index c34db45..0b705ea 100644 --- a/lustre/ptlrpc/gss/gss_keyring.c +++ b/lustre/ptlrpc/gss/gss_keyring.c @@ -759,9 +759,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) break; fallthrough; case KEY_REQKEY_DEFL_SESSION_KEYRING: - rcu_read_lock(); - dest_keyring = key_get(rcu_dereference(cred->session_keyring)); - rcu_read_unlock(); + dest_keyring = get_session_keyring(cred); if (dest_keyring) { if (!test_bit(KEY_FLAG_REVOKED, &dest_keyring->flags)) break; @@ -808,7 +806,10 @@ static void request_key_unlink(struct key *key, bool fullsearch) new_cred->uid = key->uid; new_cred->user->uid = key->uid; - new_cred->user_ns = &init_user_ns; + if (new_cred->user_ns != &init_user_ns) { + put_user_ns(new_cred->user_ns); + new_cred->user_ns = get_user_ns(&init_user_ns); + } #ifdef HAVE_USER_UID_KEYRING root_uid_keyring = current_cred()->user->uid_keyring; new_cred->user->uid_keyring = NULL; @@ -851,7 +852,8 @@ search: * for kernel implementation based on user keyring pinned from * the user_struct struct. */ - key_put(ring); + if (key_uid && !fullsearch) + key_put(ring); if (root_uid_keyring) current_cred()->user->uid_keyring = root_uid_keyring; #endif -- 1.8.3.1