Whamcloud - gitweb
LU-12634 gss: uid_keyring and session_keyring moved 43/35743/17
authorShaun Tancheff <stancheff@cray.com>
Fri, 3 Jan 2020 20:10:58 +0000 (15:10 -0500)
committerOleg Drokin <green@whamcloud.com>
Sat, 1 Feb 2020 08:10:26 +0000 (08:10 +0000)
Linux 5.3 removed uid_keyring and session_keyring from user_struct
Prefer the lookup_user_key() API when it is available (~5.0)
Prefer get_request_key_auth() when it is available (~5.0)

kernel-commit: 0f44e4d976f96c6439da0d6717238efa4b91196e
kernel-commit: 822ad64d7e46a8e2c8b8a796738d7b657cbb146d

Remove LC_HAVE_CRED_TGCRED which is no longer used.

Test-Parameters: envdefinitions=SHARED_KEY=true,SANITY_SEC_EXCEPT=30b testlist=sanity,recovery-small,sanity-sec
Cray-bug-id: LUS-7689
Signed-off-by: Shaun Tancheff <stancheff@cray.com>
Change-Id: I6d551cd8a9e317b717a43cba9be57f184a281c0a
Reviewed-on: https://review.whamcloud.com/35743
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Petros Koutoupis <pkoutoupis@cray.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/autoconf/lustre-libcfs.m4
lustre/autoconf/lustre-core.m4
lustre/ptlrpc/gss/gss_keyring.c

index 09ea8f6..0c384d4 100644 (file)
@@ -1052,6 +1052,58 @@ EXTRA_KCFLAGS="$tmp_flags"
 ]) # LIBCFS_HAVE_IOV_ITER_TYPE
 
 #
+# LIBCFS_GET_REQUEST_KEY_AUTH
+#
+# kernel 5.0 commit 822ad64d7e46a8e2c8b8a796738d7b657cbb146d
+# keys: Fix dependency loop between construction record and auth key
+#
+# Added <keys/request_key_auth-type.h> and get_request_key_auth()
+# which was propagated to stable
+#
+AC_DEFUN([LIBCFS_GET_REQUEST_KEY_AUTH], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if get_request_key_auth() is available],
+get_request_key_auth_exported, [
+       #include <linux/key.h>
+       #include <linux/keyctl.h>
+       #include <keys/request_key_auth-type.h>
+],[
+       struct key *ring;
+       const struct key *key = NULL;
+       struct request_key_auth *rka = get_request_key_auth(key);
+
+       ring = key_get(rka->dest_keyring);
+],[
+       AC_DEFINE(HAVE_GET_REQUEST_KEY_AUTH, 1,
+               [get_request_key_auth() is available])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LIBCFS_GET_REQUEST_KEY_AUTH
+
+#
+# LIBCFS_LOOKUP_USER_KEY
+#
+# kernel 5.3 commit 3cf5d076fb4d48979f382bc9452765bf8b79e740
+# signal: Remove task parameter from force_sig
+#
+AC_DEFUN([LIBCFS_LOOKUP_USER_KEY], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if lookup_user_key() is available],
+lookup_user_key_exported, [
+       #include <linux/key.h>
+       #include <linux/keyctl.h>
+],[
+       lookup_user_key(KEY_SPEC_USER_KEYRING, 0, 0);
+],[
+       AC_DEFINE(HAVE_LOOKUP_USER_KEY, 1,
+               [lookup_user_key() is available])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LIBCFS_LOOKUP_USER_KEY
+
+#
 # LIBCFS_FORCE_SIG_WITH_TASK
 #
 # kernel 5.3 commit 3cf5d076fb4d48979f382bc9452765bf8b79e740
@@ -1185,7 +1237,9 @@ LIBCFS_CLEAR_AND_WAKE_UP_BIT
 LIBCFS_HAVE_IOV_ITER_TYPE
 # 5.0
 LIBCFS_MM_TOTALRAM_PAGES_FUNC
+LIBCFS_GET_REQUEST_KEY_AUTH
 # 5.3
+LIBCFS_LOOKUP_USER_KEY
 LIBCFS_FORCE_SIG_WITH_TASK
 LIBCFS_CACHE_DETAIL_WRITERS
 ]) # LIBCFS_PROG_LINUX
index 73bac48..c6b5821 100644 (file)
@@ -232,23 +232,6 @@ AS_IF([test "x$enable_gss_keyring" != xno], [
 ]) # LC_CONFIG_GSS_KEYRING
 
 #
