Whamcloud - gitweb
LU-17714 gss: protect against revoked session keyring 06/54706/5
authorSebastien Buisson <sbuisson@ddn.com>
Mon, 8 Apr 2024 15:52:50 +0000 (17:52 +0200)
committerOleg Drokin <green@whamcloud.com>
Tue, 21 May 2024 18:24:45 +0000 (18:24 +0000)
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 <sbuisson@ddn.com>
Change-Id: I64b6ac4693a47cf43d6fa1bf4e17bfb4907670fa
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54706
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Aurelien Degremont <adegremont@nvidia.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/ptlrpc/gss/gss_keyring.c

index 800b12f..9894825 100644 (file)
@@ -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,
+                            &current_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);