]) # 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
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
#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;
* 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
}
/*
+ * 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:
* 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);
}