From 045ab5c0273a843493ed2d6d3486b41efe36b834 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Mon, 8 Apr 2024 17:52:50 +0200 Subject: [PATCH] LU-17714 gss: protect against revoked session keyring In case the session keyring is revoked, request_key() still tries to search it. Sadly this keyring is searched before the user keyring, so it will return -EKEYREVOKED, and the user keyring, that does contain the Lustre key, will not even be searched. To work around this issue in the kernel implementation of request_key, override the current process's credentials with no session keyring, if we detect it has been revoked. Test-Parameters: kerberos=true testlist=sanity-krb5 serverdistro=el8.9 Signed-off-by: Sebastien Buisson Change-Id: I64b6ac4693a47cf43d6fa1bf4e17bfb4907670fa Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54706 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Aurelien Degremont Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/ptlrpc/gss/gss_keyring.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lustre/ptlrpc/gss/gss_keyring.c b/lustre/ptlrpc/gss/gss_keyring.c index 800b12f..9894825 100644 --- a/lustre/ptlrpc/gss/gss_keyring.c +++ b/lustre/ptlrpc/gss/gss_keyring.c @@ -827,6 +827,8 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec, struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); struct ptlrpc_cli_ctx *ctx = NULL; unsigned int is_root = 0, create_new = 0; + const struct cred *old_cred = NULL; + struct cred *new_cred = NULL; struct key *key; char desc[24]; char *coinfo; @@ -968,9 +970,30 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec, CDEBUG(D_SEC, "requesting key for %s\n", desc); + if (vcred->vc_uid) { + /* If the session keyring is revoked, it must not be used by + * request_key(), otherwise we would get -EKEYREVOKED and + * the user keyring would not even be searched. + * So prepare new creds with no session keyring. + */ + if (current_cred()->session_keyring && + test_bit(KEY_FLAG_REVOKED, + ¤t_cred()->session_keyring->flags)) { + new_cred = prepare_creds(); + if (new_cred) { + new_cred->session_keyring = NULL; + old_cred = override_creds(new_cred); + } + } + } + keyring_upcall_lock(gsec_kr); key = request_key(&gss_key_type, desc, coinfo); keyring_upcall_unlock(gsec_kr); + if (old_cred) { + revert_creds(old_cred); + put_cred(new_cred); + } OBD_FREE(coinfo, coinfo_size); -- 1.8.3.1