-# LC_HAVE_CRED_TGCRED
-#
-# rhel7 struct cred has no member tgcred
-#
-AC_DEFUN([LC_HAVE_CRED_TGCRED], [
-LB_CHECK_COMPILE([if 'struct cred' has member 'tgcred'],
-cred_tgcred, [
-       #include <linux/cred.h>
-],[
-       ((struct cred *)0)->tgcred = NULL;
-],[
-       AC_DEFINE(HAVE_CRED_TGCRED, 1,
-               [struct cred has member tgcred])
-])
-]) # LC_HAVE_CRED_TGCRED
-
-#
 # LC_KEY_TYPE_INSTANTIATE_2ARGS
 #
 # rhel7 key_type->instantiate takes 2 args (struct key, struct key_preparsed_payload)
@@ -293,7 +276,6 @@ AC_MSG_RESULT([$enable_gss])
 
 AS_IF([test "x$enable_gss" != xno], [
        LC_CONFIG_GSS_KEYRING
-       LC_HAVE_CRED_TGCRED
        LC_KEY_TYPE_INSTANTIATE_2ARGS
        sunrpc_required=$enable_gss
        LC_CONFIG_SUNRPC
index cd9dc89..204cf7c 100644 (file)
 #include "gss_internal.h"
 #include "gss_api.h"
 
+#ifdef HAVE_GET_REQUEST_KEY_AUTH
+#include <keys/request_key_auth-type.h>
+#endif
+
 static struct ptlrpc_sec_policy gss_policy_keyring;
 static struct ptlrpc_ctx_ops gss_keyring_ctxops;
 static struct key_type gss_key_type;
@@ -82,45 +86,6 @@ static int sec_install_rctx_kr(struct ptlrpc_sec *sec,
  * internal helpers                     *
  ****************************************/
 
-#define DUMP_PROCESS_KEYRINGS(tsk)                                     \
-{                                                                      \
-       CWARN("DUMP PK: %s[%u,%u/%u](<-%s[%u,%u/%u]): "                 \
-             "a %d, t %d, p %d, s %d, u %d, us %d, df %d\n",           \
-             tsk->comm, tsk->pid, tsk->uid, tsk->fsuid,                \
-             tsk->parent->comm, tsk->parent->pid,                      \
-             tsk->parent->uid, tsk->parent->fsuid,                     \
-             tsk->request_key_auth ?                                   \
-             tsk->request_key_auth->serial : 0,                        \
-             key_cred(tsk)->thread_keyring ?                           \
-             key_cred(tsk)->thread_keyring->serial : 0,                \
-             key_tgcred(tsk)->process_keyring ?                        \
-             key_tgcred(tsk)->process_keyring->serial : 0,             \
-             key_tgcred(tsk)->session_keyring ?                        \
-             key_tgcred(tsk)->session_keyring->serial : 0,             \
-             key_cred(tsk)->user->uid_keyring ?                        \
-             key_cred(tsk)->user->uid_keyring->serial : 0,             \
-             key_cred(tsk)->user->session_keyring ?                    \
-             key_cred(tsk)->user->session_keyring->serial : 0,         \
-             key_cred(tsk)->jit_keyring                                \
-            );                                                         \
-}
-
-#define DUMP_KEY(key)                                                   \
-{                                                                       \
-       CWARN("DUMP KEY: %p(%d) ref %d u%u/g%u desc %s\n",              \
-             key, key->serial, ll_read_key_usage(key),                 \
-             key->uid, key->gid,                                       \
-             key->description ? key->description : "n/a"               \
-            );                                                         \
-}
-
-#define key_cred(tsk)   ((tsk)->cred)
-#ifdef HAVE_CRED_TGCRED
-#define key_tgcred(tsk) ((tsk)->cred->tgcred)
-#else
-#define key_tgcred(tsk) key_cred(tsk)
-#endif
-
 static inline void keyring_upcall_lock(struct gss_sec_keyring *gsec_kr)
 {
 #ifdef HAVE_KEYRING_UPCALL_SERIALIZED
@@ -651,41 +616,103 @@ static inline int user_is_root(struct ptlrpc_sec *sec, struct vfs_cred *vcred)
 }
 
 /*
+ * kernel 5.3: commit 0f44e4d976f96c6439da0d6717238efa4b91196e
+ * keys: Move the user and user-session keyrings to the user_namespace
+ *
+ * When lookup_user_key is available use the kernel API rather than directly
+ * accessing the uid_keyring and session_keyring via the current process
+ * credentials.
+ */
+#ifdef HAVE_LOOKUP_USER_KEY
+
+/* from Linux security/keys/internal.h: */
+#ifndef KEY_LOOKUP_FOR_UNLINK
+#define KEY_LOOKUP_FOR_UNLINK          0x04
+#endif
+
+static struct key *_user_key(key_serial_t id)
+{
+       key_ref_t ref;
+
+       might_sleep();
+       ref = lookup_user_key(id, KEY_LOOKUP_FOR_UNLINK, 0);
+       if (IS_ERR(ref))
+               return NULL;
+       return key_ref_to_ptr(ref);
+}
+
+static inline struct key *get_user_session_keyring(const struct cred *cred)
+{
+       return _user_key(KEY_SPEC_USER_SESSION_KEYRING);
+}
+
+static inline struct key *get_user_keyring(const struct cred *cred)
+{
+       return _user_key(KEY_SPEC_USER_KEYRING);
+}
+#else
+static inline struct key *get_user_session_keyring(const struct cred *cred)
+{
+       return key_get(cred->user->session_keyring);
+}
+
+static inline struct key *get_user_keyring(const struct cred *cred)
+{
+       return key_get(cred->user->uid_keyring);
+}
+#endif
+
+/*
  * unlink request key from it's ring, which is linked during request_key().
  * sadly, we have to 'guess' which keyring it's linked to.
  *
- * FIXME this code is fragile, depend on how request_key_link() is implemented.
+ * FIXME this code is fragile, it depends on how request_key() is implemented.
  */
 static void request_key_unlink(struct key *key)
 {
-       struct task_struct *tsk = current;
-       struct key *ring;
+       const struct cred *cred = current_cred();
+       struct key *ring = NULL;
 
-       switch (key_cred(tsk)->jit_keyring) {
+       switch (cred->jit_keyring) {
        case KEY_REQKEY_DEFL_DEFAULT:
+       case KEY_REQKEY_DEFL_REQUESTOR_KEYRING:
+#ifdef HAVE_GET_REQUEST_KEY_AUTH
+               if (cred->request_key_auth) {
+                       struct request_key_auth *rka;
+                       struct key *authkey = cred->request_key_auth;
+
+                       down_read(&authkey->sem);
+                       rka = get_request_key_auth(authkey);
+                       if (!test_bit(KEY_FLAG_REVOKED, &authkey->flags))
+                               ring = key_get(rka->dest_keyring);
+                       up_read(&authkey->sem);
+                       if (ring)
+                               break;
+               }
+#endif
+               /* fall through */
        case KEY_REQKEY_DEFL_THREAD_KEYRING:
-               ring = key_get(key_cred(tsk)->thread_keyring);
+               ring = key_get(cred->thread_keyring);
                if (ring)
                        break;
                /* fallthrough */
        case KEY_REQKEY_DEFL_PROCESS_KEYRING:
-               ring = key_get(key_tgcred(tsk)->process_keyring);
+               ring = key_get(cred->process_keyring);
                if (ring)
                        break;
                /* fallthrough */
        case KEY_REQKEY_DEFL_SESSION_KEYRING:
                rcu_read_lock();
-               ring = key_get(rcu_dereference(key_tgcred(tsk)
-                                              ->session_keyring));
+               ring = key_get(rcu_dereference(cred->session_keyring));
                rcu_read_unlock();
                if (ring)
                        break;
                /* fallthrough */
        case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
-               ring = key_get(key_cred(tsk)->user->session_keyring);
+               ring = get_user_session_keyring(cred);
                break;
        case KEY_REQKEY_DEFL_USER_KEYRING:
-               ring = key_get(key_cred(tsk)->user->uid_keyring);
+               ring = get_user_keyring(cred);
                break;
        case KEY_REQKEY_DEFL_GROUP_KEYRING:
        default:
@@ -1310,15 +1337,15 @@ int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
          * the session keyring is created upon upcall, and don't change all
          * the way until upcall finished, so rcu lock is not needed here.
          */
-       LASSERT(key_tgcred(current)->session_keyring);
+       LASSERT(current_cred()->session_keyring);
 
        lockdep_off();
-       rc = key_link(key_tgcred(current)->session_keyring, key);
+       rc = key_link(current_cred()->session_keyring, key);
        lockdep_on();
        if (unlikely(rc)) {
                CERROR("failed to link key %08x to keyring %08x: %d\n",
                       key->serial,
-                      key_tgcred(current)->session_keyring->serial, rc);
+                      current_cred()->session_keyring->serial, rc);
                RETURN(rc);
        }