]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop fscrypt patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Oct 2022 06:34:55 +0000 (08:34 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Oct 2022 06:34:55 +0000 (08:34 +0200)
queue-5.10/fscrypt-simplify-master-key-locking.patch [deleted file]
queue-5.10/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch [deleted file]
queue-5.10/series
queue-5.15/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch [deleted file]
queue-5.15/series
queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch [deleted file]
queue-5.19/series
queue-6.0/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch [deleted file]
queue-6.0/series

diff --git a/queue-5.10/fscrypt-simplify-master-key-locking.patch b/queue-5.10/fscrypt-simplify-master-key-locking.patch
deleted file mode 100644 (file)
index 7a953d5..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-From 49f9da1c3120bc16688a203dac6f292f4487d997 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 16 Nov 2020 19:26:26 -0800
-Subject: fscrypt: simplify master key locking
-
-From: Eric Biggers <ebiggers@google.com>
-
-[ Upstream commit 4a4b8721f1a5e4b01e45b3153c68d5a1014b25de ]
-
-The stated reasons for separating fscrypt_master_key::mk_secret_sem from
-the standard semaphore contained in every 'struct key' no longer apply.
-
-First, due to commit a992b20cd4ee ("fscrypt: add
-fscrypt_prepare_new_inode() and fscrypt_set_context()"),
-fscrypt_get_encryption_info() is no longer called from within a
-filesystem transaction.
-
-Second, due to commit d3ec10aa9581 ("KEYS: Don't write out to userspace
-while holding key semaphore"), the semaphore for the "keyring" key type
-no longer ranks above page faults.
-
-That leaves performance as the only possible reason to keep the separate
-mk_secret_sem.  Specifically, having mk_secret_sem reduces the
-contention between setup_file_encryption_key() and
-FS_IOC_{ADD,REMOVE}_ENCRYPTION_KEY.  However, these ioctls aren't
-executed often, so this doesn't seem to be worth the extra complexity.
-
-Therefore, simplify the locking design by just using key->sem instead of
-mk_secret_sem.
-
-Link: https://lore.kernel.org/r/20201117032626.320275-1-ebiggers@kernel.org
-Signed-off-by: Eric Biggers <ebiggers@google.com>
-Stable-dep-of: d7e7b9af104c ("fscrypt: stop using keyrings subsystem for fscrypt_master_key")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/crypto/fscrypt_private.h | 19 ++++++-------------
- fs/crypto/hooks.c           |  8 +++++---
- fs/crypto/keyring.c         |  8 +-------
- fs/crypto/keysetup.c        | 20 +++++++++-----------
- 4 files changed, 21 insertions(+), 34 deletions(-)
-
-diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
-index 052ad40ecdb2..8a0141f7195b 100644
---- a/fs/crypto/fscrypt_private.h
-+++ b/fs/crypto/fscrypt_private.h
-@@ -439,16 +439,9 @@ struct fscrypt_master_key {
-        * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
-        * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
-        *
--       * Locking: protected by key->sem (outer) and mk_secret_sem (inner).
--       * The reason for two locks is that key->sem also protects modifying
--       * mk_users, which ranks it above the semaphore for the keyring key
--       * type, which is in turn above page faults (via keyring_read).  But
--       * sometimes filesystems call fscrypt_get_encryption_info() from within
--       * a transaction, which ranks it below page faults.  So we need a
--       * separate lock which protects mk_secret but not also mk_users.
-+       * Locking: protected by this master key's key->sem.
-        */
-       struct fscrypt_master_key_secret        mk_secret;
--      struct rw_semaphore                     mk_secret_sem;
-       /*
-        * For v1 policy keys: an arbitrary key descriptor which was assigned by
-@@ -467,8 +460,8 @@ struct fscrypt_master_key {
-        *
-        * This is NULL for v1 policy keys; those can only be added by root.
-        *
--       * Locking: in addition to this keyrings own semaphore, this is
--       * protected by the master key's key->sem, so we can do atomic
-+       * Locking: in addition to this keyring's own semaphore, this is
-+       * protected by this master key's key->sem, so we can do atomic
-        * search+insert.  It can also be searched without taking any locks, but
-        * in that case the returned key may have already been removed.
-        */
-@@ -510,9 +503,9 @@ is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
-       /*
-        * The READ_ONCE() is only necessary for fscrypt_drop_inode() and
-        * fscrypt_key_describe().  These run in atomic context, so they can't
--       * take ->mk_secret_sem and thus 'secret' can change concurrently which
--       * would be a data race.  But they only need to know whether the secret
--       * *was* present at the time of check, so READ_ONCE() suffices.
-+       * take the key semaphore and thus 'secret' can change concurrently
-+       * which would be a data race.  But they only need to know whether the
-+       * secret *was* present at the time of check, so READ_ONCE() suffices.
-        */
-       return READ_ONCE(secret->size) != 0;
- }
-diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
-index 4180371bf864..0c6fa5c2d6f3 100644
---- a/fs/crypto/hooks.c
-+++ b/fs/crypto/hooks.c
-@@ -139,6 +139,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
-                            unsigned int oldflags, unsigned int flags)
- {
-       struct fscrypt_info *ci;
-+      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -154,13 +155,14 @@ int fscrypt_prepare_setflags(struct inode *inode,
-               ci = inode->i_crypt_info;
-               if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
-                       return -EINVAL;
--              mk = ci->ci_master_key->payload.data[0];
--              down_read(&mk->mk_secret_sem);
-+              key = ci->ci_master_key;
-+              mk = key->payload.data[0];
-+              down_read(&key->sem);
-               if (is_master_key_secret_present(&mk->mk_secret))
-                       err = fscrypt_derive_dirhash_key(ci, mk);
-               else
-                       err = -ENOKEY;
--              up_read(&mk->mk_secret_sem);
-+              up_read(&key->sem);
-               return err;
-       }
-       return 0;
-diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
-index d7ec52cb3d9a..0b3ffbb4faf4 100644
---- a/fs/crypto/keyring.c
-+++ b/fs/crypto/keyring.c
-@@ -347,7 +347,6 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret,
-       mk->mk_spec = *mk_spec;
-       move_master_key_secret(&mk->mk_secret, secret);
--      init_rwsem(&mk->mk_secret_sem);
-       refcount_set(&mk->mk_refcount, 1); /* secret is present */
-       INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
-@@ -427,11 +426,8 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
-       }
-       /* Re-add the secret if needed. */
--      if (rekey) {
--              down_write(&mk->mk_secret_sem);
-+      if (rekey)
-               move_master_key_secret(&mk->mk_secret, secret);
--              up_write(&mk->mk_secret_sem);
--      }
-       return 0;
- }
-@@ -975,10 +971,8 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-       /* No user claims remaining.  Go ahead and wipe the secret. */
-       dead = false;
-       if (is_master_key_secret_present(&mk->mk_secret)) {
--              down_write(&mk->mk_secret_sem);
-               wipe_master_key_secret(&mk->mk_secret);
-               dead = refcount_dec_and_test(&mk->mk_refcount);
--              up_write(&mk->mk_secret_sem);
-       }
-       up_write(&key->sem);
-       if (dead) {
-diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
-index 73d96e35d9ae..72aec33e0ea5 100644
---- a/fs/crypto/keysetup.c
-+++ b/fs/crypto/keysetup.c
-@@ -405,11 +405,11 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
-  * Find the master key, then set up the inode's actual encryption key.
-  *
-  * If the master key is found in the filesystem-level keyring, then the
-- * corresponding 'struct key' is returned in *master_key_ret with
-- * ->mk_secret_sem read-locked.  This is needed to ensure that only one task
-- * links the fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race
-- * to create an fscrypt_info for the same inode), and to synchronize the master
-- * key being removed with a new inode starting to use it.
-+ * corresponding 'struct key' is returned in *master_key_ret with its semaphore
-+ * read-locked.  This is needed to ensure that only one task links the
-+ * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create
-+ * an fscrypt_info for the same inode), and to synchronize the master key being
-+ * removed with a new inode starting to use it.
-  */
- static int setup_file_encryption_key(struct fscrypt_info *ci,
-                                    bool need_dirhash_key,
-@@ -458,7 +458,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       }
-       mk = key->payload.data[0];
--      down_read(&mk->mk_secret_sem);
-+      down_read(&key->sem);
-       /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
-@@ -490,7 +490,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       return 0;
- out_release_key:
--      up_read(&mk->mk_secret_sem);
-+      up_read(&key->sem);
-       key_put(key);
-       return err;
- }
-@@ -593,9 +593,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       res = 0;
- out:
-       if (master_key) {
--              struct fscrypt_master_key *mk = master_key->payload.data[0];
--
--              up_read(&mk->mk_secret_sem);
-+              up_read(&master_key->sem);
-               key_put(master_key);
-       }
-       put_crypt_info(crypt_info);
-@@ -769,7 +767,7 @@ int fscrypt_drop_inode(struct inode *inode)
-               return 0;
-       /*
--       * Note: since we aren't holding ->mk_secret_sem, the result here can
-+       * Note: since we aren't holding the key semaphore, the result here can
-        * immediately become outdated.  But there's no correctness problem with
-        * unnecessarily evicting.  Nor is there a correctness problem with not
-        * evicting while iput() is racing with the key being removed, since
--- 
-2.35.1
-
diff --git a/queue-5.10/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch b/queue-5.10/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
deleted file mode 100644 (file)
index 570c7cc..0000000
+++ /dev/null
@@ -1,1304 +0,0 @@
-From 19907e51e7fec7ef211076b11f8a4429993df750 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 1 Sep 2022 12:32:06 -0700
-Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key
-
-From: Eric Biggers <ebiggers@google.com>
-
-[ Upstream commit d7e7b9af104c7b389a0c21eb26532511bce4b510 ]
-
-The approach of fs/crypto/ internally managing the fscrypt_master_key
-structs as the payloads of "struct key" objects contained in a
-"struct key" keyring has outlived its usefulness.  The original idea was
-to simplify the code by reusing code from the keyrings subsystem.
-However, several issues have arisen that can't easily be resolved:
-
-- When a master key struct is destroyed, blk_crypto_evict_key() must be
-  called on any per-mode keys embedded in it.  (This started being the
-  case when inline encryption support was added.)  Yet, the keyrings
-  subsystem can arbitrarily delay the destruction of keys, even past the
-  time the filesystem was unmounted.  Therefore, currently there is no
-  easy way to call blk_crypto_evict_key() when a master key is
-  destroyed.  Currently, this is worked around by holding an extra
-  reference to the filesystem's request_queue(s).  But it was overlooked
-  that the request_queue reference is *not* guaranteed to pin the
-  corresponding blk_crypto_profile too; for device-mapper devices that
-  support inline crypto, it doesn't.  This can cause a use-after-free.
-
-- When the last inode that was using an incompletely-removed master key
-  is evicted, the master key removal is completed by removing the key
-  struct from the keyring.  Currently this is done via key_invalidate().
-  Yet, key_invalidate() takes the key semaphore.  This can deadlock when
-  called from the shrinker, since in fscrypt_ioctl_add_key(), memory is
-  allocated with GFP_KERNEL under the same semaphore.
-
-- More generally, the fact that the keyrings subsystem can arbitrarily
-  delay the destruction of keys (via garbage collection delay, or via
-  random processes getting temporary key references) is undesirable, as
-  it means we can't strictly guarantee that all secrets are ever wiped.
-
-- Doing the master key lookups via the keyrings subsystem results in the
-  key_permission LSM hook being called.  fscrypt doesn't want this, as
-  all access control for encrypted files is designed to happen via the
-  files themselves, like any other files.  The workaround which SELinux
-  users are using is to change their SELinux policy to grant key search
-  access to all domains.  This works, but it is an odd extra step that
-  shouldn't really have to be done.
-
-The fix for all these issues is to change the implementation to what I
-should have done originally: don't use the keyrings subsystem to keep
-track of the filesystem's fscrypt_master_key structs.  Instead, just
-store them in a regular kernel data structure, and rework the reference
-counting, locking, and lifetime accordingly.  Retain support for
-RCU-mode key lookups by using a hash table.  Replace fscrypt_sb_free()
-with fscrypt_sb_delete(), which releases the keys synchronously and runs
-a bit earlier during unmount, so that block devices are still available.
-
-A side effect of this patch is that neither the master keys themselves
-nor the filesystem keyrings will be listed in /proc/keys anymore.
-("Master key users" and the master key users keyrings will still be
-listed.)  However, this was mostly an implementation detail, and it was
-intended just for debugging purposes.  I don't know of anyone using it.
-
-This patch does *not* change how "master key users" (->mk_users) works;
-that still uses the keyrings subsystem.  That is still needed for key
-quotas, and changing that isn't necessary to solve the issues listed
-above.  If we decide to change that too, it would be a separate patch.
-
-I've marked this as fixing the original commit that added the fscrypt
-keyring, but as noted above the most important issue that this patch
-fixes wasn't introduced until the addition of inline encryption support.
-
-Fixes: 22d94f493bfb ("fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl")
-Signed-off-by: Eric Biggers <ebiggers@google.com>
-Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/crypto/fscrypt_private.h |  71 ++++--
- fs/crypto/hooks.c           |  10 +-
- fs/crypto/keyring.c         | 486 +++++++++++++++++++-----------------
- fs/crypto/keysetup.c        |  81 +++---
- fs/crypto/policy.c          |   8 +-
- fs/super.c                  |   2 +-
- include/linux/fs.h          |   2 +-
- include/linux/fscrypt.h     |   4 +-
- 8 files changed, 353 insertions(+), 311 deletions(-)
-
-diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
-index 8a0141f7195b..b746d7df3758 100644
---- a/fs/crypto/fscrypt_private.h
-+++ b/fs/crypto/fscrypt_private.h
-@@ -220,7 +220,7 @@ struct fscrypt_info {
-        * will be NULL if the master key was found in a process-subscribed
-        * keyring rather than in the filesystem-level keyring.
-        */
--      struct key *ci_master_key;
-+      struct fscrypt_master_key *ci_master_key;
-       /*
-        * Link in list of inodes that were unlocked with the master key.
-@@ -431,6 +431,40 @@ struct fscrypt_master_key_secret {
-  */
- struct fscrypt_master_key {
-+      /*
-+       * Back-pointer to the super_block of the filesystem to which this
-+       * master key has been added.  Only valid if ->mk_active_refs > 0.
-+       */
-+      struct super_block                      *mk_sb;
-+
-+      /*
-+       * Link in ->mk_sb->s_master_keys->key_hashtable.
-+       * Only valid if ->mk_active_refs > 0.
-+       */
-+      struct hlist_node                       mk_node;
-+
-+      /* Semaphore that protects ->mk_secret and ->mk_users */
-+      struct rw_semaphore                     mk_sem;
-+
-+      /*
-+       * Active and structural reference counts.  An active ref guarantees
-+       * that the struct continues to exist, continues to be in the keyring
-+       * ->mk_sb->s_master_keys, and that any embedded subkeys (e.g.
-+       * ->mk_direct_keys) that have been prepared continue to exist.
-+       * A structural ref only guarantees that the struct continues to exist.
-+       *
-+       * There is one active ref associated with ->mk_secret being present,
-+       * and one active ref for each inode in ->mk_decrypted_inodes.
-+       *
-+       * There is one structural ref associated with the active refcount being
-+       * nonzero.  Finding a key in the keyring also takes a structural ref,
-+       * which is then held temporarily while the key is operated on.
-+       */
-+      refcount_t                              mk_active_refs;
-+      refcount_t                              mk_struct_refs;
-+
-+      struct rcu_head                         mk_rcu_head;
-+
-       /*
-        * The secret key material.  After FS_IOC_REMOVE_ENCRYPTION_KEY is
-        * executed, this is wiped and no new inodes can be unlocked with this
-@@ -439,7 +473,10 @@ struct fscrypt_master_key {
-        * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
-        * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
-        *
--       * Locking: protected by this master key's key->sem.
-+       * While ->mk_secret is present, one ref in ->mk_active_refs is held.
-+       *
-+       * Locking: protected by ->mk_sem.  The manipulation of ->mk_active_refs
-+       *          associated with this field is protected by ->mk_sem as well.
-        */
-       struct fscrypt_master_key_secret        mk_secret;
-@@ -460,22 +497,12 @@ struct fscrypt_master_key {
-        *
-        * This is NULL for v1 policy keys; those can only be added by root.
-        *
--       * Locking: in addition to this keyring's own semaphore, this is
--       * protected by this master key's key->sem, so we can do atomic
--       * search+insert.  It can also be searched without taking any locks, but
--       * in that case the returned key may have already been removed.
-+       * Locking: protected by ->mk_sem.  (We don't just rely on the keyrings
-+       * subsystem semaphore ->mk_users->sem, as we need support for atomic
-+       * search+insert along with proper synchronization with ->mk_secret.)
-        */
-       struct key              *mk_users;
--      /*
--       * Length of ->mk_decrypted_inodes, plus one if mk_secret is present.
--       * Once this goes to 0, the master key is removed from ->s_master_keys.
--       * The 'struct fscrypt_master_key' will continue to live as long as the
--       * 'struct key' whose payload it is, but we won't let this reference
--       * count rise again.
--       */
--      refcount_t              mk_refcount;
--
-       /*
-        * List of inodes that were unlocked using this key.  This allows the
-        * inodes to be evicted efficiently if the key is removed.
-@@ -501,10 +528,10 @@ static inline bool
- is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
- {
-       /*
--       * The READ_ONCE() is only necessary for fscrypt_drop_inode() and
--       * fscrypt_key_describe().  These run in atomic context, so they can't
--       * take the key semaphore and thus 'secret' can change concurrently
--       * which would be a data race.  But they only need to know whether the
-+       * The READ_ONCE() is only necessary for fscrypt_drop_inode().
-+       * fscrypt_drop_inode() runs in atomic context, so it can't take the key
-+       * semaphore and thus 'secret' can change concurrently which would be a
-+       * data race.  But fscrypt_drop_inode() only need to know whether the
-        * secret *was* present at the time of check, so READ_ONCE() suffices.
-        */
-       return READ_ONCE(secret->size) != 0;
-@@ -533,7 +560,11 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
-       return 0;
- }
--struct key *
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk);
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk);
-+
-+struct fscrypt_master_key *
- fscrypt_find_master_key(struct super_block *sb,
-                       const struct fscrypt_key_specifier *mk_spec);
-diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
-index 0c6fa5c2d6f3..8268206ef21e 100644
---- a/fs/crypto/hooks.c
-+++ b/fs/crypto/hooks.c
-@@ -5,8 +5,6 @@
-  * Encryption hooks for higher-level filesystem operations.
-  */
--#include <linux/key.h>
--
- #include "fscrypt_private.h"
- /**
-@@ -139,7 +137,6 @@ int fscrypt_prepare_setflags(struct inode *inode,
-                            unsigned int oldflags, unsigned int flags)
- {
-       struct fscrypt_info *ci;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -155,14 +152,13 @@ int fscrypt_prepare_setflags(struct inode *inode,
-               ci = inode->i_crypt_info;
-               if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
-                       return -EINVAL;
--              key = ci->ci_master_key;
--              mk = key->payload.data[0];
--              down_read(&key->sem);
-+              mk = ci->ci_master_key;
-+              down_read(&mk->mk_sem);
-               if (is_master_key_secret_present(&mk->mk_secret))
-                       err = fscrypt_derive_dirhash_key(ci, mk);
-               else
-                       err = -ENOKEY;
--              up_read(&key->sem);
-+              up_read(&mk->mk_sem);
-               return err;
-       }
-       return 0;
-diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
-index 0b3ffbb4faf4..175b071beaf8 100644
---- a/fs/crypto/keyring.c
-+++ b/fs/crypto/keyring.c
-@@ -18,6 +18,7 @@
-  * information about these ioctls.
-  */
-+#include <asm/unaligned.h>
- #include <crypto/skcipher.h>
- #include <linux/key-type.h>
- #include <linux/random.h>
-@@ -25,6 +26,18 @@
- #include "fscrypt_private.h"
-+/* The master encryption keys for a filesystem (->s_master_keys) */
-+struct fscrypt_keyring {
-+      /*
-+       * Lock that protects ->key_hashtable.  It does *not* protect the
-+       * fscrypt_master_key structs themselves.
-+       */
-+      spinlock_t lock;
-+
-+      /* Hash table that maps fscrypt_key_specifier to fscrypt_master_key */
-+      struct hlist_head key_hashtable[128];
-+};
-+
- static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret)
- {
-       fscrypt_destroy_hkdf(&secret->hkdf);
-@@ -38,20 +51,70 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst,
-       memzero_explicit(src, sizeof(*src));
- }
--static void free_master_key(struct fscrypt_master_key *mk)
-+static void fscrypt_free_master_key(struct rcu_head *head)
-+{
-+      struct fscrypt_master_key *mk =
-+              container_of(head, struct fscrypt_master_key, mk_rcu_head);
-+      /*
-+       * The master key secret and any embedded subkeys should have already
-+       * been wiped when the last active reference to the fscrypt_master_key
-+       * struct was dropped; doing it here would be unnecessarily late.
-+       * Nevertheless, use kfree_sensitive() in case anything was missed.
-+       */
-+      kfree_sensitive(mk);
-+}
-+
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk)
-+{
-+      if (!refcount_dec_and_test(&mk->mk_struct_refs))
-+              return;
-+      /*
-+       * No structural references left, so free ->mk_users, and also free the
-+       * fscrypt_master_key struct itself after an RCU grace period ensures
-+       * that concurrent keyring lookups can no longer find it.
-+       */
-+      WARN_ON(refcount_read(&mk->mk_active_refs) != 0);
-+      key_put(mk->mk_users);
-+      mk->mk_users = NULL;
-+      call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
-+}
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk)
- {
-+      struct super_block *sb = mk->mk_sb;
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       size_t i;
--      wipe_master_key_secret(&mk->mk_secret);
-+      if (!refcount_dec_and_test(&mk->mk_active_refs))
-+              return;
-+      /*
-+       * No active references left, so complete the full removal of this
-+       * fscrypt_master_key struct by removing it from the keyring and
-+       * destroying any subkeys embedded in it.
-+       */
-+
-+      spin_lock(&keyring->lock);
-+      hlist_del_rcu(&mk->mk_node);
-+      spin_unlock(&keyring->lock);
-+
-+      /*
-+       * ->mk_active_refs == 0 implies that ->mk_secret is not present and
-+       * that ->mk_decrypted_inodes is empty.
-+       */
-+      WARN_ON(is_master_key_secret_present(&mk->mk_secret));
-+      WARN_ON(!list_empty(&mk->mk_decrypted_inodes));
-       for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
-               fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]);
-       }
-+      memzero_explicit(&mk->mk_ino_hash_key,
-+                       sizeof(mk->mk_ino_hash_key));
-+      mk->mk_ino_hash_key_initialized = false;
--      key_put(mk->mk_users);
--      kfree_sensitive(mk);
-+      /* Drop the structural ref associated with the active refs. */
-+      fscrypt_put_master_key(mk);
- }
- static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-@@ -61,44 +124,6 @@ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-       return master_key_spec_len(spec) != 0;
- }
--static int fscrypt_key_instantiate(struct key *key,
--                                 struct key_preparsed_payload *prep)
--{
--      key->payload.data[0] = (struct fscrypt_master_key *)prep->data;
--      return 0;
--}
--
--static void fscrypt_key_destroy(struct key *key)
--{
--      free_master_key(key->payload.data[0]);
--}
--
--static void fscrypt_key_describe(const struct key *key, struct seq_file *m)
--{
--      seq_puts(m, key->description);
--
--      if (key_is_positive(key)) {
--              const struct fscrypt_master_key *mk = key->payload.data[0];
--
--              if (!is_master_key_secret_present(&mk->mk_secret))
--                      seq_puts(m, ": secret removed");
--      }
--}
--
--/*
-- * Type of key in ->s_master_keys.  Each key of this type represents a master
-- * key which has been added to the filesystem.  Its payload is a
-- * 'struct fscrypt_master_key'.  The "." prefix in the key type name prevents
-- * users from adding keys of this type via the keyrings syscalls rather than via
-- * the intended method of FS_IOC_ADD_ENCRYPTION_KEY.
-- */
--static struct key_type key_type_fscrypt = {
--      .name                   = "._fscrypt",
--      .instantiate            = fscrypt_key_instantiate,
--      .destroy                = fscrypt_key_destroy,
--      .describe               = fscrypt_key_describe,
--};
--
- static int fscrypt_user_key_instantiate(struct key *key,
-                                       struct key_preparsed_payload *prep)
- {
-@@ -131,32 +156,6 @@ static struct key_type key_type_fscrypt_user = {
-       .describe               = fscrypt_user_key_describe,
- };
--/* Search ->s_master_keys or ->mk_users */
--static struct key *search_fscrypt_keyring(struct key *keyring,
--                                        struct key_type *type,
--                                        const char *description)
--{
--      /*
--       * We need to mark the keyring reference as "possessed" so that we
--       * acquire permission to search it, via the KEY_POS_SEARCH permission.
--       */
--      key_ref_t keyref = make_key_ref(keyring, true /* possessed */);
--
--      keyref = keyring_search(keyref, type, description, false);
--      if (IS_ERR(keyref)) {
--              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
--                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
--                      keyref = ERR_PTR(-ENOKEY);
--              return ERR_CAST(keyref);
--      }
--      return key_ref_to_ptr(keyref);
--}
--
--#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE   \
--      (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id))
--
--#define FSCRYPT_MK_DESCRIPTION_SIZE   (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1)
--
- #define FSCRYPT_MK_USERS_DESCRIPTION_SIZE     \
-       (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
-        CONST_STRLEN("-users") + 1)
-@@ -164,21 +163,6 @@ static struct key *search_fscrypt_keyring(struct key *keyring,
- #define FSCRYPT_MK_USER_DESCRIPTION_SIZE      \
-       (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
--static void format_fs_keyring_description(
--                      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE],
--                      const struct super_block *sb)
--{
--      sprintf(description, "fscrypt-%s", sb->s_id);
--}
--
--static void format_mk_description(
--                      char description[FSCRYPT_MK_DESCRIPTION_SIZE],
--                      const struct fscrypt_key_specifier *mk_spec)
--{
--      sprintf(description, "%*phN",
--              master_key_spec_len(mk_spec), (u8 *)&mk_spec->u);
--}
--
- static void format_mk_users_keyring_description(
-                       char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
-                       const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
-@@ -199,20 +183,15 @@ static void format_mk_user_description(
- /* Create ->s_master_keys if needed.  Synchronized by fscrypt_add_key_mutex. */
- static int allocate_filesystem_keyring(struct super_block *sb)
- {
--      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE];
--      struct key *keyring;
-+      struct fscrypt_keyring *keyring;
-       if (sb->s_master_keys)
-               return 0;
--      format_fs_keyring_description(description, sb);
--      keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
--                              current_cred(), KEY_POS_SEARCH |
--                                KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW,
--                              KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
--      if (IS_ERR(keyring))
--              return PTR_ERR(keyring);
--
-+      keyring = kzalloc(sizeof(*keyring), GFP_KERNEL);
-+      if (!keyring)
-+              return -ENOMEM;
-+      spin_lock_init(&keyring->lock);
-       /*
-        * Pairs with the smp_load_acquire() in fscrypt_find_master_key().
-        * I.e., here we publish ->s_master_keys with a RELEASE barrier so that
-@@ -222,21 +201,75 @@ static int allocate_filesystem_keyring(struct super_block *sb)
-       return 0;
- }
--void fscrypt_sb_free(struct super_block *sb)
-+/*
-+ * This is called at unmount time to release all encryption keys that have been
-+ * added to the filesystem, along with the keyring that contains them.
-+ *
-+ * Note that besides clearing and freeing memory, this might need to evict keys
-+ * from the keyslots of an inline crypto engine.  Therefore, this must be called
-+ * while the filesystem's underlying block device(s) are still available.
-+ */
-+void fscrypt_sb_delete(struct super_block *sb)
- {
--      key_put(sb->s_master_keys);
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-+      size_t i;
-+
-+      if (!keyring)
-+              return;
-+
-+      for (i = 0; i < ARRAY_SIZE(keyring->key_hashtable); i++) {
-+              struct hlist_head *bucket = &keyring->key_hashtable[i];
-+              struct fscrypt_master_key *mk;
-+              struct hlist_node *tmp;
-+
-+              hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
-+                      /*
-+                       * Since all inodes were already evicted, every key
-+                       * remaining in the keyring should have an empty inode
-+                       * list, and should only still be in the keyring due to
-+                       * the single active ref associated with ->mk_secret.
-+                       * There should be no structural refs beyond the one
-+                       * associated with the active ref.
-+                       */
-+                      WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
-+                      WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
-+                      WARN_ON(!is_master_key_secret_present(&mk->mk_secret));
-+                      wipe_master_key_secret(&mk->mk_secret);
-+                      fscrypt_put_master_key_activeref(mk);
-+              }
-+      }
-+      kfree_sensitive(keyring);
-       sb->s_master_keys = NULL;
- }
-+static struct hlist_head *
-+fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring,
-+                     const struct fscrypt_key_specifier *mk_spec)
-+{
-+      /*
-+       * Since key specifiers should be "random" values, it is sufficient to
-+       * use a trivial hash function that just takes the first several bits of
-+       * the key specifier.
-+       */
-+      unsigned long i = get_unaligned((unsigned long *)&mk_spec->u);
-+
-+      return &keyring->key_hashtable[i % ARRAY_SIZE(keyring->key_hashtable)];
-+}
-+
- /*
-- * Find the specified master key in ->s_master_keys.
-- * Returns ERR_PTR(-ENOKEY) if not found.
-+ * Find the specified master key struct in ->s_master_keys and take a structural
-+ * ref to it.  The structural ref guarantees that the key struct continues to
-+ * exist, but it does *not* guarantee that ->s_master_keys continues to contain
-+ * the key struct.  The structural ref needs to be dropped by
-+ * fscrypt_put_master_key().  Returns NULL if the key struct is not found.
-  */
--struct key *fscrypt_find_master_key(struct super_block *sb,
--                                  const struct fscrypt_key_specifier *mk_spec)
-+struct fscrypt_master_key *
-+fscrypt_find_master_key(struct super_block *sb,
-+                      const struct fscrypt_key_specifier *mk_spec)
- {
--      struct key *keyring;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
-+      struct fscrypt_keyring *keyring;
-+      struct hlist_head *bucket;
-+      struct fscrypt_master_key *mk;
-       /*
-        * Pairs with the smp_store_release() in allocate_filesystem_keyring().
-@@ -246,10 +279,38 @@ struct key *fscrypt_find_master_key(struct super_block *sb,
-        */
-       keyring = smp_load_acquire(&sb->s_master_keys);
-       if (keyring == NULL)
--              return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */
--
--      format_mk_description(description, mk_spec);
--      return search_fscrypt_keyring(keyring, &key_type_fscrypt, description);
-+              return NULL; /* No keyring yet, so no keys yet. */
-+
-+      bucket = fscrypt_mk_hash_bucket(keyring, mk_spec);
-+      rcu_read_lock();
-+      switch (mk_spec->type) {
-+      case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
-+                          memcmp(mk->mk_spec.u.descriptor,
-+                                 mk_spec->u.descriptor,
-+                                 FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&
-+                          memcmp(mk->mk_spec.u.identifier,
-+                                 mk_spec->u.identifier,
-+                                 FSCRYPT_KEY_IDENTIFIER_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      }
-+      mk = NULL;
-+out:
-+      rcu_read_unlock();
-+      return mk;
- }
- static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
-@@ -277,17 +338,30 @@ static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
- static struct key *find_master_key_user(struct fscrypt_master_key *mk)
- {
-       char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
-+      key_ref_t keyref;
-       format_mk_user_description(description, mk->mk_spec.u.identifier);
--      return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_user,
--                                    description);
-+
-+      /*
-+       * We need to mark the keyring reference as "possessed" so that we
-+       * acquire permission to search it, via the KEY_POS_SEARCH permission.
-+       */
-+      keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/),
-+                              &key_type_fscrypt_user, description, false);
-+      if (IS_ERR(keyref)) {
-+              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
-+                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
-+                      keyref = ERR_PTR(-ENOKEY);
-+              return ERR_CAST(keyref);
-+      }
-+      return key_ref_to_ptr(keyref);
- }
- /*
-  * Give the current user a "key" in ->mk_users.  This charges the user's quota
-  * and marks the master key as added by the current user, so that it cannot be
-- * removed by another user with the key.  Either the master key's key->sem must
-- * be held for write, or the master key must be still undergoing initialization.
-+ * removed by another user with the key.  Either ->mk_sem must be held for
-+ * write, or the master key must be still undergoing initialization.
-  */
- static int add_master_key_user(struct fscrypt_master_key *mk)
- {
-@@ -309,7 +383,7 @@ static int add_master_key_user(struct fscrypt_master_key *mk)
- /*
-  * Remove the current user's "key" from ->mk_users.
-- * The master key's key->sem must be held for write.
-+ * ->mk_sem must be held for write.
-  *
-  * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
-  */
-@@ -327,63 +401,49 @@ static int remove_master_key_user(struct fscrypt_master_key *mk)
- }
- /*
-- * Allocate a new fscrypt_master_key which contains the given secret, set it as
-- * the payload of a new 'struct key' of type fscrypt, and link the 'struct key'
-- * into the given keyring.  Synchronized by fscrypt_add_key_mutex.
-+ * Allocate a new fscrypt_master_key, transfer the given secret over to it, and
-+ * insert it into sb->s_master_keys.
-  */
--static int add_new_master_key(struct fscrypt_master_key_secret *secret,
--                            const struct fscrypt_key_specifier *mk_spec,
--                            struct key *keyring)
-+static int add_new_master_key(struct super_block *sb,
-+                            struct fscrypt_master_key_secret *secret,
-+                            const struct fscrypt_key_specifier *mk_spec)
- {
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       struct fscrypt_master_key *mk;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
--      struct key *key;
-       int err;
-       mk = kzalloc(sizeof(*mk), GFP_KERNEL);
-       if (!mk)
-               return -ENOMEM;
-+      mk->mk_sb = sb;
-+      init_rwsem(&mk->mk_sem);
-+      refcount_set(&mk->mk_struct_refs, 1);
-       mk->mk_spec = *mk_spec;
--      move_master_key_secret(&mk->mk_secret, secret);
--
--      refcount_set(&mk->mk_refcount, 1); /* secret is present */
-       INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
-       spin_lock_init(&mk->mk_decrypted_inodes_lock);
-       if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
-               err = allocate_master_key_users_keyring(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-               err = add_master_key_user(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-       }
--      /*
--       * Note that we don't charge this key to anyone's quota, since when
--       * ->mk_users is in use those keys are charged instead, and otherwise
--       * (when ->mk_users isn't in use) only root can add these keys.
--       */
--      format_mk_description(description, mk_spec);
--      key = key_alloc(&key_type_fscrypt, description,
--                      GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
--                      KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_USR_VIEW,
--                      KEY_ALLOC_NOT_IN_QUOTA, NULL);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              goto out_free_mk;
--      }
--      err = key_instantiate_and_link(key, mk, sizeof(*mk), keyring, NULL);
--      key_put(key);
--      if (err)
--              goto out_free_mk;
-+      move_master_key_secret(&mk->mk_secret, secret);
-+      refcount_set(&mk->mk_active_refs, 1); /* ->mk_secret is present */
-+      spin_lock(&keyring->lock);
-+      hlist_add_head_rcu(&mk->mk_node,
-+                         fscrypt_mk_hash_bucket(keyring, mk_spec));
-+      spin_unlock(&keyring->lock);
-       return 0;
--out_free_mk:
--      free_master_key(mk);
-+out_put:
-+      fscrypt_put_master_key(mk);
-       return err;
- }
-@@ -392,42 +452,34 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret,
- static int add_existing_master_key(struct fscrypt_master_key *mk,
-                                  struct fscrypt_master_key_secret *secret)
- {
--      struct key *mk_user;
--      bool rekey;
-       int err;
-       /*
-        * If the current user is already in ->mk_users, then there's nothing to
--       * do.  (Not applicable for v1 policy keys, which have NULL ->mk_users.)
-+       * do.  Otherwise, we need to add the user to ->mk_users.  (Neither is
-+       * applicable for v1 policy keys, which have NULL ->mk_users.)
-        */
-       if (mk->mk_users) {
--              mk_user = find_master_key_user(mk);
-+              struct key *mk_user = find_master_key_user(mk);
-+
-               if (mk_user != ERR_PTR(-ENOKEY)) {
-                       if (IS_ERR(mk_user))
-                               return PTR_ERR(mk_user);
-                       key_put(mk_user);
-                       return 0;
-               }
--      }
--
--      /* If we'll be re-adding ->mk_secret, try to take the reference. */
--      rekey = !is_master_key_secret_present(&mk->mk_secret);
--      if (rekey && !refcount_inc_not_zero(&mk->mk_refcount))
--              return KEY_DEAD;
--
--      /* Add the current user to ->mk_users, if applicable. */
--      if (mk->mk_users) {
-               err = add_master_key_user(mk);
--              if (err) {
--                      if (rekey && refcount_dec_and_test(&mk->mk_refcount))
--                              return KEY_DEAD;
-+              if (err)
-                       return err;
--              }
-       }
-       /* Re-add the secret if needed. */
--      if (rekey)
-+      if (!is_master_key_secret_present(&mk->mk_secret)) {
-+              if (!refcount_inc_not_zero(&mk->mk_active_refs))
-+                      return KEY_DEAD;
-               move_master_key_secret(&mk->mk_secret, secret);
-+      }
-+
-       return 0;
- }
-@@ -436,38 +488,36 @@ static int do_add_master_key(struct super_block *sb,
-                            const struct fscrypt_key_specifier *mk_spec)
- {
-       static DEFINE_MUTEX(fscrypt_add_key_mutex);
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       int err;
-       mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */
--retry:
--      key = fscrypt_find_master_key(sb, mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              if (err != -ENOKEY)
--                      goto out_unlock;
-+
-+      mk = fscrypt_find_master_key(sb, mk_spec);
-+      if (!mk) {
-               /* Didn't find the key in ->s_master_keys.  Add it. */
-               err = allocate_filesystem_keyring(sb);
--              if (err)
--                      goto out_unlock;
--              err = add_new_master_key(secret, mk_spec, sb->s_master_keys);
-+              if (!err)
-+                      err = add_new_master_key(sb, secret, mk_spec);
-       } else {
-               /*
-                * Found the key in ->s_master_keys.  Re-add the secret if
-                * needed, and add the user to ->mk_users if needed.
-                */
--              down_write(&key->sem);
--              err = add_existing_master_key(key->payload.data[0], secret);
--              up_write(&key->sem);
-+              down_write(&mk->mk_sem);
-+              err = add_existing_master_key(mk, secret);
-+              up_write(&mk->mk_sem);
-               if (err == KEY_DEAD) {
--                      /* Key being removed or needs to be removed */
--                      key_invalidate(key);
--                      key_put(key);
--                      goto retry;
-+                      /*
-+                       * We found a key struct, but it's already been fully
-+                       * removed.  Ignore the old struct and add a new one.
-+                       * fscrypt_add_key_mutex means we don't need to worry
-+                       * about concurrent adds.
-+                       */
-+                      err = add_new_master_key(sb, secret, mk_spec);
-               }
--              key_put(key);
-+              fscrypt_put_master_key(mk);
-       }
--out_unlock:
-       mutex_unlock(&fscrypt_add_key_mutex);
-       return err;
- }
-@@ -731,19 +781,19 @@ int fscrypt_verify_key_added(struct super_block *sb,
-                            const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
- {
-       struct fscrypt_key_specifier mk_spec;
--      struct key *key, *mk_user;
-       struct fscrypt_master_key *mk;
-+      struct key *mk_user;
-       int err;
-       mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
-       memcpy(mk_spec.u.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE);
--      key = fscrypt_find_master_key(sb, &mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &mk_spec);
-+      if (!mk) {
-+              err = -ENOKEY;
-               goto out;
-       }
--      mk = key->payload.data[0];
-+      down_read(&mk->mk_sem);
-       mk_user = find_master_key_user(mk);
-       if (IS_ERR(mk_user)) {
-               err = PTR_ERR(mk_user);
-@@ -751,7 +801,8 @@ int fscrypt_verify_key_added(struct super_block *sb,
-               key_put(mk_user);
-               err = 0;
-       }
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (err == -ENOKEY && capable(CAP_FOWNER))
-               err = 0;
-@@ -913,11 +964,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_remove_key_arg __user *uarg = _uarg;
-       struct fscrypt_remove_key_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       u32 status_flags = 0;
-       int err;
--      bool dead;
-+      bool inodes_remain;
-       if (copy_from_user(&arg, uarg, sizeof(arg)))
-               return -EFAULT;
-@@ -937,12 +987,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               return -EACCES;
-       /* Find the key being removed. */
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key))
--              return PTR_ERR(key);
--      mk = key->payload.data[0];
--
--      down_write(&key->sem);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk)
-+              return -ENOKEY;
-+      down_write(&mk->mk_sem);
-       /* If relevant, remove current user's (or all users) claim to the key */
-       if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -951,7 +999,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               else
-                       err = remove_master_key_user(mk);
-               if (err) {
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-               if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -963,26 +1011,22 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-                       status_flags |=
-                               FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS;
-                       err = 0;
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-       }
-       /* No user claims remaining.  Go ahead and wipe the secret. */
--      dead = false;
-+      err = -ENOKEY;
-       if (is_master_key_secret_present(&mk->mk_secret)) {
-               wipe_master_key_secret(&mk->mk_secret);
--              dead = refcount_dec_and_test(&mk->mk_refcount);
--      }
--      up_write(&key->sem);
--      if (dead) {
--              /*
--               * No inodes reference the key, and we wiped the secret, so the
--               * key object is free to be removed from the keyring.
--               */
--              key_invalidate(key);
-+              fscrypt_put_master_key_activeref(mk);
-               err = 0;
--      } else {
-+      }
-+      inodes_remain = refcount_read(&mk->mk_active_refs) > 0;
-+      up_write(&mk->mk_sem);
-+
-+      if (inodes_remain) {
-               /* Some inodes still reference this key; try to evict them. */
-               err = try_to_lock_encrypted_files(sb, mk);
-               if (err == -EBUSY) {
-@@ -998,7 +1042,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-        * has been fully removed including all files locked.
-        */
- out_put_key:
--      key_put(key);
-+      fscrypt_put_master_key(mk);
-       if (err == 0)
-               err = put_user(status_flags, &uarg->removal_status_flags);
-       return err;
-@@ -1045,7 +1089,6 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
- {
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_get_key_status_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -1062,19 +1105,18 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       arg.user_count = 0;
-       memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved));
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY))
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk) {
-               arg.status = FSCRYPT_KEY_STATUS_ABSENT;
-               err = 0;
-               goto out;
-       }
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
--              arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED;
-+              arg.status = refcount_read(&mk->mk_active_refs) > 0 ?
-+                      FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED :
-+                      FSCRYPT_KEY_STATUS_ABSENT /* raced with full removal */;
-               err = 0;
-               goto out_release_key;
-       }
-@@ -1096,8 +1138,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       }
-       err = 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (!err && copy_to_user(uarg, &arg, sizeof(arg)))
-               err = -EFAULT;
-@@ -1109,13 +1151,9 @@ int __init fscrypt_init_keyring(void)
- {
-       int err;
--      err = register_key_type(&key_type_fscrypt);
--      if (err)
--              return err;
--
-       err = register_key_type(&key_type_fscrypt_user);
-       if (err)
--              goto err_unregister_fscrypt;
-+              return err;
-       err = register_key_type(&key_type_fscrypt_provisioning);
-       if (err)
-@@ -1125,7 +1163,5 @@ int __init fscrypt_init_keyring(void)
- err_unregister_fscrypt_user:
-       unregister_key_type(&key_type_fscrypt_user);
--err_unregister_fscrypt:
--      unregister_key_type(&key_type_fscrypt);
-       return err;
- }
-diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
-index 72aec33e0ea5..7b14054fab49 100644
---- a/fs/crypto/keysetup.c
-+++ b/fs/crypto/keysetup.c
-@@ -9,7 +9,6 @@
-  */
- #include <crypto/skcipher.h>
--#include <linux/key.h>
- #include <linux/random.h>
- #include "fscrypt_private.h"
-@@ -151,6 +150,7 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key)
- {
-       crypto_free_skcipher(prep_key->tfm);
-       fscrypt_destroy_inline_crypt_key(prep_key);
-+      memzero_explicit(prep_key, sizeof(*prep_key));
- }
- /* Given a per-file encryption key, set up the file's crypto transform object */
-@@ -404,20 +404,18 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
- /*
-  * Find the master key, then set up the inode's actual encryption key.
-  *
-- * If the master key is found in the filesystem-level keyring, then the
-- * corresponding 'struct key' is returned in *master_key_ret with its semaphore
-- * read-locked.  This is needed to ensure that only one task links the
-- * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create
-- * an fscrypt_info for the same inode), and to synchronize the master key being
-- * removed with a new inode starting to use it.
-+ * If the master key is found in the filesystem-level keyring, then it is
-+ * returned in *mk_ret with its semaphore read-locked.  This is needed to ensure
-+ * that only one task links the fscrypt_info into ->mk_decrypted_inodes (as
-+ * multiple tasks may race to create an fscrypt_info for the same inode), and to
-+ * synchronize the master key being removed with a new inode starting to use it.
-  */
- static int setup_file_encryption_key(struct fscrypt_info *ci,
-                                    bool need_dirhash_key,
--                                   struct key **master_key_ret)
-+                                   struct fscrypt_master_key **mk_ret)
- {
--      struct key *key;
--      struct fscrypt_master_key *mk = NULL;
-       struct fscrypt_key_specifier mk_spec;
-+      struct fscrypt_master_key *mk;
-       int err;
-       err = fscrypt_select_encryption_impl(ci);
-@@ -442,11 +440,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-               return -EINVAL;
-       }
--      key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY) ||
--                  ci->ci_policy.version != FSCRYPT_POLICY_V1)
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
-+      if (!mk) {
-+              if (ci->ci_policy.version != FSCRYPT_POLICY_V1)
-+                      return -ENOKEY;
-               /*
-                * As a legacy fallback for v1 policies, search for the key in
-@@ -456,9 +453,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-                */
-               return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci);
-       }
--
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
-@@ -486,18 +481,18 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       if (err)
-               goto out_release_key;
--      *master_key_ret = key;
-+      *mk_ret = mk;
-       return 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
-       return err;
- }
- static void put_crypt_info(struct fscrypt_info *ci)
- {
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       if (!ci)
-               return;
-@@ -507,24 +502,18 @@ static void put_crypt_info(struct fscrypt_info *ci)
-       else if (ci->ci_owns_key)
-               fscrypt_destroy_prepared_key(&ci->ci_enc_key);
--      key = ci->ci_master_key;
--      if (key) {
--              struct fscrypt_master_key *mk = key->payload.data[0];
--
-+      mk = ci->ci_master_key;
-+      if (mk) {
-               /*
-                * Remove this inode from the list of inodes that were unlocked
--               * with the master key.
--               *
--               * In addition, if we're removing the last inode from a key that
--               * already had its secret removed, invalidate the key so that it
--               * gets removed from ->s_master_keys.
-+               * with the master key.  In addition, if we're removing the last
-+               * inode from a master key struct that already had its secret
-+               * removed, then complete the full removal of the struct.
-                */
-               spin_lock(&mk->mk_decrypted_inodes_lock);
-               list_del(&ci->ci_master_key_link);
-               spin_unlock(&mk->mk_decrypted_inodes_lock);
--              if (refcount_dec_and_test(&mk->mk_refcount))
--                      key_invalidate(key);
--              key_put(key);
-+              fscrypt_put_master_key_activeref(mk);
-       }
-       memzero_explicit(ci, sizeof(*ci));
-       kmem_cache_free(fscrypt_info_cachep, ci);
-@@ -538,7 +527,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
- {
-       struct fscrypt_info *crypt_info;
-       struct fscrypt_mode *mode;
--      struct key *master_key = NULL;
-+      struct fscrypt_master_key *mk = NULL;
-       int res;
-       res = fscrypt_initialize(inode->i_sb->s_cop->flags);
-@@ -561,8 +550,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
-       crypt_info->ci_mode = mode;
--      res = setup_file_encryption_key(crypt_info, need_dirhash_key,
--                                      &master_key);
-+      res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
-       if (res)
-               goto out;
-@@ -577,12 +565,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-                * We won the race and set ->i_crypt_info to our crypt_info.
-                * Now link it into the master key's inode list.
-                */
--              if (master_key) {
--                      struct fscrypt_master_key *mk =
--                              master_key->payload.data[0];
--
--                      refcount_inc(&mk->mk_refcount);
--                      crypt_info->ci_master_key = key_get(master_key);
-+              if (mk) {
-+                      crypt_info->ci_master_key = mk;
-+                      refcount_inc(&mk->mk_active_refs);
-                       spin_lock(&mk->mk_decrypted_inodes_lock);
-                       list_add(&crypt_info->ci_master_key_link,
-                                &mk->mk_decrypted_inodes);
-@@ -592,9 +577,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       }
-       res = 0;
- out:
--      if (master_key) {
--              up_read(&master_key->sem);
--              key_put(master_key);
-+      if (mk) {
-+              up_read(&mk->mk_sem);
-+              fscrypt_put_master_key(mk);
-       }
-       put_crypt_info(crypt_info);
-       return res;
-@@ -745,7 +730,6 @@ EXPORT_SYMBOL(fscrypt_free_inode);
- int fscrypt_drop_inode(struct inode *inode)
- {
-       const struct fscrypt_info *ci = fscrypt_get_info(inode);
--      const struct fscrypt_master_key *mk;
-       /*
-        * If ci is NULL, then the inode doesn't have an encryption key set up
-@@ -755,7 +739,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        */
-       if (!ci || !ci->ci_master_key)
-               return 0;
--      mk = ci->ci_master_key->payload.data[0];
-       /*
-        * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes
-@@ -774,6 +757,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        * then the thread removing the key will either evict the inode itself
-        * or will correctly detect that it wasn't evicted due to the race.
-        */
--      return !is_master_key_secret_present(&mk->mk_secret);
-+      return !is_master_key_secret_present(&ci->ci_master_key->mk_secret);
- }
- EXPORT_SYMBOL_GPL(fscrypt_drop_inode);
-diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
-index faa0f21daa68..f68265c36377 100644
---- a/fs/crypto/policy.c
-+++ b/fs/crypto/policy.c
-@@ -686,12 +686,8 @@ int fscrypt_set_context(struct inode *inode, void *fs_data)
-        * delayed key setup that requires the inode number.
-        */
-       if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
--          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
--              const struct fscrypt_master_key *mk =
--                      ci->ci_master_key->payload.data[0];
--
--              fscrypt_hash_inode_number(ci, mk);
--      }
-+          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
-+              fscrypt_hash_inode_number(ci, ci->ci_master_key);
-       return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, fs_data);
- }
-diff --git a/fs/super.c b/fs/super.c
-index 705be5d0600e..88ecc2c6dba5 100644
---- a/fs/super.c
-+++ b/fs/super.c
-@@ -293,7 +293,6 @@ static void __put_super(struct super_block *s)
-               WARN_ON(s->s_inode_lru.node);
-               WARN_ON(!list_empty(&s->s_mounts));
-               security_sb_free(s);
--              fscrypt_sb_free(s);
-               put_user_ns(s->s_user_ns);
-               kfree(s->s_subtype);
-               call_rcu(&s->rcu, destroy_super_rcu);
-@@ -454,6 +453,7 @@ void generic_shutdown_super(struct super_block *sb)
-               evict_inodes(sb);
-               /* only nonzero refcount inodes can have marks */
-               fsnotify_sb_delete(sb);
-+              fscrypt_sb_delete(sb);
-               security_sb_delete(sb);
-               if (sb->s_dio_done_wq) {
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index c8f887641878..df54acdd3554 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -1437,7 +1437,7 @@ struct super_block {
-       const struct xattr_handler **s_xattr;
- #ifdef CONFIG_FS_ENCRYPTION
-       const struct fscrypt_operations *s_cop;
--      struct key              *s_master_keys; /* master crypto keys in use */
-+      struct fscrypt_keyring  *s_master_keys; /* master crypto keys in use */
- #endif
- #ifdef CONFIG_FS_VERITY
-       const struct fsverity_operations *s_vop;
-diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
-index d0a1b8edfd9d..23d3ea47f764 100644
---- a/include/linux/fscrypt.h
-+++ b/include/linux/fscrypt.h
-@@ -193,7 +193,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--void fscrypt_sb_free(struct super_block *sb);
-+void fscrypt_sb_delete(struct super_block *sb);
- int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
- int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg);
- int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *arg);
-@@ -380,7 +380,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--static inline void fscrypt_sb_free(struct super_block *sb)
-+static inline void fscrypt_sb_delete(struct super_block *sb)
- {
- }
--- 
-2.35.1
-
index 48f81934be0960e9132a39b60706ac47529198c0..54d1205724a69d0499061e092629766a83104be1 100644 (file)
@@ -93,9 +93,7 @@ userfaultfd-open-userfaultfds-with-o_rdonly.patch
 sh-machvec-use-char-for-section-boundaries.patch
 mips-sgi-ip27-free-some-unused-memory.patch
 mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch
-fscrypt-simplify-master-key-locking.patch
 fs-security-add-sb_delete-hook.patch
-fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
 arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch
 arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch
 objtool-preserve-special-st_shndx-indexes-in-elf_upd.patch
diff --git a/queue-5.15/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch b/queue-5.15/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
deleted file mode 100644 (file)
index 7466d53..0000000
+++ /dev/null
@@ -1,1304 +0,0 @@
-From 3fed658e73d0c7e04b5f0380cf88b31fbdbd9ce0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 1 Sep 2022 12:32:06 -0700
-Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key
-
-From: Eric Biggers <ebiggers@google.com>
-
-[ Upstream commit d7e7b9af104c7b389a0c21eb26532511bce4b510 ]
-
-The approach of fs/crypto/ internally managing the fscrypt_master_key
-structs as the payloads of "struct key" objects contained in a
-"struct key" keyring has outlived its usefulness.  The original idea was
-to simplify the code by reusing code from the keyrings subsystem.
-However, several issues have arisen that can't easily be resolved:
-
-- When a master key struct is destroyed, blk_crypto_evict_key() must be
-  called on any per-mode keys embedded in it.  (This started being the
-  case when inline encryption support was added.)  Yet, the keyrings
-  subsystem can arbitrarily delay the destruction of keys, even past the
-  time the filesystem was unmounted.  Therefore, currently there is no
-  easy way to call blk_crypto_evict_key() when a master key is
-  destroyed.  Currently, this is worked around by holding an extra
-  reference to the filesystem's request_queue(s).  But it was overlooked
-  that the request_queue reference is *not* guaranteed to pin the
-  corresponding blk_crypto_profile too; for device-mapper devices that
-  support inline crypto, it doesn't.  This can cause a use-after-free.
-
-- When the last inode that was using an incompletely-removed master key
-  is evicted, the master key removal is completed by removing the key
-  struct from the keyring.  Currently this is done via key_invalidate().
-  Yet, key_invalidate() takes the key semaphore.  This can deadlock when
-  called from the shrinker, since in fscrypt_ioctl_add_key(), memory is
-  allocated with GFP_KERNEL under the same semaphore.
-
-- More generally, the fact that the keyrings subsystem can arbitrarily
-  delay the destruction of keys (via garbage collection delay, or via
-  random processes getting temporary key references) is undesirable, as
-  it means we can't strictly guarantee that all secrets are ever wiped.
-
-- Doing the master key lookups via the keyrings subsystem results in the
-  key_permission LSM hook being called.  fscrypt doesn't want this, as
-  all access control for encrypted files is designed to happen via the
-  files themselves, like any other files.  The workaround which SELinux
-  users are using is to change their SELinux policy to grant key search
-  access to all domains.  This works, but it is an odd extra step that
-  shouldn't really have to be done.
-
-The fix for all these issues is to change the implementation to what I
-should have done originally: don't use the keyrings subsystem to keep
-track of the filesystem's fscrypt_master_key structs.  Instead, just
-store them in a regular kernel data structure, and rework the reference
-counting, locking, and lifetime accordingly.  Retain support for
-RCU-mode key lookups by using a hash table.  Replace fscrypt_sb_free()
-with fscrypt_sb_delete(), which releases the keys synchronously and runs
-a bit earlier during unmount, so that block devices are still available.
-
-A side effect of this patch is that neither the master keys themselves
-nor the filesystem keyrings will be listed in /proc/keys anymore.
-("Master key users" and the master key users keyrings will still be
-listed.)  However, this was mostly an implementation detail, and it was
-intended just for debugging purposes.  I don't know of anyone using it.
-
-This patch does *not* change how "master key users" (->mk_users) works;
-that still uses the keyrings subsystem.  That is still needed for key
-quotas, and changing that isn't necessary to solve the issues listed
-above.  If we decide to change that too, it would be a separate patch.
-
-I've marked this as fixing the original commit that added the fscrypt
-keyring, but as noted above the most important issue that this patch
-fixes wasn't introduced until the addition of inline encryption support.
-
-Fixes: 22d94f493bfb ("fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl")
-Signed-off-by: Eric Biggers <ebiggers@google.com>
-Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/crypto/fscrypt_private.h |  71 ++++--
- fs/crypto/hooks.c           |  10 +-
- fs/crypto/keyring.c         | 486 +++++++++++++++++++-----------------
- fs/crypto/keysetup.c        |  81 +++---
- fs/crypto/policy.c          |   8 +-
- fs/super.c                  |   2 +-
- include/linux/fs.h          |   2 +-
- include/linux/fscrypt.h     |   4 +-
- 8 files changed, 353 insertions(+), 311 deletions(-)
-
-diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
-index cb25ef0cdf1f..373c434b375c 100644
---- a/fs/crypto/fscrypt_private.h
-+++ b/fs/crypto/fscrypt_private.h
-@@ -220,7 +220,7 @@ struct fscrypt_info {
-        * will be NULL if the master key was found in a process-subscribed
-        * keyring rather than in the filesystem-level keyring.
-        */
--      struct key *ci_master_key;
-+      struct fscrypt_master_key *ci_master_key;
-       /*
-        * Link in list of inodes that were unlocked with the master key.
-@@ -430,6 +430,40 @@ struct fscrypt_master_key_secret {
-  */
- struct fscrypt_master_key {
-+      /*
-+       * Back-pointer to the super_block of the filesystem to which this
-+       * master key has been added.  Only valid if ->mk_active_refs > 0.
-+       */
-+      struct super_block                      *mk_sb;
-+
-+      /*
-+       * Link in ->mk_sb->s_master_keys->key_hashtable.
-+       * Only valid if ->mk_active_refs > 0.
-+       */
-+      struct hlist_node                       mk_node;
-+
-+      /* Semaphore that protects ->mk_secret and ->mk_users */
-+      struct rw_semaphore                     mk_sem;
-+
-+      /*
-+       * Active and structural reference counts.  An active ref guarantees
-+       * that the struct continues to exist, continues to be in the keyring
-+       * ->mk_sb->s_master_keys, and that any embedded subkeys (e.g.
-+       * ->mk_direct_keys) that have been prepared continue to exist.
-+       * A structural ref only guarantees that the struct continues to exist.
-+       *
-+       * There is one active ref associated with ->mk_secret being present,
-+       * and one active ref for each inode in ->mk_decrypted_inodes.
-+       *
-+       * There is one structural ref associated with the active refcount being
-+       * nonzero.  Finding a key in the keyring also takes a structural ref,
-+       * which is then held temporarily while the key is operated on.
-+       */
-+      refcount_t                              mk_active_refs;
-+      refcount_t                              mk_struct_refs;
-+
-+      struct rcu_head                         mk_rcu_head;
-+
-       /*
-        * The secret key material.  After FS_IOC_REMOVE_ENCRYPTION_KEY is
-        * executed, this is wiped and no new inodes can be unlocked with this
-@@ -438,7 +472,10 @@ struct fscrypt_master_key {
-        * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
-        * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
-        *
--       * Locking: protected by this master key's key->sem.
-+       * While ->mk_secret is present, one ref in ->mk_active_refs is held.
-+       *
-+       * Locking: protected by ->mk_sem.  The manipulation of ->mk_active_refs
-+       *          associated with this field is protected by ->mk_sem as well.
-        */
-       struct fscrypt_master_key_secret        mk_secret;
-@@ -459,22 +496,12 @@ struct fscrypt_master_key {
-        *
-        * This is NULL for v1 policy keys; those can only be added by root.
-        *
--       * Locking: in addition to this keyring's own semaphore, this is
--       * protected by this master key's key->sem, so we can do atomic
--       * search+insert.  It can also be searched without taking any locks, but
--       * in that case the returned key may have already been removed.
-+       * Locking: protected by ->mk_sem.  (We don't just rely on the keyrings
-+       * subsystem semaphore ->mk_users->sem, as we need support for atomic
-+       * search+insert along with proper synchronization with ->mk_secret.)
-        */
-       struct key              *mk_users;
--      /*
--       * Length of ->mk_decrypted_inodes, plus one if mk_secret is present.
--       * Once this goes to 0, the master key is removed from ->s_master_keys.
--       * The 'struct fscrypt_master_key' will continue to live as long as the
--       * 'struct key' whose payload it is, but we won't let this reference
--       * count rise again.
--       */
--      refcount_t              mk_refcount;
--
-       /*
-        * List of inodes that were unlocked using this key.  This allows the
-        * inodes to be evicted efficiently if the key is removed.
-@@ -500,10 +527,10 @@ static inline bool
- is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
- {
-       /*
--       * The READ_ONCE() is only necessary for fscrypt_drop_inode() and
--       * fscrypt_key_describe().  These run in atomic context, so they can't
--       * take the key semaphore and thus 'secret' can change concurrently
--       * which would be a data race.  But they only need to know whether the
-+       * The READ_ONCE() is only necessary for fscrypt_drop_inode().
-+       * fscrypt_drop_inode() runs in atomic context, so it can't take the key
-+       * semaphore and thus 'secret' can change concurrently which would be a
-+       * data race.  But fscrypt_drop_inode() only need to know whether the
-        * secret *was* present at the time of check, so READ_ONCE() suffices.
-        */
-       return READ_ONCE(secret->size) != 0;
-@@ -532,7 +559,11 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
-       return 0;
- }
--struct key *
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk);
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk);
-+
-+struct fscrypt_master_key *
- fscrypt_find_master_key(struct super_block *sb,
-                       const struct fscrypt_key_specifier *mk_spec);
-diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
-index af74599ae1cf..be5c650e4957 100644
---- a/fs/crypto/hooks.c
-+++ b/fs/crypto/hooks.c
-@@ -5,8 +5,6 @@
-  * Encryption hooks for higher-level filesystem operations.
-  */
--#include <linux/key.h>
--
- #include "fscrypt_private.h"
- /**
-@@ -142,7 +140,6 @@ int fscrypt_prepare_setflags(struct inode *inode,
-                            unsigned int oldflags, unsigned int flags)
- {
-       struct fscrypt_info *ci;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -158,14 +155,13 @@ int fscrypt_prepare_setflags(struct inode *inode,
-               ci = inode->i_crypt_info;
-               if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
-                       return -EINVAL;
--              key = ci->ci_master_key;
--              mk = key->payload.data[0];
--              down_read(&key->sem);
-+              mk = ci->ci_master_key;
-+              down_read(&mk->mk_sem);
-               if (is_master_key_secret_present(&mk->mk_secret))
-                       err = fscrypt_derive_dirhash_key(ci, mk);
-               else
-                       err = -ENOKEY;
--              up_read(&key->sem);
-+              up_read(&mk->mk_sem);
-               return err;
-       }
-       return 0;
-diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
-index 0b3ffbb4faf4..175b071beaf8 100644
---- a/fs/crypto/keyring.c
-+++ b/fs/crypto/keyring.c
-@@ -18,6 +18,7 @@
-  * information about these ioctls.
-  */
-+#include <asm/unaligned.h>
- #include <crypto/skcipher.h>
- #include <linux/key-type.h>
- #include <linux/random.h>
-@@ -25,6 +26,18 @@
- #include "fscrypt_private.h"
-+/* The master encryption keys for a filesystem (->s_master_keys) */
-+struct fscrypt_keyring {
-+      /*
-+       * Lock that protects ->key_hashtable.  It does *not* protect the
-+       * fscrypt_master_key structs themselves.
-+       */
-+      spinlock_t lock;
-+
-+      /* Hash table that maps fscrypt_key_specifier to fscrypt_master_key */
-+      struct hlist_head key_hashtable[128];
-+};
-+
- static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret)
- {
-       fscrypt_destroy_hkdf(&secret->hkdf);
-@@ -38,20 +51,70 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst,
-       memzero_explicit(src, sizeof(*src));
- }
--static void free_master_key(struct fscrypt_master_key *mk)
-+static void fscrypt_free_master_key(struct rcu_head *head)
-+{
-+      struct fscrypt_master_key *mk =
-+              container_of(head, struct fscrypt_master_key, mk_rcu_head);
-+      /*
-+       * The master key secret and any embedded subkeys should have already
-+       * been wiped when the last active reference to the fscrypt_master_key
-+       * struct was dropped; doing it here would be unnecessarily late.
-+       * Nevertheless, use kfree_sensitive() in case anything was missed.
-+       */
-+      kfree_sensitive(mk);
-+}
-+
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk)
-+{
-+      if (!refcount_dec_and_test(&mk->mk_struct_refs))
-+              return;
-+      /*
-+       * No structural references left, so free ->mk_users, and also free the
-+       * fscrypt_master_key struct itself after an RCU grace period ensures
-+       * that concurrent keyring lookups can no longer find it.
-+       */
-+      WARN_ON(refcount_read(&mk->mk_active_refs) != 0);
-+      key_put(mk->mk_users);
-+      mk->mk_users = NULL;
-+      call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
-+}
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk)
- {
-+      struct super_block *sb = mk->mk_sb;
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       size_t i;
--      wipe_master_key_secret(&mk->mk_secret);
-+      if (!refcount_dec_and_test(&mk->mk_active_refs))
-+              return;
-+      /*
-+       * No active references left, so complete the full removal of this
-+       * fscrypt_master_key struct by removing it from the keyring and
-+       * destroying any subkeys embedded in it.
-+       */
-+
-+      spin_lock(&keyring->lock);
-+      hlist_del_rcu(&mk->mk_node);
-+      spin_unlock(&keyring->lock);
-+
-+      /*
-+       * ->mk_active_refs == 0 implies that ->mk_secret is not present and
-+       * that ->mk_decrypted_inodes is empty.
-+       */
-+      WARN_ON(is_master_key_secret_present(&mk->mk_secret));
-+      WARN_ON(!list_empty(&mk->mk_decrypted_inodes));
-       for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
-               fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]);
-       }
-+      memzero_explicit(&mk->mk_ino_hash_key,
-+                       sizeof(mk->mk_ino_hash_key));
-+      mk->mk_ino_hash_key_initialized = false;
--      key_put(mk->mk_users);
--      kfree_sensitive(mk);
-+      /* Drop the structural ref associated with the active refs. */
-+      fscrypt_put_master_key(mk);
- }
- static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-@@ -61,44 +124,6 @@ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-       return master_key_spec_len(spec) != 0;
- }
--static int fscrypt_key_instantiate(struct key *key,
--                                 struct key_preparsed_payload *prep)
--{
--      key->payload.data[0] = (struct fscrypt_master_key *)prep->data;
--      return 0;
--}
--
--static void fscrypt_key_destroy(struct key *key)
--{
--      free_master_key(key->payload.data[0]);
--}
--
--static void fscrypt_key_describe(const struct key *key, struct seq_file *m)
--{
--      seq_puts(m, key->description);
--
--      if (key_is_positive(key)) {
--              const struct fscrypt_master_key *mk = key->payload.data[0];
--
--              if (!is_master_key_secret_present(&mk->mk_secret))
--                      seq_puts(m, ": secret removed");
--      }
--}
--
--/*
-- * Type of key in ->s_master_keys.  Each key of this type represents a master
-- * key which has been added to the filesystem.  Its payload is a
-- * 'struct fscrypt_master_key'.  The "." prefix in the key type name prevents
-- * users from adding keys of this type via the keyrings syscalls rather than via
-- * the intended method of FS_IOC_ADD_ENCRYPTION_KEY.
-- */
--static struct key_type key_type_fscrypt = {
--      .name                   = "._fscrypt",
--      .instantiate            = fscrypt_key_instantiate,
--      .destroy                = fscrypt_key_destroy,
--      .describe               = fscrypt_key_describe,
--};
--
- static int fscrypt_user_key_instantiate(struct key *key,
-                                       struct key_preparsed_payload *prep)
- {
-@@ -131,32 +156,6 @@ static struct key_type key_type_fscrypt_user = {
-       .describe               = fscrypt_user_key_describe,
- };
--/* Search ->s_master_keys or ->mk_users */
--static struct key *search_fscrypt_keyring(struct key *keyring,
--                                        struct key_type *type,
--                                        const char *description)
--{
--      /*
--       * We need to mark the keyring reference as "possessed" so that we
--       * acquire permission to search it, via the KEY_POS_SEARCH permission.
--       */
--      key_ref_t keyref = make_key_ref(keyring, true /* possessed */);
--
--      keyref = keyring_search(keyref, type, description, false);
--      if (IS_ERR(keyref)) {
--              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
--                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
--                      keyref = ERR_PTR(-ENOKEY);
--              return ERR_CAST(keyref);
--      }
--      return key_ref_to_ptr(keyref);
--}
--
--#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE   \
--      (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id))
--
--#define FSCRYPT_MK_DESCRIPTION_SIZE   (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1)
--
- #define FSCRYPT_MK_USERS_DESCRIPTION_SIZE     \
-       (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
-        CONST_STRLEN("-users") + 1)
-@@ -164,21 +163,6 @@ static struct key *search_fscrypt_keyring(struct key *keyring,
- #define FSCRYPT_MK_USER_DESCRIPTION_SIZE      \
-       (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
--static void format_fs_keyring_description(
--                      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE],
--                      const struct super_block *sb)
--{
--      sprintf(description, "fscrypt-%s", sb->s_id);
--}
--
--static void format_mk_description(
--                      char description[FSCRYPT_MK_DESCRIPTION_SIZE],
--                      const struct fscrypt_key_specifier *mk_spec)
--{
--      sprintf(description, "%*phN",
--              master_key_spec_len(mk_spec), (u8 *)&mk_spec->u);
--}
--
- static void format_mk_users_keyring_description(
-                       char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
-                       const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
-@@ -199,20 +183,15 @@ static void format_mk_user_description(
- /* Create ->s_master_keys if needed.  Synchronized by fscrypt_add_key_mutex. */
- static int allocate_filesystem_keyring(struct super_block *sb)
- {
--      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE];
--      struct key *keyring;
-+      struct fscrypt_keyring *keyring;
-       if (sb->s_master_keys)
-               return 0;
--      format_fs_keyring_description(description, sb);
--      keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
--                              current_cred(), KEY_POS_SEARCH |
--                                KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW,
--                              KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
--      if (IS_ERR(keyring))
--              return PTR_ERR(keyring);
--
-+      keyring = kzalloc(sizeof(*keyring), GFP_KERNEL);
-+      if (!keyring)
-+              return -ENOMEM;
-+      spin_lock_init(&keyring->lock);
-       /*
-        * Pairs with the smp_load_acquire() in fscrypt_find_master_key().
-        * I.e., here we publish ->s_master_keys with a RELEASE barrier so that
-@@ -222,21 +201,75 @@ static int allocate_filesystem_keyring(struct super_block *sb)
-       return 0;
- }
--void fscrypt_sb_free(struct super_block *sb)
-+/*
-+ * This is called at unmount time to release all encryption keys that have been
-+ * added to the filesystem, along with the keyring that contains them.
-+ *
-+ * Note that besides clearing and freeing memory, this might need to evict keys
-+ * from the keyslots of an inline crypto engine.  Therefore, this must be called
-+ * while the filesystem's underlying block device(s) are still available.
-+ */
-+void fscrypt_sb_delete(struct super_block *sb)
- {
--      key_put(sb->s_master_keys);
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-+      size_t i;
-+
-+      if (!keyring)
-+              return;
-+
-+      for (i = 0; i < ARRAY_SIZE(keyring->key_hashtable); i++) {
-+              struct hlist_head *bucket = &keyring->key_hashtable[i];
-+              struct fscrypt_master_key *mk;
-+              struct hlist_node *tmp;
-+
-+              hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
-+                      /*
-+                       * Since all inodes were already evicted, every key
-+                       * remaining in the keyring should have an empty inode
-+                       * list, and should only still be in the keyring due to
-+                       * the single active ref associated with ->mk_secret.
-+                       * There should be no structural refs beyond the one
-+                       * associated with the active ref.
-+                       */
-+                      WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
-+                      WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
-+                      WARN_ON(!is_master_key_secret_present(&mk->mk_secret));
-+                      wipe_master_key_secret(&mk->mk_secret);
-+                      fscrypt_put_master_key_activeref(mk);
-+              }
-+      }
-+      kfree_sensitive(keyring);
-       sb->s_master_keys = NULL;
- }
-+static struct hlist_head *
-+fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring,
-+                     const struct fscrypt_key_specifier *mk_spec)
-+{
-+      /*
-+       * Since key specifiers should be "random" values, it is sufficient to
-+       * use a trivial hash function that just takes the first several bits of
-+       * the key specifier.
-+       */
-+      unsigned long i = get_unaligned((unsigned long *)&mk_spec->u);
-+
-+      return &keyring->key_hashtable[i % ARRAY_SIZE(keyring->key_hashtable)];
-+}
-+
- /*
-- * Find the specified master key in ->s_master_keys.
-- * Returns ERR_PTR(-ENOKEY) if not found.
-+ * Find the specified master key struct in ->s_master_keys and take a structural
-+ * ref to it.  The structural ref guarantees that the key struct continues to
-+ * exist, but it does *not* guarantee that ->s_master_keys continues to contain
-+ * the key struct.  The structural ref needs to be dropped by
-+ * fscrypt_put_master_key().  Returns NULL if the key struct is not found.
-  */
--struct key *fscrypt_find_master_key(struct super_block *sb,
--                                  const struct fscrypt_key_specifier *mk_spec)
-+struct fscrypt_master_key *
-+fscrypt_find_master_key(struct super_block *sb,
-+                      const struct fscrypt_key_specifier *mk_spec)
- {
--      struct key *keyring;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
-+      struct fscrypt_keyring *keyring;
-+      struct hlist_head *bucket;
-+      struct fscrypt_master_key *mk;
-       /*
-        * Pairs with the smp_store_release() in allocate_filesystem_keyring().
-@@ -246,10 +279,38 @@ struct key *fscrypt_find_master_key(struct super_block *sb,
-        */
-       keyring = smp_load_acquire(&sb->s_master_keys);
-       if (keyring == NULL)
--              return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */
--
--      format_mk_description(description, mk_spec);
--      return search_fscrypt_keyring(keyring, &key_type_fscrypt, description);
-+              return NULL; /* No keyring yet, so no keys yet. */
-+
-+      bucket = fscrypt_mk_hash_bucket(keyring, mk_spec);
-+      rcu_read_lock();
-+      switch (mk_spec->type) {
-+      case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
-+                          memcmp(mk->mk_spec.u.descriptor,
-+                                 mk_spec->u.descriptor,
-+                                 FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&
-+                          memcmp(mk->mk_spec.u.identifier,
-+                                 mk_spec->u.identifier,
-+                                 FSCRYPT_KEY_IDENTIFIER_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      }
-+      mk = NULL;
-+out:
-+      rcu_read_unlock();
-+      return mk;
- }
- static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
-@@ -277,17 +338,30 @@ static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
- static struct key *find_master_key_user(struct fscrypt_master_key *mk)
- {
-       char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
-+      key_ref_t keyref;
-       format_mk_user_description(description, mk->mk_spec.u.identifier);
--      return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_user,
--                                    description);
-+
-+      /*
-+       * We need to mark the keyring reference as "possessed" so that we
-+       * acquire permission to search it, via the KEY_POS_SEARCH permission.
-+       */
-+      keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/),
-+                              &key_type_fscrypt_user, description, false);
-+      if (IS_ERR(keyref)) {
-+              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
-+                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
-+                      keyref = ERR_PTR(-ENOKEY);
-+              return ERR_CAST(keyref);
-+      }
-+      return key_ref_to_ptr(keyref);
- }
- /*
-  * Give the current user a "key" in ->mk_users.  This charges the user's quota
-  * and marks the master key as added by the current user, so that it cannot be
-- * removed by another user with the key.  Either the master key's key->sem must
-- * be held for write, or the master key must be still undergoing initialization.
-+ * removed by another user with the key.  Either ->mk_sem must be held for
-+ * write, or the master key must be still undergoing initialization.
-  */
- static int add_master_key_user(struct fscrypt_master_key *mk)
- {
-@@ -309,7 +383,7 @@ static int add_master_key_user(struct fscrypt_master_key *mk)
- /*
-  * Remove the current user's "key" from ->mk_users.
-- * The master key's key->sem must be held for write.
-+ * ->mk_sem must be held for write.
-  *
-  * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
-  */
-@@ -327,63 +401,49 @@ static int remove_master_key_user(struct fscrypt_master_key *mk)
- }
- /*
-- * Allocate a new fscrypt_master_key which contains the given secret, set it as
-- * the payload of a new 'struct key' of type fscrypt, and link the 'struct key'
-- * into the given keyring.  Synchronized by fscrypt_add_key_mutex.
-+ * Allocate a new fscrypt_master_key, transfer the given secret over to it, and
-+ * insert it into sb->s_master_keys.
-  */
--static int add_new_master_key(struct fscrypt_master_key_secret *secret,
--                            const struct fscrypt_key_specifier *mk_spec,
--                            struct key *keyring)
-+static int add_new_master_key(struct super_block *sb,
-+                            struct fscrypt_master_key_secret *secret,
-+                            const struct fscrypt_key_specifier *mk_spec)
- {
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       struct fscrypt_master_key *mk;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
--      struct key *key;
-       int err;
-       mk = kzalloc(sizeof(*mk), GFP_KERNEL);
-       if (!mk)
-               return -ENOMEM;
-+      mk->mk_sb = sb;
-+      init_rwsem(&mk->mk_sem);
-+      refcount_set(&mk->mk_struct_refs, 1);
-       mk->mk_spec = *mk_spec;
--      move_master_key_secret(&mk->mk_secret, secret);
--
--      refcount_set(&mk->mk_refcount, 1); /* secret is present */
-       INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
-       spin_lock_init(&mk->mk_decrypted_inodes_lock);
-       if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
-               err = allocate_master_key_users_keyring(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-               err = add_master_key_user(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-       }
--      /*
--       * Note that we don't charge this key to anyone's quota, since when
--       * ->mk_users is in use those keys are charged instead, and otherwise
--       * (when ->mk_users isn't in use) only root can add these keys.
--       */
--      format_mk_description(description, mk_spec);
--      key = key_alloc(&key_type_fscrypt, description,
--                      GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
--                      KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_USR_VIEW,
--                      KEY_ALLOC_NOT_IN_QUOTA, NULL);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              goto out_free_mk;
--      }
--      err = key_instantiate_and_link(key, mk, sizeof(*mk), keyring, NULL);
--      key_put(key);
--      if (err)
--              goto out_free_mk;
-+      move_master_key_secret(&mk->mk_secret, secret);
-+      refcount_set(&mk->mk_active_refs, 1); /* ->mk_secret is present */
-+      spin_lock(&keyring->lock);
-+      hlist_add_head_rcu(&mk->mk_node,
-+                         fscrypt_mk_hash_bucket(keyring, mk_spec));
-+      spin_unlock(&keyring->lock);
-       return 0;
--out_free_mk:
--      free_master_key(mk);
-+out_put:
-+      fscrypt_put_master_key(mk);
-       return err;
- }
-@@ -392,42 +452,34 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret,
- static int add_existing_master_key(struct fscrypt_master_key *mk,
-                                  struct fscrypt_master_key_secret *secret)
- {
--      struct key *mk_user;
--      bool rekey;
-       int err;
-       /*
-        * If the current user is already in ->mk_users, then there's nothing to
--       * do.  (Not applicable for v1 policy keys, which have NULL ->mk_users.)
-+       * do.  Otherwise, we need to add the user to ->mk_users.  (Neither is
-+       * applicable for v1 policy keys, which have NULL ->mk_users.)
-        */
-       if (mk->mk_users) {
--              mk_user = find_master_key_user(mk);
-+              struct key *mk_user = find_master_key_user(mk);
-+
-               if (mk_user != ERR_PTR(-ENOKEY)) {
-                       if (IS_ERR(mk_user))
-                               return PTR_ERR(mk_user);
-                       key_put(mk_user);
-                       return 0;
-               }
--      }
--
--      /* If we'll be re-adding ->mk_secret, try to take the reference. */
--      rekey = !is_master_key_secret_present(&mk->mk_secret);
--      if (rekey && !refcount_inc_not_zero(&mk->mk_refcount))
--              return KEY_DEAD;
--
--      /* Add the current user to ->mk_users, if applicable. */
--      if (mk->mk_users) {
-               err = add_master_key_user(mk);
--              if (err) {
--                      if (rekey && refcount_dec_and_test(&mk->mk_refcount))
--                              return KEY_DEAD;
-+              if (err)
-                       return err;
--              }
-       }
-       /* Re-add the secret if needed. */
--      if (rekey)
-+      if (!is_master_key_secret_present(&mk->mk_secret)) {
-+              if (!refcount_inc_not_zero(&mk->mk_active_refs))
-+                      return KEY_DEAD;
-               move_master_key_secret(&mk->mk_secret, secret);
-+      }
-+
-       return 0;
- }
-@@ -436,38 +488,36 @@ static int do_add_master_key(struct super_block *sb,
-                            const struct fscrypt_key_specifier *mk_spec)
- {
-       static DEFINE_MUTEX(fscrypt_add_key_mutex);
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       int err;
-       mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */
--retry:
--      key = fscrypt_find_master_key(sb, mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              if (err != -ENOKEY)
--                      goto out_unlock;
-+
-+      mk = fscrypt_find_master_key(sb, mk_spec);
-+      if (!mk) {
-               /* Didn't find the key in ->s_master_keys.  Add it. */
-               err = allocate_filesystem_keyring(sb);
--              if (err)
--                      goto out_unlock;
--              err = add_new_master_key(secret, mk_spec, sb->s_master_keys);
-+              if (!err)
-+                      err = add_new_master_key(sb, secret, mk_spec);
-       } else {
-               /*
-                * Found the key in ->s_master_keys.  Re-add the secret if
-                * needed, and add the user to ->mk_users if needed.
-                */
--              down_write(&key->sem);
--              err = add_existing_master_key(key->payload.data[0], secret);
--              up_write(&key->sem);
-+              down_write(&mk->mk_sem);
-+              err = add_existing_master_key(mk, secret);
-+              up_write(&mk->mk_sem);
-               if (err == KEY_DEAD) {
--                      /* Key being removed or needs to be removed */
--                      key_invalidate(key);
--                      key_put(key);
--                      goto retry;
-+                      /*
-+                       * We found a key struct, but it's already been fully
-+                       * removed.  Ignore the old struct and add a new one.
-+                       * fscrypt_add_key_mutex means we don't need to worry
-+                       * about concurrent adds.
-+                       */
-+                      err = add_new_master_key(sb, secret, mk_spec);
-               }
--              key_put(key);
-+              fscrypt_put_master_key(mk);
-       }
--out_unlock:
-       mutex_unlock(&fscrypt_add_key_mutex);
-       return err;
- }
-@@ -731,19 +781,19 @@ int fscrypt_verify_key_added(struct super_block *sb,
-                            const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
- {
-       struct fscrypt_key_specifier mk_spec;
--      struct key *key, *mk_user;
-       struct fscrypt_master_key *mk;
-+      struct key *mk_user;
-       int err;
-       mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
-       memcpy(mk_spec.u.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE);
--      key = fscrypt_find_master_key(sb, &mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &mk_spec);
-+      if (!mk) {
-+              err = -ENOKEY;
-               goto out;
-       }
--      mk = key->payload.data[0];
-+      down_read(&mk->mk_sem);
-       mk_user = find_master_key_user(mk);
-       if (IS_ERR(mk_user)) {
-               err = PTR_ERR(mk_user);
-@@ -751,7 +801,8 @@ int fscrypt_verify_key_added(struct super_block *sb,
-               key_put(mk_user);
-               err = 0;
-       }
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (err == -ENOKEY && capable(CAP_FOWNER))
-               err = 0;
-@@ -913,11 +964,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_remove_key_arg __user *uarg = _uarg;
-       struct fscrypt_remove_key_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       u32 status_flags = 0;
-       int err;
--      bool dead;
-+      bool inodes_remain;
-       if (copy_from_user(&arg, uarg, sizeof(arg)))
-               return -EFAULT;
-@@ -937,12 +987,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               return -EACCES;
-       /* Find the key being removed. */
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key))
--              return PTR_ERR(key);
--      mk = key->payload.data[0];
--
--      down_write(&key->sem);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk)
-+              return -ENOKEY;
-+      down_write(&mk->mk_sem);
-       /* If relevant, remove current user's (or all users) claim to the key */
-       if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -951,7 +999,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               else
-                       err = remove_master_key_user(mk);
-               if (err) {
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-               if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -963,26 +1011,22 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-                       status_flags |=
-                               FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS;
-                       err = 0;
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-       }
-       /* No user claims remaining.  Go ahead and wipe the secret. */
--      dead = false;
-+      err = -ENOKEY;
-       if (is_master_key_secret_present(&mk->mk_secret)) {
-               wipe_master_key_secret(&mk->mk_secret);
--              dead = refcount_dec_and_test(&mk->mk_refcount);
--      }
--      up_write(&key->sem);
--      if (dead) {
--              /*
--               * No inodes reference the key, and we wiped the secret, so the
--               * key object is free to be removed from the keyring.
--               */
--              key_invalidate(key);
-+              fscrypt_put_master_key_activeref(mk);
-               err = 0;
--      } else {
-+      }
-+      inodes_remain = refcount_read(&mk->mk_active_refs) > 0;
-+      up_write(&mk->mk_sem);
-+
-+      if (inodes_remain) {
-               /* Some inodes still reference this key; try to evict them. */
-               err = try_to_lock_encrypted_files(sb, mk);
-               if (err == -EBUSY) {
-@@ -998,7 +1042,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-        * has been fully removed including all files locked.
-        */
- out_put_key:
--      key_put(key);
-+      fscrypt_put_master_key(mk);
-       if (err == 0)
-               err = put_user(status_flags, &uarg->removal_status_flags);
-       return err;
-@@ -1045,7 +1089,6 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
- {
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_get_key_status_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -1062,19 +1105,18 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       arg.user_count = 0;
-       memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved));
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY))
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk) {
-               arg.status = FSCRYPT_KEY_STATUS_ABSENT;
-               err = 0;
-               goto out;
-       }
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
--              arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED;
-+              arg.status = refcount_read(&mk->mk_active_refs) > 0 ?
-+                      FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED :
-+                      FSCRYPT_KEY_STATUS_ABSENT /* raced with full removal */;
-               err = 0;
-               goto out_release_key;
-       }
-@@ -1096,8 +1138,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       }
-       err = 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (!err && copy_to_user(uarg, &arg, sizeof(arg)))
-               err = -EFAULT;
-@@ -1109,13 +1151,9 @@ int __init fscrypt_init_keyring(void)
- {
-       int err;
--      err = register_key_type(&key_type_fscrypt);
--      if (err)
--              return err;
--
-       err = register_key_type(&key_type_fscrypt_user);
-       if (err)
--              goto err_unregister_fscrypt;
-+              return err;
-       err = register_key_type(&key_type_fscrypt_provisioning);
-       if (err)
-@@ -1125,7 +1163,5 @@ int __init fscrypt_init_keyring(void)
- err_unregister_fscrypt_user:
-       unregister_key_type(&key_type_fscrypt_user);
--err_unregister_fscrypt:
--      unregister_key_type(&key_type_fscrypt);
-       return err;
- }
-diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
-index 89cd533a88bf..c3fbd594cc79 100644
---- a/fs/crypto/keysetup.c
-+++ b/fs/crypto/keysetup.c
-@@ -9,7 +9,6 @@
-  */
- #include <crypto/skcipher.h>
--#include <linux/key.h>
- #include <linux/random.h>
- #include "fscrypt_private.h"
-@@ -151,6 +150,7 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key)
- {
-       crypto_free_skcipher(prep_key->tfm);
-       fscrypt_destroy_inline_crypt_key(prep_key);
-+      memzero_explicit(prep_key, sizeof(*prep_key));
- }
- /* Given a per-file encryption key, set up the file's crypto transform object */
-@@ -404,20 +404,18 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
- /*
-  * Find the master key, then set up the inode's actual encryption key.
-  *
-- * If the master key is found in the filesystem-level keyring, then the
-- * corresponding 'struct key' is returned in *master_key_ret with its semaphore
-- * read-locked.  This is needed to ensure that only one task links the
-- * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create
-- * an fscrypt_info for the same inode), and to synchronize the master key being
-- * removed with a new inode starting to use it.
-+ * If the master key is found in the filesystem-level keyring, then it is
-+ * returned in *mk_ret with its semaphore read-locked.  This is needed to ensure
-+ * that only one task links the fscrypt_info into ->mk_decrypted_inodes (as
-+ * multiple tasks may race to create an fscrypt_info for the same inode), and to
-+ * synchronize the master key being removed with a new inode starting to use it.
-  */
- static int setup_file_encryption_key(struct fscrypt_info *ci,
-                                    bool need_dirhash_key,
--                                   struct key **master_key_ret)
-+                                   struct fscrypt_master_key **mk_ret)
- {
--      struct key *key;
--      struct fscrypt_master_key *mk = NULL;
-       struct fscrypt_key_specifier mk_spec;
-+      struct fscrypt_master_key *mk;
-       int err;
-       err = fscrypt_select_encryption_impl(ci);
-@@ -442,11 +440,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-               return -EINVAL;
-       }
--      key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY) ||
--                  ci->ci_policy.version != FSCRYPT_POLICY_V1)
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
-+      if (!mk) {
-+              if (ci->ci_policy.version != FSCRYPT_POLICY_V1)
-+                      return -ENOKEY;
-               /*
-                * As a legacy fallback for v1 policies, search for the key in
-@@ -456,9 +453,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-                */
-               return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci);
-       }
--
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
-@@ -486,18 +481,18 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       if (err)
-               goto out_release_key;
--      *master_key_ret = key;
-+      *mk_ret = mk;
-       return 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
-       return err;
- }
- static void put_crypt_info(struct fscrypt_info *ci)
- {
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       if (!ci)
-               return;
-@@ -507,24 +502,18 @@ static void put_crypt_info(struct fscrypt_info *ci)
-       else if (ci->ci_owns_key)
-               fscrypt_destroy_prepared_key(&ci->ci_enc_key);
--      key = ci->ci_master_key;
--      if (key) {
--              struct fscrypt_master_key *mk = key->payload.data[0];
--
-+      mk = ci->ci_master_key;
-+      if (mk) {
-               /*
-                * Remove this inode from the list of inodes that were unlocked
--               * with the master key.
--               *
--               * In addition, if we're removing the last inode from a key that
--               * already had its secret removed, invalidate the key so that it
--               * gets removed from ->s_master_keys.
-+               * with the master key.  In addition, if we're removing the last
-+               * inode from a master key struct that already had its secret
-+               * removed, then complete the full removal of the struct.
-                */
-               spin_lock(&mk->mk_decrypted_inodes_lock);
-               list_del(&ci->ci_master_key_link);
-               spin_unlock(&mk->mk_decrypted_inodes_lock);
--              if (refcount_dec_and_test(&mk->mk_refcount))
--                      key_invalidate(key);
--              key_put(key);
-+              fscrypt_put_master_key_activeref(mk);
-       }
-       memzero_explicit(ci, sizeof(*ci));
-       kmem_cache_free(fscrypt_info_cachep, ci);
-@@ -538,7 +527,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
- {
-       struct fscrypt_info *crypt_info;
-       struct fscrypt_mode *mode;
--      struct key *master_key = NULL;
-+      struct fscrypt_master_key *mk = NULL;
-       int res;
-       res = fscrypt_initialize(inode->i_sb->s_cop->flags);
-@@ -561,8 +550,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
-       crypt_info->ci_mode = mode;
--      res = setup_file_encryption_key(crypt_info, need_dirhash_key,
--                                      &master_key);
-+      res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
-       if (res)
-               goto out;
-@@ -577,12 +565,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-                * We won the race and set ->i_crypt_info to our crypt_info.
-                * Now link it into the master key's inode list.
-                */
--              if (master_key) {
--                      struct fscrypt_master_key *mk =
--                              master_key->payload.data[0];
--
--                      refcount_inc(&mk->mk_refcount);
--                      crypt_info->ci_master_key = key_get(master_key);
-+              if (mk) {
-+                      crypt_info->ci_master_key = mk;
-+                      refcount_inc(&mk->mk_active_refs);
-                       spin_lock(&mk->mk_decrypted_inodes_lock);
-                       list_add(&crypt_info->ci_master_key_link,
-                                &mk->mk_decrypted_inodes);
-@@ -592,9 +577,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       }
-       res = 0;
- out:
--      if (master_key) {
--              up_read(&master_key->sem);
--              key_put(master_key);
-+      if (mk) {
-+              up_read(&mk->mk_sem);
-+              fscrypt_put_master_key(mk);
-       }
-       put_crypt_info(crypt_info);
-       return res;
-@@ -759,7 +744,6 @@ EXPORT_SYMBOL(fscrypt_free_inode);
- int fscrypt_drop_inode(struct inode *inode)
- {
-       const struct fscrypt_info *ci = fscrypt_get_info(inode);
--      const struct fscrypt_master_key *mk;
-       /*
-        * If ci is NULL, then the inode doesn't have an encryption key set up
-@@ -769,7 +753,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        */
-       if (!ci || !ci->ci_master_key)
-               return 0;
--      mk = ci->ci_master_key->payload.data[0];
-       /*
-        * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes
-@@ -788,6 +771,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        * then the thread removing the key will either evict the inode itself
-        * or will correctly detect that it wasn't evicted due to the race.
-        */
--      return !is_master_key_secret_present(&mk->mk_secret);
-+      return !is_master_key_secret_present(&ci->ci_master_key->mk_secret);
- }
- EXPORT_SYMBOL_GPL(fscrypt_drop_inode);
-diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
-index ed3d623724cd..cad34dbe8e29 100644
---- a/fs/crypto/policy.c
-+++ b/fs/crypto/policy.c
-@@ -692,12 +692,8 @@ int fscrypt_set_context(struct inode *inode, void *fs_data)
-        * delayed key setup that requires the inode number.
-        */
-       if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
--          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
--              const struct fscrypt_master_key *mk =
--                      ci->ci_master_key->payload.data[0];
--
--              fscrypt_hash_inode_number(ci, mk);
--      }
-+          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
-+              fscrypt_hash_inode_number(ci, ci->ci_master_key);
-       return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, fs_data);
- }
-diff --git a/fs/super.c b/fs/super.c
-index 87379bb1f7a3..479c6bfc5033 100644
---- a/fs/super.c
-+++ b/fs/super.c
-@@ -293,7 +293,6 @@ static void __put_super(struct super_block *s)
-               WARN_ON(s->s_inode_lru.node);
-               WARN_ON(!list_empty(&s->s_mounts));
-               security_sb_free(s);
--              fscrypt_sb_free(s);
-               put_user_ns(s->s_user_ns);
-               kfree(s->s_subtype);
-               call_rcu(&s->rcu, destroy_super_rcu);
-@@ -454,6 +453,7 @@ void generic_shutdown_super(struct super_block *sb)
-               evict_inodes(sb);
-               /* only nonzero refcount inodes can have marks */
-               fsnotify_sb_delete(sb);
-+              fscrypt_sb_delete(sb);
-               security_sb_delete(sb);
-               if (sb->s_dio_done_wq) {
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index fd4c450dc612..806ac72c7220 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -1487,7 +1487,7 @@ struct super_block {
-       const struct xattr_handler **s_xattr;
- #ifdef CONFIG_FS_ENCRYPTION
-       const struct fscrypt_operations *s_cop;
--      struct key              *s_master_keys; /* master crypto keys in use */
-+      struct fscrypt_keyring  *s_master_keys; /* master crypto keys in use */
- #endif
- #ifdef CONFIG_FS_VERITY
-       const struct fsverity_operations *s_vop;
-diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
-index e912ed9141d9..3867e25d5a95 100644
---- a/include/linux/fscrypt.h
-+++ b/include/linux/fscrypt.h
-@@ -294,7 +294,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--void fscrypt_sb_free(struct super_block *sb);
-+void fscrypt_sb_delete(struct super_block *sb);
- int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
- int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg);
- int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *arg);
-@@ -482,7 +482,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--static inline void fscrypt_sb_free(struct super_block *sb)
-+static inline void fscrypt_sb_delete(struct super_block *sb)
- {
- }
--- 
-2.35.1
-
index 5cc7d810d4cfbeb9c66e27b1248c48c62d09a222..bc3c6b0920a69b9be01e44a8e6f4697d4fde9ef5 100644 (file)
@@ -140,7 +140,6 @@ thermal-cpufreq_cooling-check-the-policy-first-in-cp.patch
 sh-machvec-use-char-for-section-boundaries.patch
 mips-sgi-ip27-free-some-unused-memory.patch
 mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch
-fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
 arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch
 arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch
 objtool-preserve-special-st_shndx-indexes-in-elf_upd.patch
diff --git a/queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch b/queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
deleted file mode 100644 (file)
index ac483ce..0000000
+++ /dev/null
@@ -1,1304 +0,0 @@
-From 15d10c3e27d4314c2ba2fdb4caecd290ba0b9795 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 1 Sep 2022 12:32:06 -0700
-Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key
-
-From: Eric Biggers <ebiggers@google.com>
-
-[ Upstream commit d7e7b9af104c7b389a0c21eb26532511bce4b510 ]
-
-The approach of fs/crypto/ internally managing the fscrypt_master_key
-structs as the payloads of "struct key" objects contained in a
-"struct key" keyring has outlived its usefulness.  The original idea was
-to simplify the code by reusing code from the keyrings subsystem.
-However, several issues have arisen that can't easily be resolved:
-
-- When a master key struct is destroyed, blk_crypto_evict_key() must be
-  called on any per-mode keys embedded in it.  (This started being the
-  case when inline encryption support was added.)  Yet, the keyrings
-  subsystem can arbitrarily delay the destruction of keys, even past the
-  time the filesystem was unmounted.  Therefore, currently there is no
-  easy way to call blk_crypto_evict_key() when a master key is
-  destroyed.  Currently, this is worked around by holding an extra
-  reference to the filesystem's request_queue(s).  But it was overlooked
-  that the request_queue reference is *not* guaranteed to pin the
-  corresponding blk_crypto_profile too; for device-mapper devices that
-  support inline crypto, it doesn't.  This can cause a use-after-free.
-
-- When the last inode that was using an incompletely-removed master key
-  is evicted, the master key removal is completed by removing the key
-  struct from the keyring.  Currently this is done via key_invalidate().
-  Yet, key_invalidate() takes the key semaphore.  This can deadlock when
-  called from the shrinker, since in fscrypt_ioctl_add_key(), memory is
-  allocated with GFP_KERNEL under the same semaphore.
-
-- More generally, the fact that the keyrings subsystem can arbitrarily
-  delay the destruction of keys (via garbage collection delay, or via
-  random processes getting temporary key references) is undesirable, as
-  it means we can't strictly guarantee that all secrets are ever wiped.
-
-- Doing the master key lookups via the keyrings subsystem results in the
-  key_permission LSM hook being called.  fscrypt doesn't want this, as
-  all access control for encrypted files is designed to happen via the
-  files themselves, like any other files.  The workaround which SELinux
-  users are using is to change their SELinux policy to grant key search
-  access to all domains.  This works, but it is an odd extra step that
-  shouldn't really have to be done.
-
-The fix for all these issues is to change the implementation to what I
-should have done originally: don't use the keyrings subsystem to keep
-track of the filesystem's fscrypt_master_key structs.  Instead, just
-store them in a regular kernel data structure, and rework the reference
-counting, locking, and lifetime accordingly.  Retain support for
-RCU-mode key lookups by using a hash table.  Replace fscrypt_sb_free()
-with fscrypt_sb_delete(), which releases the keys synchronously and runs
-a bit earlier during unmount, so that block devices are still available.
-
-A side effect of this patch is that neither the master keys themselves
-nor the filesystem keyrings will be listed in /proc/keys anymore.
-("Master key users" and the master key users keyrings will still be
-listed.)  However, this was mostly an implementation detail, and it was
-intended just for debugging purposes.  I don't know of anyone using it.
-
-This patch does *not* change how "master key users" (->mk_users) works;
-that still uses the keyrings subsystem.  That is still needed for key
-quotas, and changing that isn't necessary to solve the issues listed
-above.  If we decide to change that too, it would be a separate patch.
-
-I've marked this as fixing the original commit that added the fscrypt
-keyring, but as noted above the most important issue that this patch
-fixes wasn't introduced until the addition of inline encryption support.
-
-Fixes: 22d94f493bfb ("fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl")
-Signed-off-by: Eric Biggers <ebiggers@google.com>
-Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/crypto/fscrypt_private.h |  71 ++++--
- fs/crypto/hooks.c           |  10 +-
- fs/crypto/keyring.c         | 486 +++++++++++++++++++-----------------
- fs/crypto/keysetup.c        |  81 +++---
- fs/crypto/policy.c          |   8 +-
- fs/super.c                  |   2 +-
- include/linux/fs.h          |   2 +-
- include/linux/fscrypt.h     |   4 +-
- 8 files changed, 353 insertions(+), 311 deletions(-)
-
-diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
-index 6b4c8094cc7b..731a9a34ec21 100644
---- a/fs/crypto/fscrypt_private.h
-+++ b/fs/crypto/fscrypt_private.h
-@@ -225,7 +225,7 @@ struct fscrypt_info {
-        * will be NULL if the master key was found in a process-subscribed
-        * keyring rather than in the filesystem-level keyring.
-        */
--      struct key *ci_master_key;
-+      struct fscrypt_master_key *ci_master_key;
-       /*
-        * Link in list of inodes that were unlocked with the master key.
-@@ -439,6 +439,40 @@ struct fscrypt_master_key_secret {
-  */
- struct fscrypt_master_key {
-+      /*
-+       * Back-pointer to the super_block of the filesystem to which this
-+       * master key has been added.  Only valid if ->mk_active_refs > 0.
-+       */
-+      struct super_block                      *mk_sb;
-+
-+      /*
-+       * Link in ->mk_sb->s_master_keys->key_hashtable.
-+       * Only valid if ->mk_active_refs > 0.
-+       */
-+      struct hlist_node                       mk_node;
-+
-+      /* Semaphore that protects ->mk_secret and ->mk_users */
-+      struct rw_semaphore                     mk_sem;
-+
-+      /*
-+       * Active and structural reference counts.  An active ref guarantees
-+       * that the struct continues to exist, continues to be in the keyring
-+       * ->mk_sb->s_master_keys, and that any embedded subkeys (e.g.
-+       * ->mk_direct_keys) that have been prepared continue to exist.
-+       * A structural ref only guarantees that the struct continues to exist.
-+       *
-+       * There is one active ref associated with ->mk_secret being present,
-+       * and one active ref for each inode in ->mk_decrypted_inodes.
-+       *
-+       * There is one structural ref associated with the active refcount being
-+       * nonzero.  Finding a key in the keyring also takes a structural ref,
-+       * which is then held temporarily while the key is operated on.
-+       */
-+      refcount_t                              mk_active_refs;
-+      refcount_t                              mk_struct_refs;
-+
-+      struct rcu_head                         mk_rcu_head;
-+
-       /*
-        * The secret key material.  After FS_IOC_REMOVE_ENCRYPTION_KEY is
-        * executed, this is wiped and no new inodes can be unlocked with this
-@@ -447,7 +481,10 @@ struct fscrypt_master_key {
-        * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
-        * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
-        *
--       * Locking: protected by this master key's key->sem.
-+       * While ->mk_secret is present, one ref in ->mk_active_refs is held.
-+       *
-+       * Locking: protected by ->mk_sem.  The manipulation of ->mk_active_refs
-+       *          associated with this field is protected by ->mk_sem as well.
-        */
-       struct fscrypt_master_key_secret        mk_secret;
-@@ -468,22 +505,12 @@ struct fscrypt_master_key {
-        *
-        * This is NULL for v1 policy keys; those can only be added by root.
-        *
--       * Locking: in addition to this keyring's own semaphore, this is
--       * protected by this master key's key->sem, so we can do atomic
--       * search+insert.  It can also be searched without taking any locks, but
--       * in that case the returned key may have already been removed.
-+       * Locking: protected by ->mk_sem.  (We don't just rely on the keyrings
-+       * subsystem semaphore ->mk_users->sem, as we need support for atomic
-+       * search+insert along with proper synchronization with ->mk_secret.)
-        */
-       struct key              *mk_users;
--      /*
--       * Length of ->mk_decrypted_inodes, plus one if mk_secret is present.
--       * Once this goes to 0, the master key is removed from ->s_master_keys.
--       * The 'struct fscrypt_master_key' will continue to live as long as the
--       * 'struct key' whose payload it is, but we won't let this reference
--       * count rise again.
--       */
--      refcount_t              mk_refcount;
--
-       /*
-        * List of inodes that were unlocked using this key.  This allows the
-        * inodes to be evicted efficiently if the key is removed.
-@@ -509,10 +536,10 @@ static inline bool
- is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
- {
-       /*
--       * The READ_ONCE() is only necessary for fscrypt_drop_inode() and
--       * fscrypt_key_describe().  These run in atomic context, so they can't
--       * take the key semaphore and thus 'secret' can change concurrently
--       * which would be a data race.  But they only need to know whether the
-+       * The READ_ONCE() is only necessary for fscrypt_drop_inode().
-+       * fscrypt_drop_inode() runs in atomic context, so it can't take the key
-+       * semaphore and thus 'secret' can change concurrently which would be a
-+       * data race.  But fscrypt_drop_inode() only need to know whether the
-        * secret *was* present at the time of check, so READ_ONCE() suffices.
-        */
-       return READ_ONCE(secret->size) != 0;
-@@ -541,7 +568,11 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
-       return 0;
- }
--struct key *
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk);
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk);
-+
-+struct fscrypt_master_key *
- fscrypt_find_master_key(struct super_block *sb,
-                       const struct fscrypt_key_specifier *mk_spec);
-diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
-index af74599ae1cf..be5c650e4957 100644
---- a/fs/crypto/hooks.c
-+++ b/fs/crypto/hooks.c
-@@ -5,8 +5,6 @@
-  * Encryption hooks for higher-level filesystem operations.
-  */
--#include <linux/key.h>
--
- #include "fscrypt_private.h"
- /**
-@@ -142,7 +140,6 @@ int fscrypt_prepare_setflags(struct inode *inode,
-                            unsigned int oldflags, unsigned int flags)
- {
-       struct fscrypt_info *ci;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -158,14 +155,13 @@ int fscrypt_prepare_setflags(struct inode *inode,
-               ci = inode->i_crypt_info;
-               if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
-                       return -EINVAL;
--              key = ci->ci_master_key;
--              mk = key->payload.data[0];
--              down_read(&key->sem);
-+              mk = ci->ci_master_key;
-+              down_read(&mk->mk_sem);
-               if (is_master_key_secret_present(&mk->mk_secret))
-                       err = fscrypt_derive_dirhash_key(ci, mk);
-               else
-                       err = -ENOKEY;
--              up_read(&key->sem);
-+              up_read(&mk->mk_sem);
-               return err;
-       }
-       return 0;
-diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
-index caee9f8620dd..9b98d6a576e6 100644
---- a/fs/crypto/keyring.c
-+++ b/fs/crypto/keyring.c
-@@ -18,6 +18,7 @@
-  * information about these ioctls.
-  */
-+#include <asm/unaligned.h>
- #include <crypto/skcipher.h>
- #include <linux/key-type.h>
- #include <linux/random.h>
-@@ -25,6 +26,18 @@
- #include "fscrypt_private.h"
-+/* The master encryption keys for a filesystem (->s_master_keys) */
-+struct fscrypt_keyring {
-+      /*
-+       * Lock that protects ->key_hashtable.  It does *not* protect the
-+       * fscrypt_master_key structs themselves.
-+       */
-+      spinlock_t lock;
-+
-+      /* Hash table that maps fscrypt_key_specifier to fscrypt_master_key */
-+      struct hlist_head key_hashtable[128];
-+};
-+
- static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret)
- {
-       fscrypt_destroy_hkdf(&secret->hkdf);
-@@ -38,20 +51,70 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst,
-       memzero_explicit(src, sizeof(*src));
- }
--static void free_master_key(struct fscrypt_master_key *mk)
-+static void fscrypt_free_master_key(struct rcu_head *head)
-+{
-+      struct fscrypt_master_key *mk =
-+              container_of(head, struct fscrypt_master_key, mk_rcu_head);
-+      /*
-+       * The master key secret and any embedded subkeys should have already
-+       * been wiped when the last active reference to the fscrypt_master_key
-+       * struct was dropped; doing it here would be unnecessarily late.
-+       * Nevertheless, use kfree_sensitive() in case anything was missed.
-+       */
-+      kfree_sensitive(mk);
-+}
-+
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk)
-+{
-+      if (!refcount_dec_and_test(&mk->mk_struct_refs))
-+              return;
-+      /*
-+       * No structural references left, so free ->mk_users, and also free the
-+       * fscrypt_master_key struct itself after an RCU grace period ensures
-+       * that concurrent keyring lookups can no longer find it.
-+       */
-+      WARN_ON(refcount_read(&mk->mk_active_refs) != 0);
-+      key_put(mk->mk_users);
-+      mk->mk_users = NULL;
-+      call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
-+}
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk)
- {
-+      struct super_block *sb = mk->mk_sb;
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       size_t i;
--      wipe_master_key_secret(&mk->mk_secret);
-+      if (!refcount_dec_and_test(&mk->mk_active_refs))
-+              return;
-+      /*
-+       * No active references left, so complete the full removal of this
-+       * fscrypt_master_key struct by removing it from the keyring and
-+       * destroying any subkeys embedded in it.
-+       */
-+
-+      spin_lock(&keyring->lock);
-+      hlist_del_rcu(&mk->mk_node);
-+      spin_unlock(&keyring->lock);
-+
-+      /*
-+       * ->mk_active_refs == 0 implies that ->mk_secret is not present and
-+       * that ->mk_decrypted_inodes is empty.
-+       */
-+      WARN_ON(is_master_key_secret_present(&mk->mk_secret));
-+      WARN_ON(!list_empty(&mk->mk_decrypted_inodes));
-       for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
-               fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]);
-       }
-+      memzero_explicit(&mk->mk_ino_hash_key,
-+                       sizeof(mk->mk_ino_hash_key));
-+      mk->mk_ino_hash_key_initialized = false;
--      key_put(mk->mk_users);
--      kfree_sensitive(mk);
-+      /* Drop the structural ref associated with the active refs. */
-+      fscrypt_put_master_key(mk);
- }
- static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-@@ -61,44 +124,6 @@ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-       return master_key_spec_len(spec) != 0;
- }
--static int fscrypt_key_instantiate(struct key *key,
--                                 struct key_preparsed_payload *prep)
--{
--      key->payload.data[0] = (struct fscrypt_master_key *)prep->data;
--      return 0;
--}
--
--static void fscrypt_key_destroy(struct key *key)
--{
--      free_master_key(key->payload.data[0]);
--}
--
--static void fscrypt_key_describe(const struct key *key, struct seq_file *m)
--{
--      seq_puts(m, key->description);
--
--      if (key_is_positive(key)) {
--              const struct fscrypt_master_key *mk = key->payload.data[0];
--
--              if (!is_master_key_secret_present(&mk->mk_secret))
--                      seq_puts(m, ": secret removed");
--      }
--}
--
--/*
-- * Type of key in ->s_master_keys.  Each key of this type represents a master
-- * key which has been added to the filesystem.  Its payload is a
-- * 'struct fscrypt_master_key'.  The "." prefix in the key type name prevents
-- * users from adding keys of this type via the keyrings syscalls rather than via
-- * the intended method of FS_IOC_ADD_ENCRYPTION_KEY.
-- */
--static struct key_type key_type_fscrypt = {
--      .name                   = "._fscrypt",
--      .instantiate            = fscrypt_key_instantiate,
--      .destroy                = fscrypt_key_destroy,
--      .describe               = fscrypt_key_describe,
--};
--
- static int fscrypt_user_key_instantiate(struct key *key,
-                                       struct key_preparsed_payload *prep)
- {
-@@ -131,32 +156,6 @@ static struct key_type key_type_fscrypt_user = {
-       .describe               = fscrypt_user_key_describe,
- };
--/* Search ->s_master_keys or ->mk_users */
--static struct key *search_fscrypt_keyring(struct key *keyring,
--                                        struct key_type *type,
--                                        const char *description)
--{
--      /*
--       * We need to mark the keyring reference as "possessed" so that we
--       * acquire permission to search it, via the KEY_POS_SEARCH permission.
--       */
--      key_ref_t keyref = make_key_ref(keyring, true /* possessed */);
--
--      keyref = keyring_search(keyref, type, description, false);
--      if (IS_ERR(keyref)) {
--              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
--                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
--                      keyref = ERR_PTR(-ENOKEY);
--              return ERR_CAST(keyref);
--      }
--      return key_ref_to_ptr(keyref);
--}
--
--#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE   \
--      (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id))
--
--#define FSCRYPT_MK_DESCRIPTION_SIZE   (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1)
--
- #define FSCRYPT_MK_USERS_DESCRIPTION_SIZE     \
-       (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
-        CONST_STRLEN("-users") + 1)
-@@ -164,21 +163,6 @@ static struct key *search_fscrypt_keyring(struct key *keyring,
- #define FSCRYPT_MK_USER_DESCRIPTION_SIZE      \
-       (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
--static void format_fs_keyring_description(
--                      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE],
--                      const struct super_block *sb)
--{
--      sprintf(description, "fscrypt-%s", sb->s_id);
--}
--
--static void format_mk_description(
--                      char description[FSCRYPT_MK_DESCRIPTION_SIZE],
--                      const struct fscrypt_key_specifier *mk_spec)
--{
--      sprintf(description, "%*phN",
--              master_key_spec_len(mk_spec), (u8 *)&mk_spec->u);
--}
--
- static void format_mk_users_keyring_description(
-                       char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
-                       const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
-@@ -199,20 +183,15 @@ static void format_mk_user_description(
- /* Create ->s_master_keys if needed.  Synchronized by fscrypt_add_key_mutex. */
- static int allocate_filesystem_keyring(struct super_block *sb)
- {
--      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE];
--      struct key *keyring;
-+      struct fscrypt_keyring *keyring;
-       if (sb->s_master_keys)
-               return 0;
--      format_fs_keyring_description(description, sb);
--      keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
--                              current_cred(), KEY_POS_SEARCH |
--                                KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW,
--                              KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
--      if (IS_ERR(keyring))
--              return PTR_ERR(keyring);
--
-+      keyring = kzalloc(sizeof(*keyring), GFP_KERNEL);
-+      if (!keyring)
-+              return -ENOMEM;
-+      spin_lock_init(&keyring->lock);
-       /*
-        * Pairs with the smp_load_acquire() in fscrypt_find_master_key().
-        * I.e., here we publish ->s_master_keys with a RELEASE barrier so that
-@@ -222,21 +201,75 @@ static int allocate_filesystem_keyring(struct super_block *sb)
-       return 0;
- }
--void fscrypt_sb_free(struct super_block *sb)
-+/*
-+ * This is called at unmount time to release all encryption keys that have been
-+ * added to the filesystem, along with the keyring that contains them.
-+ *
-+ * Note that besides clearing and freeing memory, this might need to evict keys
-+ * from the keyslots of an inline crypto engine.  Therefore, this must be called
-+ * while the filesystem's underlying block device(s) are still available.
-+ */
-+void fscrypt_sb_delete(struct super_block *sb)
- {
--      key_put(sb->s_master_keys);
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-+      size_t i;
-+
-+      if (!keyring)
-+              return;
-+
-+      for (i = 0; i < ARRAY_SIZE(keyring->key_hashtable); i++) {
-+              struct hlist_head *bucket = &keyring->key_hashtable[i];
-+              struct fscrypt_master_key *mk;
-+              struct hlist_node *tmp;
-+
-+              hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
-+                      /*
-+                       * Since all inodes were already evicted, every key
-+                       * remaining in the keyring should have an empty inode
-+                       * list, and should only still be in the keyring due to
-+                       * the single active ref associated with ->mk_secret.
-+                       * There should be no structural refs beyond the one
-+                       * associated with the active ref.
-+                       */
-+                      WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
-+                      WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
-+                      WARN_ON(!is_master_key_secret_present(&mk->mk_secret));
-+                      wipe_master_key_secret(&mk->mk_secret);
-+                      fscrypt_put_master_key_activeref(mk);
-+              }
-+      }
-+      kfree_sensitive(keyring);
-       sb->s_master_keys = NULL;
- }
-+static struct hlist_head *
-+fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring,
-+                     const struct fscrypt_key_specifier *mk_spec)
-+{
-+      /*
-+       * Since key specifiers should be "random" values, it is sufficient to
-+       * use a trivial hash function that just takes the first several bits of
-+       * the key specifier.
-+       */
-+      unsigned long i = get_unaligned((unsigned long *)&mk_spec->u);
-+
-+      return &keyring->key_hashtable[i % ARRAY_SIZE(keyring->key_hashtable)];
-+}
-+
- /*
-- * Find the specified master key in ->s_master_keys.
-- * Returns ERR_PTR(-ENOKEY) if not found.
-+ * Find the specified master key struct in ->s_master_keys and take a structural
-+ * ref to it.  The structural ref guarantees that the key struct continues to
-+ * exist, but it does *not* guarantee that ->s_master_keys continues to contain
-+ * the key struct.  The structural ref needs to be dropped by
-+ * fscrypt_put_master_key().  Returns NULL if the key struct is not found.
-  */
--struct key *fscrypt_find_master_key(struct super_block *sb,
--                                  const struct fscrypt_key_specifier *mk_spec)
-+struct fscrypt_master_key *
-+fscrypt_find_master_key(struct super_block *sb,
-+                      const struct fscrypt_key_specifier *mk_spec)
- {
--      struct key *keyring;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
-+      struct fscrypt_keyring *keyring;
-+      struct hlist_head *bucket;
-+      struct fscrypt_master_key *mk;
-       /*
-        * Pairs with the smp_store_release() in allocate_filesystem_keyring().
-@@ -246,10 +279,38 @@ struct key *fscrypt_find_master_key(struct super_block *sb,
-        */
-       keyring = smp_load_acquire(&sb->s_master_keys);
-       if (keyring == NULL)
--              return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */
--
--      format_mk_description(description, mk_spec);
--      return search_fscrypt_keyring(keyring, &key_type_fscrypt, description);
-+              return NULL; /* No keyring yet, so no keys yet. */
-+
-+      bucket = fscrypt_mk_hash_bucket(keyring, mk_spec);
-+      rcu_read_lock();
-+      switch (mk_spec->type) {
-+      case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
-+                          memcmp(mk->mk_spec.u.descriptor,
-+                                 mk_spec->u.descriptor,
-+                                 FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&
-+                          memcmp(mk->mk_spec.u.identifier,
-+                                 mk_spec->u.identifier,
-+                                 FSCRYPT_KEY_IDENTIFIER_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      }
-+      mk = NULL;
-+out:
-+      rcu_read_unlock();
-+      return mk;
- }
- static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
-@@ -277,17 +338,30 @@ static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
- static struct key *find_master_key_user(struct fscrypt_master_key *mk)
- {
-       char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
-+      key_ref_t keyref;
-       format_mk_user_description(description, mk->mk_spec.u.identifier);
--      return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_user,
--                                    description);
-+
-+      /*
-+       * We need to mark the keyring reference as "possessed" so that we
-+       * acquire permission to search it, via the KEY_POS_SEARCH permission.
-+       */
-+      keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/),
-+                              &key_type_fscrypt_user, description, false);
-+      if (IS_ERR(keyref)) {
-+              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
-+                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
-+                      keyref = ERR_PTR(-ENOKEY);
-+              return ERR_CAST(keyref);
-+      }
-+      return key_ref_to_ptr(keyref);
- }
- /*
-  * Give the current user a "key" in ->mk_users.  This charges the user's quota
-  * and marks the master key as added by the current user, so that it cannot be
-- * removed by another user with the key.  Either the master key's key->sem must
-- * be held for write, or the master key must be still undergoing initialization.
-+ * removed by another user with the key.  Either ->mk_sem must be held for
-+ * write, or the master key must be still undergoing initialization.
-  */
- static int add_master_key_user(struct fscrypt_master_key *mk)
- {
-@@ -309,7 +383,7 @@ static int add_master_key_user(struct fscrypt_master_key *mk)
- /*
-  * Remove the current user's "key" from ->mk_users.
-- * The master key's key->sem must be held for write.
-+ * ->mk_sem must be held for write.
-  *
-  * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
-  */
-@@ -327,63 +401,49 @@ static int remove_master_key_user(struct fscrypt_master_key *mk)
- }
- /*
-- * Allocate a new fscrypt_master_key which contains the given secret, set it as
-- * the payload of a new 'struct key' of type fscrypt, and link the 'struct key'
-- * into the given keyring.  Synchronized by fscrypt_add_key_mutex.
-+ * Allocate a new fscrypt_master_key, transfer the given secret over to it, and
-+ * insert it into sb->s_master_keys.
-  */
--static int add_new_master_key(struct fscrypt_master_key_secret *secret,
--                            const struct fscrypt_key_specifier *mk_spec,
--                            struct key *keyring)
-+static int add_new_master_key(struct super_block *sb,
-+                            struct fscrypt_master_key_secret *secret,
-+                            const struct fscrypt_key_specifier *mk_spec)
- {
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       struct fscrypt_master_key *mk;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
--      struct key *key;
-       int err;
-       mk = kzalloc(sizeof(*mk), GFP_KERNEL);
-       if (!mk)
-               return -ENOMEM;
-+      mk->mk_sb = sb;
-+      init_rwsem(&mk->mk_sem);
-+      refcount_set(&mk->mk_struct_refs, 1);
-       mk->mk_spec = *mk_spec;
--      move_master_key_secret(&mk->mk_secret, secret);
--
--      refcount_set(&mk->mk_refcount, 1); /* secret is present */
-       INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
-       spin_lock_init(&mk->mk_decrypted_inodes_lock);
-       if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
-               err = allocate_master_key_users_keyring(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-               err = add_master_key_user(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-       }
--      /*
--       * Note that we don't charge this key to anyone's quota, since when
--       * ->mk_users is in use those keys are charged instead, and otherwise
--       * (when ->mk_users isn't in use) only root can add these keys.
--       */
--      format_mk_description(description, mk_spec);
--      key = key_alloc(&key_type_fscrypt, description,
--                      GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
--                      KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_USR_VIEW,
--                      KEY_ALLOC_NOT_IN_QUOTA, NULL);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              goto out_free_mk;
--      }
--      err = key_instantiate_and_link(key, mk, sizeof(*mk), keyring, NULL);
--      key_put(key);
--      if (err)
--              goto out_free_mk;
-+      move_master_key_secret(&mk->mk_secret, secret);
-+      refcount_set(&mk->mk_active_refs, 1); /* ->mk_secret is present */
-+      spin_lock(&keyring->lock);
-+      hlist_add_head_rcu(&mk->mk_node,
-+                         fscrypt_mk_hash_bucket(keyring, mk_spec));
-+      spin_unlock(&keyring->lock);
-       return 0;
--out_free_mk:
--      free_master_key(mk);
-+out_put:
-+      fscrypt_put_master_key(mk);
-       return err;
- }
-@@ -392,42 +452,34 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret,
- static int add_existing_master_key(struct fscrypt_master_key *mk,
-                                  struct fscrypt_master_key_secret *secret)
- {
--      struct key *mk_user;
--      bool rekey;
-       int err;
-       /*
-        * If the current user is already in ->mk_users, then there's nothing to
--       * do.  (Not applicable for v1 policy keys, which have NULL ->mk_users.)
-+       * do.  Otherwise, we need to add the user to ->mk_users.  (Neither is
-+       * applicable for v1 policy keys, which have NULL ->mk_users.)
-        */
-       if (mk->mk_users) {
--              mk_user = find_master_key_user(mk);
-+              struct key *mk_user = find_master_key_user(mk);
-+
-               if (mk_user != ERR_PTR(-ENOKEY)) {
-                       if (IS_ERR(mk_user))
-                               return PTR_ERR(mk_user);
-                       key_put(mk_user);
-                       return 0;
-               }
--      }
--
--      /* If we'll be re-adding ->mk_secret, try to take the reference. */
--      rekey = !is_master_key_secret_present(&mk->mk_secret);
--      if (rekey && !refcount_inc_not_zero(&mk->mk_refcount))
--              return KEY_DEAD;
--
--      /* Add the current user to ->mk_users, if applicable. */
--      if (mk->mk_users) {
-               err = add_master_key_user(mk);
--              if (err) {
--                      if (rekey && refcount_dec_and_test(&mk->mk_refcount))
--                              return KEY_DEAD;
-+              if (err)
-                       return err;
--              }
-       }
-       /* Re-add the secret if needed. */
--      if (rekey)
-+      if (!is_master_key_secret_present(&mk->mk_secret)) {
-+              if (!refcount_inc_not_zero(&mk->mk_active_refs))
-+                      return KEY_DEAD;
-               move_master_key_secret(&mk->mk_secret, secret);
-+      }
-+
-       return 0;
- }
-@@ -436,38 +488,36 @@ static int do_add_master_key(struct super_block *sb,
-                            const struct fscrypt_key_specifier *mk_spec)
- {
-       static DEFINE_MUTEX(fscrypt_add_key_mutex);
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       int err;
-       mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */
--retry:
--      key = fscrypt_find_master_key(sb, mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              if (err != -ENOKEY)
--                      goto out_unlock;
-+
-+      mk = fscrypt_find_master_key(sb, mk_spec);
-+      if (!mk) {
-               /* Didn't find the key in ->s_master_keys.  Add it. */
-               err = allocate_filesystem_keyring(sb);
--              if (err)
--                      goto out_unlock;
--              err = add_new_master_key(secret, mk_spec, sb->s_master_keys);
-+              if (!err)
-+                      err = add_new_master_key(sb, secret, mk_spec);
-       } else {
-               /*
-                * Found the key in ->s_master_keys.  Re-add the secret if
-                * needed, and add the user to ->mk_users if needed.
-                */
--              down_write(&key->sem);
--              err = add_existing_master_key(key->payload.data[0], secret);
--              up_write(&key->sem);
-+              down_write(&mk->mk_sem);
-+              err = add_existing_master_key(mk, secret);
-+              up_write(&mk->mk_sem);
-               if (err == KEY_DEAD) {
--                      /* Key being removed or needs to be removed */
--                      key_invalidate(key);
--                      key_put(key);
--                      goto retry;
-+                      /*
-+                       * We found a key struct, but it's already been fully
-+                       * removed.  Ignore the old struct and add a new one.
-+                       * fscrypt_add_key_mutex means we don't need to worry
-+                       * about concurrent adds.
-+                       */
-+                      err = add_new_master_key(sb, secret, mk_spec);
-               }
--              key_put(key);
-+              fscrypt_put_master_key(mk);
-       }
--out_unlock:
-       mutex_unlock(&fscrypt_add_key_mutex);
-       return err;
- }
-@@ -771,19 +821,19 @@ int fscrypt_verify_key_added(struct super_block *sb,
-                            const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
- {
-       struct fscrypt_key_specifier mk_spec;
--      struct key *key, *mk_user;
-       struct fscrypt_master_key *mk;
-+      struct key *mk_user;
-       int err;
-       mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
-       memcpy(mk_spec.u.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE);
--      key = fscrypt_find_master_key(sb, &mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &mk_spec);
-+      if (!mk) {
-+              err = -ENOKEY;
-               goto out;
-       }
--      mk = key->payload.data[0];
-+      down_read(&mk->mk_sem);
-       mk_user = find_master_key_user(mk);
-       if (IS_ERR(mk_user)) {
-               err = PTR_ERR(mk_user);
-@@ -791,7 +841,8 @@ int fscrypt_verify_key_added(struct super_block *sb,
-               key_put(mk_user);
-               err = 0;
-       }
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (err == -ENOKEY && capable(CAP_FOWNER))
-               err = 0;
-@@ -953,11 +1004,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_remove_key_arg __user *uarg = _uarg;
-       struct fscrypt_remove_key_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       u32 status_flags = 0;
-       int err;
--      bool dead;
-+      bool inodes_remain;
-       if (copy_from_user(&arg, uarg, sizeof(arg)))
-               return -EFAULT;
-@@ -977,12 +1027,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               return -EACCES;
-       /* Find the key being removed. */
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key))
--              return PTR_ERR(key);
--      mk = key->payload.data[0];
--
--      down_write(&key->sem);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk)
-+              return -ENOKEY;
-+      down_write(&mk->mk_sem);
-       /* If relevant, remove current user's (or all users) claim to the key */
-       if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -991,7 +1039,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               else
-                       err = remove_master_key_user(mk);
-               if (err) {
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-               if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -1003,26 +1051,22 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-                       status_flags |=
-                               FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS;
-                       err = 0;
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-       }
-       /* No user claims remaining.  Go ahead and wipe the secret. */
--      dead = false;
-+      err = -ENOKEY;
-       if (is_master_key_secret_present(&mk->mk_secret)) {
-               wipe_master_key_secret(&mk->mk_secret);
--              dead = refcount_dec_and_test(&mk->mk_refcount);
--      }
--      up_write(&key->sem);
--      if (dead) {
--              /*
--               * No inodes reference the key, and we wiped the secret, so the
--               * key object is free to be removed from the keyring.
--               */
--              key_invalidate(key);
-+              fscrypt_put_master_key_activeref(mk);
-               err = 0;
--      } else {
-+      }
-+      inodes_remain = refcount_read(&mk->mk_active_refs) > 0;
-+      up_write(&mk->mk_sem);
-+
-+      if (inodes_remain) {
-               /* Some inodes still reference this key; try to evict them. */
-               err = try_to_lock_encrypted_files(sb, mk);
-               if (err == -EBUSY) {
-@@ -1038,7 +1082,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-        * has been fully removed including all files locked.
-        */
- out_put_key:
--      key_put(key);
-+      fscrypt_put_master_key(mk);
-       if (err == 0)
-               err = put_user(status_flags, &uarg->removal_status_flags);
-       return err;
-@@ -1085,7 +1129,6 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
- {
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_get_key_status_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -1102,19 +1145,18 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       arg.user_count = 0;
-       memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved));
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY))
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk) {
-               arg.status = FSCRYPT_KEY_STATUS_ABSENT;
-               err = 0;
-               goto out;
-       }
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
--              arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED;
-+              arg.status = refcount_read(&mk->mk_active_refs) > 0 ?
-+                      FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED :
-+                      FSCRYPT_KEY_STATUS_ABSENT /* raced with full removal */;
-               err = 0;
-               goto out_release_key;
-       }
-@@ -1136,8 +1178,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       }
-       err = 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (!err && copy_to_user(uarg, &arg, sizeof(arg)))
-               err = -EFAULT;
-@@ -1149,13 +1191,9 @@ int __init fscrypt_init_keyring(void)
- {
-       int err;
--      err = register_key_type(&key_type_fscrypt);
--      if (err)
--              return err;
--
-       err = register_key_type(&key_type_fscrypt_user);
-       if (err)
--              goto err_unregister_fscrypt;
-+              return err;
-       err = register_key_type(&key_type_fscrypt_provisioning);
-       if (err)
-@@ -1165,7 +1203,5 @@ int __init fscrypt_init_keyring(void)
- err_unregister_fscrypt_user:
-       unregister_key_type(&key_type_fscrypt_user);
--err_unregister_fscrypt:
--      unregister_key_type(&key_type_fscrypt);
-       return err;
- }
-diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
-index c35711896bd4..f8f8f41c1de9 100644
---- a/fs/crypto/keysetup.c
-+++ b/fs/crypto/keysetup.c
-@@ -9,7 +9,6 @@
-  */
- #include <crypto/skcipher.h>
--#include <linux/key.h>
- #include <linux/random.h>
- #include "fscrypt_private.h"
-@@ -152,6 +151,7 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key)
- {
-       crypto_free_skcipher(prep_key->tfm);
-       fscrypt_destroy_inline_crypt_key(prep_key);
-+      memzero_explicit(prep_key, sizeof(*prep_key));
- }
- /* Given a per-file encryption key, set up the file's crypto transform object */
-@@ -405,20 +405,18 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
- /*
-  * Find the master key, then set up the inode's actual encryption key.
-  *
-- * If the master key is found in the filesystem-level keyring, then the
-- * corresponding 'struct key' is returned in *master_key_ret with its semaphore
-- * read-locked.  This is needed to ensure that only one task links the
-- * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create
-- * an fscrypt_info for the same inode), and to synchronize the master key being
-- * removed with a new inode starting to use it.
-+ * If the master key is found in the filesystem-level keyring, then it is
-+ * returned in *mk_ret with its semaphore read-locked.  This is needed to ensure
-+ * that only one task links the fscrypt_info into ->mk_decrypted_inodes (as
-+ * multiple tasks may race to create an fscrypt_info for the same inode), and to
-+ * synchronize the master key being removed with a new inode starting to use it.
-  */
- static int setup_file_encryption_key(struct fscrypt_info *ci,
-                                    bool need_dirhash_key,
--                                   struct key **master_key_ret)
-+                                   struct fscrypt_master_key **mk_ret)
- {
--      struct key *key;
--      struct fscrypt_master_key *mk = NULL;
-       struct fscrypt_key_specifier mk_spec;
-+      struct fscrypt_master_key *mk;
-       int err;
-       err = fscrypt_select_encryption_impl(ci);
-@@ -429,11 +427,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       if (err)
-               return err;
--      key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY) ||
--                  ci->ci_policy.version != FSCRYPT_POLICY_V1)
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
-+      if (!mk) {
-+              if (ci->ci_policy.version != FSCRYPT_POLICY_V1)
-+                      return -ENOKEY;
-               /*
-                * As a legacy fallback for v1 policies, search for the key in
-@@ -443,9 +440,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-                */
-               return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci);
-       }
--
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
-@@ -473,18 +468,18 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       if (err)
-               goto out_release_key;
--      *master_key_ret = key;
-+      *mk_ret = mk;
-       return 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
-       return err;
- }
- static void put_crypt_info(struct fscrypt_info *ci)
- {
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       if (!ci)
-               return;
-@@ -494,24 +489,18 @@ static void put_crypt_info(struct fscrypt_info *ci)
-       else if (ci->ci_owns_key)
-               fscrypt_destroy_prepared_key(&ci->ci_enc_key);
--      key = ci->ci_master_key;
--      if (key) {
--              struct fscrypt_master_key *mk = key->payload.data[0];
--
-+      mk = ci->ci_master_key;
-+      if (mk) {
-               /*
-                * Remove this inode from the list of inodes that were unlocked
--               * with the master key.
--               *
--               * In addition, if we're removing the last inode from a key that
--               * already had its secret removed, invalidate the key so that it
--               * gets removed from ->s_master_keys.
-+               * with the master key.  In addition, if we're removing the last
-+               * inode from a master key struct that already had its secret
-+               * removed, then complete the full removal of the struct.
-                */
-               spin_lock(&mk->mk_decrypted_inodes_lock);
-               list_del(&ci->ci_master_key_link);
-               spin_unlock(&mk->mk_decrypted_inodes_lock);
--              if (refcount_dec_and_test(&mk->mk_refcount))
--                      key_invalidate(key);
--              key_put(key);
-+              fscrypt_put_master_key_activeref(mk);
-       }
-       memzero_explicit(ci, sizeof(*ci));
-       kmem_cache_free(fscrypt_info_cachep, ci);
-@@ -525,7 +514,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
- {
-       struct fscrypt_info *crypt_info;
-       struct fscrypt_mode *mode;
--      struct key *master_key = NULL;
-+      struct fscrypt_master_key *mk = NULL;
-       int res;
-       res = fscrypt_initialize(inode->i_sb->s_cop->flags);
-@@ -548,8 +537,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
-       crypt_info->ci_mode = mode;
--      res = setup_file_encryption_key(crypt_info, need_dirhash_key,
--                                      &master_key);
-+      res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
-       if (res)
-               goto out;
-@@ -564,12 +552,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-                * We won the race and set ->i_crypt_info to our crypt_info.
-                * Now link it into the master key's inode list.
-                */
--              if (master_key) {
--                      struct fscrypt_master_key *mk =
--                              master_key->payload.data[0];
--
--                      refcount_inc(&mk->mk_refcount);
--                      crypt_info->ci_master_key = key_get(master_key);
-+              if (mk) {
-+                      crypt_info->ci_master_key = mk;
-+                      refcount_inc(&mk->mk_active_refs);
-                       spin_lock(&mk->mk_decrypted_inodes_lock);
-                       list_add(&crypt_info->ci_master_key_link,
-                                &mk->mk_decrypted_inodes);
-@@ -579,9 +564,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       }
-       res = 0;
- out:
--      if (master_key) {
--              up_read(&master_key->sem);
--              key_put(master_key);
-+      if (mk) {
-+              up_read(&mk->mk_sem);
-+              fscrypt_put_master_key(mk);
-       }
-       put_crypt_info(crypt_info);
-       return res;
-@@ -746,7 +731,6 @@ EXPORT_SYMBOL(fscrypt_free_inode);
- int fscrypt_drop_inode(struct inode *inode)
- {
-       const struct fscrypt_info *ci = fscrypt_get_info(inode);
--      const struct fscrypt_master_key *mk;
-       /*
-        * If ci is NULL, then the inode doesn't have an encryption key set up
-@@ -756,7 +740,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        */
-       if (!ci || !ci->ci_master_key)
-               return 0;
--      mk = ci->ci_master_key->payload.data[0];
-       /*
-        * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes
-@@ -775,6 +758,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        * then the thread removing the key will either evict the inode itself
-        * or will correctly detect that it wasn't evicted due to the race.
-        */
--      return !is_master_key_secret_present(&mk->mk_secret);
-+      return !is_master_key_secret_present(&ci->ci_master_key->mk_secret);
- }
- EXPORT_SYMBOL_GPL(fscrypt_drop_inode);
-diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
-index 5f858cee1e3b..ad21498f77bb 100644
---- a/fs/crypto/policy.c
-+++ b/fs/crypto/policy.c
-@@ -713,12 +713,8 @@ int fscrypt_set_context(struct inode *inode, void *fs_data)
-        * delayed key setup that requires the inode number.
-        */
-       if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
--          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
--              const struct fscrypt_master_key *mk =
--                      ci->ci_master_key->payload.data[0];
--
--              fscrypt_hash_inode_number(ci, mk);
--      }
-+          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
-+              fscrypt_hash_inode_number(ci, ci->ci_master_key);
-       return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, fs_data);
- }
-diff --git a/fs/super.c b/fs/super.c
-index 60f57c7bc0a6..9ac1e71f5150 100644
---- a/fs/super.c
-+++ b/fs/super.c
-@@ -291,7 +291,6 @@ static void __put_super(struct super_block *s)
-               WARN_ON(s->s_inode_lru.node);
-               WARN_ON(!list_empty(&s->s_mounts));
-               security_sb_free(s);
--              fscrypt_sb_free(s);
-               put_user_ns(s->s_user_ns);
-               kfree(s->s_subtype);
-               call_rcu(&s->rcu, destroy_super_rcu);
-@@ -451,6 +450,7 @@ void generic_shutdown_super(struct super_block *sb)
-               evict_inodes(sb);
-               /* only nonzero refcount inodes can have marks */
-               fsnotify_sb_delete(sb);
-+              fscrypt_sb_delete(sb);
-               security_sb_delete(sb);
-               if (sb->s_dio_done_wq) {
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index fb19f532c76c..21ed10a2e1cd 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -1455,7 +1455,7 @@ struct super_block {
-       const struct xattr_handler **s_xattr;
- #ifdef CONFIG_FS_ENCRYPTION
-       const struct fscrypt_operations *s_cop;
--      struct key              *s_master_keys; /* master crypto keys in use */
-+      struct fscrypt_keyring  *s_master_keys; /* master crypto keys in use */
- #endif
- #ifdef CONFIG_FS_VERITY
-       const struct fsverity_operations *s_vop;
-diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
-index e60d57c99cb6..4737075c7426 100644
---- a/include/linux/fscrypt.h
-+++ b/include/linux/fscrypt.h
-@@ -311,7 +311,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--void fscrypt_sb_free(struct super_block *sb);
-+void fscrypt_sb_delete(struct super_block *sb);
- int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
- int fscrypt_add_test_dummy_key(struct super_block *sb,
-                              const struct fscrypt_dummy_policy *dummy_policy);
-@@ -521,7 +521,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--static inline void fscrypt_sb_free(struct super_block *sb)
-+static inline void fscrypt_sb_delete(struct super_block *sb)
- {
- }
--- 
-2.35.1
-
index 4cfff2ebe58cdae617eb966b5cc3545fb1830ca4..9c6604362bdbbe054ad1a3f712cfc1c25f1b2199 100644 (file)
@@ -185,7 +185,6 @@ mips-sgi-ip30-fix-platform-device-leak-in-bridge_pla.patch
 mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch
 erofs-fix-order-max_order-warning-due-to-crafted-neg.patch
 erofs-use-kill_anon_super-to-kill-super-in-fscache-m.patch
-fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
 arm-9243-1-riscpc-unbreak-the-build.patch
 arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch
 arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch
diff --git a/queue-6.0/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch b/queue-6.0/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
deleted file mode 100644 (file)
index 55f462e..0000000
+++ /dev/null
@@ -1,1304 +0,0 @@
-From b85bdbcda08d53cc7429a2592980f006f3d7c4ea Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 1 Sep 2022 12:32:06 -0700
-Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key
-
-From: Eric Biggers <ebiggers@google.com>
-
-[ Upstream commit d7e7b9af104c7b389a0c21eb26532511bce4b510 ]
-
-The approach of fs/crypto/ internally managing the fscrypt_master_key
-structs as the payloads of "struct key" objects contained in a
-"struct key" keyring has outlived its usefulness.  The original idea was
-to simplify the code by reusing code from the keyrings subsystem.
-However, several issues have arisen that can't easily be resolved:
-
-- When a master key struct is destroyed, blk_crypto_evict_key() must be
-  called on any per-mode keys embedded in it.  (This started being the
-  case when inline encryption support was added.)  Yet, the keyrings
-  subsystem can arbitrarily delay the destruction of keys, even past the
-  time the filesystem was unmounted.  Therefore, currently there is no
-  easy way to call blk_crypto_evict_key() when a master key is
-  destroyed.  Currently, this is worked around by holding an extra
-  reference to the filesystem's request_queue(s).  But it was overlooked
-  that the request_queue reference is *not* guaranteed to pin the
-  corresponding blk_crypto_profile too; for device-mapper devices that
-  support inline crypto, it doesn't.  This can cause a use-after-free.
-
-- When the last inode that was using an incompletely-removed master key
-  is evicted, the master key removal is completed by removing the key
-  struct from the keyring.  Currently this is done via key_invalidate().
-  Yet, key_invalidate() takes the key semaphore.  This can deadlock when
-  called from the shrinker, since in fscrypt_ioctl_add_key(), memory is
-  allocated with GFP_KERNEL under the same semaphore.
-
-- More generally, the fact that the keyrings subsystem can arbitrarily
-  delay the destruction of keys (via garbage collection delay, or via
-  random processes getting temporary key references) is undesirable, as
-  it means we can't strictly guarantee that all secrets are ever wiped.
-
-- Doing the master key lookups via the keyrings subsystem results in the
-  key_permission LSM hook being called.  fscrypt doesn't want this, as
-  all access control for encrypted files is designed to happen via the
-  files themselves, like any other files.  The workaround which SELinux
-  users are using is to change their SELinux policy to grant key search
-  access to all domains.  This works, but it is an odd extra step that
-  shouldn't really have to be done.
-
-The fix for all these issues is to change the implementation to what I
-should have done originally: don't use the keyrings subsystem to keep
-track of the filesystem's fscrypt_master_key structs.  Instead, just
-store them in a regular kernel data structure, and rework the reference
-counting, locking, and lifetime accordingly.  Retain support for
-RCU-mode key lookups by using a hash table.  Replace fscrypt_sb_free()
-with fscrypt_sb_delete(), which releases the keys synchronously and runs
-a bit earlier during unmount, so that block devices are still available.
-
-A side effect of this patch is that neither the master keys themselves
-nor the filesystem keyrings will be listed in /proc/keys anymore.
-("Master key users" and the master key users keyrings will still be
-listed.)  However, this was mostly an implementation detail, and it was
-intended just for debugging purposes.  I don't know of anyone using it.
-
-This patch does *not* change how "master key users" (->mk_users) works;
-that still uses the keyrings subsystem.  That is still needed for key
-quotas, and changing that isn't necessary to solve the issues listed
-above.  If we decide to change that too, it would be a separate patch.
-
-I've marked this as fixing the original commit that added the fscrypt
-keyring, but as noted above the most important issue that this patch
-fixes wasn't introduced until the addition of inline encryption support.
-
-Fixes: 22d94f493bfb ("fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl")
-Signed-off-by: Eric Biggers <ebiggers@google.com>
-Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/crypto/fscrypt_private.h |  71 ++++--
- fs/crypto/hooks.c           |  10 +-
- fs/crypto/keyring.c         | 486 +++++++++++++++++++-----------------
- fs/crypto/keysetup.c        |  81 +++---
- fs/crypto/policy.c          |   8 +-
- fs/super.c                  |   2 +-
- include/linux/fs.h          |   2 +-
- include/linux/fscrypt.h     |   4 +-
- 8 files changed, 353 insertions(+), 311 deletions(-)
-
-diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
-index 3afdaa084773..577cae7facb0 100644
---- a/fs/crypto/fscrypt_private.h
-+++ b/fs/crypto/fscrypt_private.h
-@@ -225,7 +225,7 @@ struct fscrypt_info {
-        * will be NULL if the master key was found in a process-subscribed
-        * keyring rather than in the filesystem-level keyring.
-        */
--      struct key *ci_master_key;
-+      struct fscrypt_master_key *ci_master_key;
-       /*
-        * Link in list of inodes that were unlocked with the master key.
-@@ -436,6 +436,40 @@ struct fscrypt_master_key_secret {
-  */
- struct fscrypt_master_key {
-+      /*
-+       * Back-pointer to the super_block of the filesystem to which this
-+       * master key has been added.  Only valid if ->mk_active_refs > 0.
-+       */
-+      struct super_block                      *mk_sb;
-+
-+      /*
-+       * Link in ->mk_sb->s_master_keys->key_hashtable.
-+       * Only valid if ->mk_active_refs > 0.
-+       */
-+      struct hlist_node                       mk_node;
-+
-+      /* Semaphore that protects ->mk_secret and ->mk_users */
-+      struct rw_semaphore                     mk_sem;
-+
-+      /*
-+       * Active and structural reference counts.  An active ref guarantees
-+       * that the struct continues to exist, continues to be in the keyring
-+       * ->mk_sb->s_master_keys, and that any embedded subkeys (e.g.
-+       * ->mk_direct_keys) that have been prepared continue to exist.
-+       * A structural ref only guarantees that the struct continues to exist.
-+       *
-+       * There is one active ref associated with ->mk_secret being present,
-+       * and one active ref for each inode in ->mk_decrypted_inodes.
-+       *
-+       * There is one structural ref associated with the active refcount being
-+       * nonzero.  Finding a key in the keyring also takes a structural ref,
-+       * which is then held temporarily while the key is operated on.
-+       */
-+      refcount_t                              mk_active_refs;
-+      refcount_t                              mk_struct_refs;
-+
-+      struct rcu_head                         mk_rcu_head;
-+
-       /*
-        * The secret key material.  After FS_IOC_REMOVE_ENCRYPTION_KEY is
-        * executed, this is wiped and no new inodes can be unlocked with this
-@@ -444,7 +478,10 @@ struct fscrypt_master_key {
-        * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
-        * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
-        *
--       * Locking: protected by this master key's key->sem.
-+       * While ->mk_secret is present, one ref in ->mk_active_refs is held.
-+       *
-+       * Locking: protected by ->mk_sem.  The manipulation of ->mk_active_refs
-+       *          associated with this field is protected by ->mk_sem as well.
-        */
-       struct fscrypt_master_key_secret        mk_secret;
-@@ -465,22 +502,12 @@ struct fscrypt_master_key {
-        *
-        * This is NULL for v1 policy keys; those can only be added by root.
-        *
--       * Locking: in addition to this keyring's own semaphore, this is
--       * protected by this master key's key->sem, so we can do atomic
--       * search+insert.  It can also be searched without taking any locks, but
--       * in that case the returned key may have already been removed.
-+       * Locking: protected by ->mk_sem.  (We don't just rely on the keyrings
-+       * subsystem semaphore ->mk_users->sem, as we need support for atomic
-+       * search+insert along with proper synchronization with ->mk_secret.)
-        */
-       struct key              *mk_users;
--      /*
--       * Length of ->mk_decrypted_inodes, plus one if mk_secret is present.
--       * Once this goes to 0, the master key is removed from ->s_master_keys.
--       * The 'struct fscrypt_master_key' will continue to live as long as the
--       * 'struct key' whose payload it is, but we won't let this reference
--       * count rise again.
--       */
--      refcount_t              mk_refcount;
--
-       /*
-        * List of inodes that were unlocked using this key.  This allows the
-        * inodes to be evicted efficiently if the key is removed.
-@@ -506,10 +533,10 @@ static inline bool
- is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
- {
-       /*
--       * The READ_ONCE() is only necessary for fscrypt_drop_inode() and
--       * fscrypt_key_describe().  These run in atomic context, so they can't
--       * take the key semaphore and thus 'secret' can change concurrently
--       * which would be a data race.  But they only need to know whether the
-+       * The READ_ONCE() is only necessary for fscrypt_drop_inode().
-+       * fscrypt_drop_inode() runs in atomic context, so it can't take the key
-+       * semaphore and thus 'secret' can change concurrently which would be a
-+       * data race.  But fscrypt_drop_inode() only need to know whether the
-        * secret *was* present at the time of check, so READ_ONCE() suffices.
-        */
-       return READ_ONCE(secret->size) != 0;
-@@ -538,7 +565,11 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
-       return 0;
- }
--struct key *
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk);
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk);
-+
-+struct fscrypt_master_key *
- fscrypt_find_master_key(struct super_block *sb,
-                       const struct fscrypt_key_specifier *mk_spec);
-diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
-index 7c01025879b3..7b8c5a1104b5 100644
---- a/fs/crypto/hooks.c
-+++ b/fs/crypto/hooks.c
-@@ -5,8 +5,6 @@
-  * Encryption hooks for higher-level filesystem operations.
-  */
--#include <linux/key.h>
--
- #include "fscrypt_private.h"
- /**
-@@ -142,7 +140,6 @@ int fscrypt_prepare_setflags(struct inode *inode,
-                            unsigned int oldflags, unsigned int flags)
- {
-       struct fscrypt_info *ci;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -158,14 +155,13 @@ int fscrypt_prepare_setflags(struct inode *inode,
-               ci = inode->i_crypt_info;
-               if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
-                       return -EINVAL;
--              key = ci->ci_master_key;
--              mk = key->payload.data[0];
--              down_read(&key->sem);
-+              mk = ci->ci_master_key;
-+              down_read(&mk->mk_sem);
-               if (is_master_key_secret_present(&mk->mk_secret))
-                       err = fscrypt_derive_dirhash_key(ci, mk);
-               else
-                       err = -ENOKEY;
--              up_read(&key->sem);
-+              up_read(&mk->mk_sem);
-               return err;
-       }
-       return 0;
-diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
-index caee9f8620dd..9b98d6a576e6 100644
---- a/fs/crypto/keyring.c
-+++ b/fs/crypto/keyring.c
-@@ -18,6 +18,7 @@
-  * information about these ioctls.
-  */
-+#include <asm/unaligned.h>
- #include <crypto/skcipher.h>
- #include <linux/key-type.h>
- #include <linux/random.h>
-@@ -25,6 +26,18 @@
- #include "fscrypt_private.h"
-+/* The master encryption keys for a filesystem (->s_master_keys) */
-+struct fscrypt_keyring {
-+      /*
-+       * Lock that protects ->key_hashtable.  It does *not* protect the
-+       * fscrypt_master_key structs themselves.
-+       */
-+      spinlock_t lock;
-+
-+      /* Hash table that maps fscrypt_key_specifier to fscrypt_master_key */
-+      struct hlist_head key_hashtable[128];
-+};
-+
- static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret)
- {
-       fscrypt_destroy_hkdf(&secret->hkdf);
-@@ -38,20 +51,70 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst,
-       memzero_explicit(src, sizeof(*src));
- }
--static void free_master_key(struct fscrypt_master_key *mk)
-+static void fscrypt_free_master_key(struct rcu_head *head)
-+{
-+      struct fscrypt_master_key *mk =
-+              container_of(head, struct fscrypt_master_key, mk_rcu_head);
-+      /*
-+       * The master key secret and any embedded subkeys should have already
-+       * been wiped when the last active reference to the fscrypt_master_key
-+       * struct was dropped; doing it here would be unnecessarily late.
-+       * Nevertheless, use kfree_sensitive() in case anything was missed.
-+       */
-+      kfree_sensitive(mk);
-+}
-+
-+void fscrypt_put_master_key(struct fscrypt_master_key *mk)
-+{
-+      if (!refcount_dec_and_test(&mk->mk_struct_refs))
-+              return;
-+      /*
-+       * No structural references left, so free ->mk_users, and also free the
-+       * fscrypt_master_key struct itself after an RCU grace period ensures
-+       * that concurrent keyring lookups can no longer find it.
-+       */
-+      WARN_ON(refcount_read(&mk->mk_active_refs) != 0);
-+      key_put(mk->mk_users);
-+      mk->mk_users = NULL;
-+      call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
-+}
-+
-+void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk)
- {
-+      struct super_block *sb = mk->mk_sb;
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       size_t i;
--      wipe_master_key_secret(&mk->mk_secret);
-+      if (!refcount_dec_and_test(&mk->mk_active_refs))
-+              return;
-+      /*
-+       * No active references left, so complete the full removal of this
-+       * fscrypt_master_key struct by removing it from the keyring and
-+       * destroying any subkeys embedded in it.
-+       */
-+
-+      spin_lock(&keyring->lock);
-+      hlist_del_rcu(&mk->mk_node);
-+      spin_unlock(&keyring->lock);
-+
-+      /*
-+       * ->mk_active_refs == 0 implies that ->mk_secret is not present and
-+       * that ->mk_decrypted_inodes is empty.
-+       */
-+      WARN_ON(is_master_key_secret_present(&mk->mk_secret));
-+      WARN_ON(!list_empty(&mk->mk_decrypted_inodes));
-       for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
-               fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]);
-               fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]);
-       }
-+      memzero_explicit(&mk->mk_ino_hash_key,
-+                       sizeof(mk->mk_ino_hash_key));
-+      mk->mk_ino_hash_key_initialized = false;
--      key_put(mk->mk_users);
--      kfree_sensitive(mk);
-+      /* Drop the structural ref associated with the active refs. */
-+      fscrypt_put_master_key(mk);
- }
- static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-@@ -61,44 +124,6 @@ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
-       return master_key_spec_len(spec) != 0;
- }
--static int fscrypt_key_instantiate(struct key *key,
--                                 struct key_preparsed_payload *prep)
--{
--      key->payload.data[0] = (struct fscrypt_master_key *)prep->data;
--      return 0;
--}
--
--static void fscrypt_key_destroy(struct key *key)
--{
--      free_master_key(key->payload.data[0]);
--}
--
--static void fscrypt_key_describe(const struct key *key, struct seq_file *m)
--{
--      seq_puts(m, key->description);
--
--      if (key_is_positive(key)) {
--              const struct fscrypt_master_key *mk = key->payload.data[0];
--
--              if (!is_master_key_secret_present(&mk->mk_secret))
--                      seq_puts(m, ": secret removed");
--      }
--}
--
--/*
-- * Type of key in ->s_master_keys.  Each key of this type represents a master
-- * key which has been added to the filesystem.  Its payload is a
-- * 'struct fscrypt_master_key'.  The "." prefix in the key type name prevents
-- * users from adding keys of this type via the keyrings syscalls rather than via
-- * the intended method of FS_IOC_ADD_ENCRYPTION_KEY.
-- */
--static struct key_type key_type_fscrypt = {
--      .name                   = "._fscrypt",
--      .instantiate            = fscrypt_key_instantiate,
--      .destroy                = fscrypt_key_destroy,
--      .describe               = fscrypt_key_describe,
--};
--
- static int fscrypt_user_key_instantiate(struct key *key,
-                                       struct key_preparsed_payload *prep)
- {
-@@ -131,32 +156,6 @@ static struct key_type key_type_fscrypt_user = {
-       .describe               = fscrypt_user_key_describe,
- };
--/* Search ->s_master_keys or ->mk_users */
--static struct key *search_fscrypt_keyring(struct key *keyring,
--                                        struct key_type *type,
--                                        const char *description)
--{
--      /*
--       * We need to mark the keyring reference as "possessed" so that we
--       * acquire permission to search it, via the KEY_POS_SEARCH permission.
--       */
--      key_ref_t keyref = make_key_ref(keyring, true /* possessed */);
--
--      keyref = keyring_search(keyref, type, description, false);
--      if (IS_ERR(keyref)) {
--              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
--                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
--                      keyref = ERR_PTR(-ENOKEY);
--              return ERR_CAST(keyref);
--      }
--      return key_ref_to_ptr(keyref);
--}
--
--#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE   \
--      (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id))
--
--#define FSCRYPT_MK_DESCRIPTION_SIZE   (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1)
--
- #define FSCRYPT_MK_USERS_DESCRIPTION_SIZE     \
-       (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
-        CONST_STRLEN("-users") + 1)
-@@ -164,21 +163,6 @@ static struct key *search_fscrypt_keyring(struct key *keyring,
- #define FSCRYPT_MK_USER_DESCRIPTION_SIZE      \
-       (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
--static void format_fs_keyring_description(
--                      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE],
--                      const struct super_block *sb)
--{
--      sprintf(description, "fscrypt-%s", sb->s_id);
--}
--
--static void format_mk_description(
--                      char description[FSCRYPT_MK_DESCRIPTION_SIZE],
--                      const struct fscrypt_key_specifier *mk_spec)
--{
--      sprintf(description, "%*phN",
--              master_key_spec_len(mk_spec), (u8 *)&mk_spec->u);
--}
--
- static void format_mk_users_keyring_description(
-                       char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
-                       const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
-@@ -199,20 +183,15 @@ static void format_mk_user_description(
- /* Create ->s_master_keys if needed.  Synchronized by fscrypt_add_key_mutex. */
- static int allocate_filesystem_keyring(struct super_block *sb)
- {
--      char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE];
--      struct key *keyring;
-+      struct fscrypt_keyring *keyring;
-       if (sb->s_master_keys)
-               return 0;
--      format_fs_keyring_description(description, sb);
--      keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
--                              current_cred(), KEY_POS_SEARCH |
--                                KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW,
--                              KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
--      if (IS_ERR(keyring))
--              return PTR_ERR(keyring);
--
-+      keyring = kzalloc(sizeof(*keyring), GFP_KERNEL);
-+      if (!keyring)
-+              return -ENOMEM;
-+      spin_lock_init(&keyring->lock);
-       /*
-        * Pairs with the smp_load_acquire() in fscrypt_find_master_key().
-        * I.e., here we publish ->s_master_keys with a RELEASE barrier so that
-@@ -222,21 +201,75 @@ static int allocate_filesystem_keyring(struct super_block *sb)
-       return 0;
- }
--void fscrypt_sb_free(struct super_block *sb)
-+/*
-+ * This is called at unmount time to release all encryption keys that have been
-+ * added to the filesystem, along with the keyring that contains them.
-+ *
-+ * Note that besides clearing and freeing memory, this might need to evict keys
-+ * from the keyslots of an inline crypto engine.  Therefore, this must be called
-+ * while the filesystem's underlying block device(s) are still available.
-+ */
-+void fscrypt_sb_delete(struct super_block *sb)
- {
--      key_put(sb->s_master_keys);
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-+      size_t i;
-+
-+      if (!keyring)
-+              return;
-+
-+      for (i = 0; i < ARRAY_SIZE(keyring->key_hashtable); i++) {
-+              struct hlist_head *bucket = &keyring->key_hashtable[i];
-+              struct fscrypt_master_key *mk;
-+              struct hlist_node *tmp;
-+
-+              hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
-+                      /*
-+                       * Since all inodes were already evicted, every key
-+                       * remaining in the keyring should have an empty inode
-+                       * list, and should only still be in the keyring due to
-+                       * the single active ref associated with ->mk_secret.
-+                       * There should be no structural refs beyond the one
-+                       * associated with the active ref.
-+                       */
-+                      WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
-+                      WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
-+                      WARN_ON(!is_master_key_secret_present(&mk->mk_secret));
-+                      wipe_master_key_secret(&mk->mk_secret);
-+                      fscrypt_put_master_key_activeref(mk);
-+              }
-+      }
-+      kfree_sensitive(keyring);
-       sb->s_master_keys = NULL;
- }
-+static struct hlist_head *
-+fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring,
-+                     const struct fscrypt_key_specifier *mk_spec)
-+{
-+      /*
-+       * Since key specifiers should be "random" values, it is sufficient to
-+       * use a trivial hash function that just takes the first several bits of
-+       * the key specifier.
-+       */
-+      unsigned long i = get_unaligned((unsigned long *)&mk_spec->u);
-+
-+      return &keyring->key_hashtable[i % ARRAY_SIZE(keyring->key_hashtable)];
-+}
-+
- /*
-- * Find the specified master key in ->s_master_keys.
-- * Returns ERR_PTR(-ENOKEY) if not found.
-+ * Find the specified master key struct in ->s_master_keys and take a structural
-+ * ref to it.  The structural ref guarantees that the key struct continues to
-+ * exist, but it does *not* guarantee that ->s_master_keys continues to contain
-+ * the key struct.  The structural ref needs to be dropped by
-+ * fscrypt_put_master_key().  Returns NULL if the key struct is not found.
-  */
--struct key *fscrypt_find_master_key(struct super_block *sb,
--                                  const struct fscrypt_key_specifier *mk_spec)
-+struct fscrypt_master_key *
-+fscrypt_find_master_key(struct super_block *sb,
-+                      const struct fscrypt_key_specifier *mk_spec)
- {
--      struct key *keyring;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
-+      struct fscrypt_keyring *keyring;
-+      struct hlist_head *bucket;
-+      struct fscrypt_master_key *mk;
-       /*
-        * Pairs with the smp_store_release() in allocate_filesystem_keyring().
-@@ -246,10 +279,38 @@ struct key *fscrypt_find_master_key(struct super_block *sb,
-        */
-       keyring = smp_load_acquire(&sb->s_master_keys);
-       if (keyring == NULL)
--              return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */
--
--      format_mk_description(description, mk_spec);
--      return search_fscrypt_keyring(keyring, &key_type_fscrypt, description);
-+              return NULL; /* No keyring yet, so no keys yet. */
-+
-+      bucket = fscrypt_mk_hash_bucket(keyring, mk_spec);
-+      rcu_read_lock();
-+      switch (mk_spec->type) {
-+      case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
-+                          memcmp(mk->mk_spec.u.descriptor,
-+                                 mk_spec->u.descriptor,
-+                                 FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
-+              hlist_for_each_entry_rcu(mk, bucket, mk_node) {
-+                      if (mk->mk_spec.type ==
-+                              FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&
-+                          memcmp(mk->mk_spec.u.identifier,
-+                                 mk_spec->u.identifier,
-+                                 FSCRYPT_KEY_IDENTIFIER_SIZE) == 0 &&
-+                          refcount_inc_not_zero(&mk->mk_struct_refs))
-+                              goto out;
-+              }
-+              break;
-+      }
-+      mk = NULL;
-+out:
-+      rcu_read_unlock();
-+      return mk;
- }
- static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
-@@ -277,17 +338,30 @@ static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
- static struct key *find_master_key_user(struct fscrypt_master_key *mk)
- {
-       char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
-+      key_ref_t keyref;
-       format_mk_user_description(description, mk->mk_spec.u.identifier);
--      return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_user,
--                                    description);
-+
-+      /*
-+       * We need to mark the keyring reference as "possessed" so that we
-+       * acquire permission to search it, via the KEY_POS_SEARCH permission.
-+       */
-+      keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/),
-+                              &key_type_fscrypt_user, description, false);
-+      if (IS_ERR(keyref)) {
-+              if (PTR_ERR(keyref) == -EAGAIN || /* not found */
-+                  PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
-+                      keyref = ERR_PTR(-ENOKEY);
-+              return ERR_CAST(keyref);
-+      }
-+      return key_ref_to_ptr(keyref);
- }
- /*
-  * Give the current user a "key" in ->mk_users.  This charges the user's quota
-  * and marks the master key as added by the current user, so that it cannot be
-- * removed by another user with the key.  Either the master key's key->sem must
-- * be held for write, or the master key must be still undergoing initialization.
-+ * removed by another user with the key.  Either ->mk_sem must be held for
-+ * write, or the master key must be still undergoing initialization.
-  */
- static int add_master_key_user(struct fscrypt_master_key *mk)
- {
-@@ -309,7 +383,7 @@ static int add_master_key_user(struct fscrypt_master_key *mk)
- /*
-  * Remove the current user's "key" from ->mk_users.
-- * The master key's key->sem must be held for write.
-+ * ->mk_sem must be held for write.
-  *
-  * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
-  */
-@@ -327,63 +401,49 @@ static int remove_master_key_user(struct fscrypt_master_key *mk)
- }
- /*
-- * Allocate a new fscrypt_master_key which contains the given secret, set it as
-- * the payload of a new 'struct key' of type fscrypt, and link the 'struct key'
-- * into the given keyring.  Synchronized by fscrypt_add_key_mutex.
-+ * Allocate a new fscrypt_master_key, transfer the given secret over to it, and
-+ * insert it into sb->s_master_keys.
-  */
--static int add_new_master_key(struct fscrypt_master_key_secret *secret,
--                            const struct fscrypt_key_specifier *mk_spec,
--                            struct key *keyring)
-+static int add_new_master_key(struct super_block *sb,
-+                            struct fscrypt_master_key_secret *secret,
-+                            const struct fscrypt_key_specifier *mk_spec)
- {
-+      struct fscrypt_keyring *keyring = sb->s_master_keys;
-       struct fscrypt_master_key *mk;
--      char description[FSCRYPT_MK_DESCRIPTION_SIZE];
--      struct key *key;
-       int err;
-       mk = kzalloc(sizeof(*mk), GFP_KERNEL);
-       if (!mk)
-               return -ENOMEM;
-+      mk->mk_sb = sb;
-+      init_rwsem(&mk->mk_sem);
-+      refcount_set(&mk->mk_struct_refs, 1);
-       mk->mk_spec = *mk_spec;
--      move_master_key_secret(&mk->mk_secret, secret);
--
--      refcount_set(&mk->mk_refcount, 1); /* secret is present */
-       INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
-       spin_lock_init(&mk->mk_decrypted_inodes_lock);
-       if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
-               err = allocate_master_key_users_keyring(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-               err = add_master_key_user(mk);
-               if (err)
--                      goto out_free_mk;
-+                      goto out_put;
-       }
--      /*
--       * Note that we don't charge this key to anyone's quota, since when
--       * ->mk_users is in use those keys are charged instead, and otherwise
--       * (when ->mk_users isn't in use) only root can add these keys.
--       */
--      format_mk_description(description, mk_spec);
--      key = key_alloc(&key_type_fscrypt, description,
--                      GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
--                      KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_USR_VIEW,
--                      KEY_ALLOC_NOT_IN_QUOTA, NULL);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              goto out_free_mk;
--      }
--      err = key_instantiate_and_link(key, mk, sizeof(*mk), keyring, NULL);
--      key_put(key);
--      if (err)
--              goto out_free_mk;
-+      move_master_key_secret(&mk->mk_secret, secret);
-+      refcount_set(&mk->mk_active_refs, 1); /* ->mk_secret is present */
-+      spin_lock(&keyring->lock);
-+      hlist_add_head_rcu(&mk->mk_node,
-+                         fscrypt_mk_hash_bucket(keyring, mk_spec));
-+      spin_unlock(&keyring->lock);
-       return 0;
--out_free_mk:
--      free_master_key(mk);
-+out_put:
-+      fscrypt_put_master_key(mk);
-       return err;
- }
-@@ -392,42 +452,34 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret,
- static int add_existing_master_key(struct fscrypt_master_key *mk,
-                                  struct fscrypt_master_key_secret *secret)
- {
--      struct key *mk_user;
--      bool rekey;
-       int err;
-       /*
-        * If the current user is already in ->mk_users, then there's nothing to
--       * do.  (Not applicable for v1 policy keys, which have NULL ->mk_users.)
-+       * do.  Otherwise, we need to add the user to ->mk_users.  (Neither is
-+       * applicable for v1 policy keys, which have NULL ->mk_users.)
-        */
-       if (mk->mk_users) {
--              mk_user = find_master_key_user(mk);
-+              struct key *mk_user = find_master_key_user(mk);
-+
-               if (mk_user != ERR_PTR(-ENOKEY)) {
-                       if (IS_ERR(mk_user))
-                               return PTR_ERR(mk_user);
-                       key_put(mk_user);
-                       return 0;
-               }
--      }
--
--      /* If we'll be re-adding ->mk_secret, try to take the reference. */
--      rekey = !is_master_key_secret_present(&mk->mk_secret);
--      if (rekey && !refcount_inc_not_zero(&mk->mk_refcount))
--              return KEY_DEAD;
--
--      /* Add the current user to ->mk_users, if applicable. */
--      if (mk->mk_users) {
-               err = add_master_key_user(mk);
--              if (err) {
--                      if (rekey && refcount_dec_and_test(&mk->mk_refcount))
--                              return KEY_DEAD;
-+              if (err)
-                       return err;
--              }
-       }
-       /* Re-add the secret if needed. */
--      if (rekey)
-+      if (!is_master_key_secret_present(&mk->mk_secret)) {
-+              if (!refcount_inc_not_zero(&mk->mk_active_refs))
-+                      return KEY_DEAD;
-               move_master_key_secret(&mk->mk_secret, secret);
-+      }
-+
-       return 0;
- }
-@@ -436,38 +488,36 @@ static int do_add_master_key(struct super_block *sb,
-                            const struct fscrypt_key_specifier *mk_spec)
- {
-       static DEFINE_MUTEX(fscrypt_add_key_mutex);
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       int err;
-       mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */
--retry:
--      key = fscrypt_find_master_key(sb, mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
--              if (err != -ENOKEY)
--                      goto out_unlock;
-+
-+      mk = fscrypt_find_master_key(sb, mk_spec);
-+      if (!mk) {
-               /* Didn't find the key in ->s_master_keys.  Add it. */
-               err = allocate_filesystem_keyring(sb);
--              if (err)
--                      goto out_unlock;
--              err = add_new_master_key(secret, mk_spec, sb->s_master_keys);
-+              if (!err)
-+                      err = add_new_master_key(sb, secret, mk_spec);
-       } else {
-               /*
-                * Found the key in ->s_master_keys.  Re-add the secret if
-                * needed, and add the user to ->mk_users if needed.
-                */
--              down_write(&key->sem);
--              err = add_existing_master_key(key->payload.data[0], secret);
--              up_write(&key->sem);
-+              down_write(&mk->mk_sem);
-+              err = add_existing_master_key(mk, secret);
-+              up_write(&mk->mk_sem);
-               if (err == KEY_DEAD) {
--                      /* Key being removed or needs to be removed */
--                      key_invalidate(key);
--                      key_put(key);
--                      goto retry;
-+                      /*
-+                       * We found a key struct, but it's already been fully
-+                       * removed.  Ignore the old struct and add a new one.
-+                       * fscrypt_add_key_mutex means we don't need to worry
-+                       * about concurrent adds.
-+                       */
-+                      err = add_new_master_key(sb, secret, mk_spec);
-               }
--              key_put(key);
-+              fscrypt_put_master_key(mk);
-       }
--out_unlock:
-       mutex_unlock(&fscrypt_add_key_mutex);
-       return err;
- }
-@@ -771,19 +821,19 @@ int fscrypt_verify_key_added(struct super_block *sb,
-                            const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
- {
-       struct fscrypt_key_specifier mk_spec;
--      struct key *key, *mk_user;
-       struct fscrypt_master_key *mk;
-+      struct key *mk_user;
-       int err;
-       mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
-       memcpy(mk_spec.u.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE);
--      key = fscrypt_find_master_key(sb, &mk_spec);
--      if (IS_ERR(key)) {
--              err = PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &mk_spec);
-+      if (!mk) {
-+              err = -ENOKEY;
-               goto out;
-       }
--      mk = key->payload.data[0];
-+      down_read(&mk->mk_sem);
-       mk_user = find_master_key_user(mk);
-       if (IS_ERR(mk_user)) {
-               err = PTR_ERR(mk_user);
-@@ -791,7 +841,8 @@ int fscrypt_verify_key_added(struct super_block *sb,
-               key_put(mk_user);
-               err = 0;
-       }
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (err == -ENOKEY && capable(CAP_FOWNER))
-               err = 0;
-@@ -953,11 +1004,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_remove_key_arg __user *uarg = _uarg;
-       struct fscrypt_remove_key_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       u32 status_flags = 0;
-       int err;
--      bool dead;
-+      bool inodes_remain;
-       if (copy_from_user(&arg, uarg, sizeof(arg)))
-               return -EFAULT;
-@@ -977,12 +1027,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               return -EACCES;
-       /* Find the key being removed. */
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key))
--              return PTR_ERR(key);
--      mk = key->payload.data[0];
--
--      down_write(&key->sem);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk)
-+              return -ENOKEY;
-+      down_write(&mk->mk_sem);
-       /* If relevant, remove current user's (or all users) claim to the key */
-       if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -991,7 +1039,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-               else
-                       err = remove_master_key_user(mk);
-               if (err) {
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-               if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
-@@ -1003,26 +1051,22 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-                       status_flags |=
-                               FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS;
-                       err = 0;
--                      up_write(&key->sem);
-+                      up_write(&mk->mk_sem);
-                       goto out_put_key;
-               }
-       }
-       /* No user claims remaining.  Go ahead and wipe the secret. */
--      dead = false;
-+      err = -ENOKEY;
-       if (is_master_key_secret_present(&mk->mk_secret)) {
-               wipe_master_key_secret(&mk->mk_secret);
--              dead = refcount_dec_and_test(&mk->mk_refcount);
--      }
--      up_write(&key->sem);
--      if (dead) {
--              /*
--               * No inodes reference the key, and we wiped the secret, so the
--               * key object is free to be removed from the keyring.
--               */
--              key_invalidate(key);
-+              fscrypt_put_master_key_activeref(mk);
-               err = 0;
--      } else {
-+      }
-+      inodes_remain = refcount_read(&mk->mk_active_refs) > 0;
-+      up_write(&mk->mk_sem);
-+
-+      if (inodes_remain) {
-               /* Some inodes still reference this key; try to evict them. */
-               err = try_to_lock_encrypted_files(sb, mk);
-               if (err == -EBUSY) {
-@@ -1038,7 +1082,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
-        * has been fully removed including all files locked.
-        */
- out_put_key:
--      key_put(key);
-+      fscrypt_put_master_key(mk);
-       if (err == 0)
-               err = put_user(status_flags, &uarg->removal_status_flags);
-       return err;
-@@ -1085,7 +1129,6 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
- {
-       struct super_block *sb = file_inode(filp)->i_sb;
-       struct fscrypt_get_key_status_arg arg;
--      struct key *key;
-       struct fscrypt_master_key *mk;
-       int err;
-@@ -1102,19 +1145,18 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       arg.user_count = 0;
-       memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved));
--      key = fscrypt_find_master_key(sb, &arg.key_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY))
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(sb, &arg.key_spec);
-+      if (!mk) {
-               arg.status = FSCRYPT_KEY_STATUS_ABSENT;
-               err = 0;
-               goto out;
-       }
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
--              arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED;
-+              arg.status = refcount_read(&mk->mk_active_refs) > 0 ?
-+                      FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED :
-+                      FSCRYPT_KEY_STATUS_ABSENT /* raced with full removal */;
-               err = 0;
-               goto out_release_key;
-       }
-@@ -1136,8 +1178,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
-       }
-       err = 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
- out:
-       if (!err && copy_to_user(uarg, &arg, sizeof(arg)))
-               err = -EFAULT;
-@@ -1149,13 +1191,9 @@ int __init fscrypt_init_keyring(void)
- {
-       int err;
--      err = register_key_type(&key_type_fscrypt);
--      if (err)
--              return err;
--
-       err = register_key_type(&key_type_fscrypt_user);
-       if (err)
--              goto err_unregister_fscrypt;
-+              return err;
-       err = register_key_type(&key_type_fscrypt_provisioning);
-       if (err)
-@@ -1165,7 +1203,5 @@ int __init fscrypt_init_keyring(void)
- err_unregister_fscrypt_user:
-       unregister_key_type(&key_type_fscrypt_user);
--err_unregister_fscrypt:
--      unregister_key_type(&key_type_fscrypt);
-       return err;
- }
-diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
-index fbc71abdabe3..e037a7b8e9e4 100644
---- a/fs/crypto/keysetup.c
-+++ b/fs/crypto/keysetup.c
-@@ -9,7 +9,6 @@
-  */
- #include <crypto/skcipher.h>
--#include <linux/key.h>
- #include <linux/random.h>
- #include "fscrypt_private.h"
-@@ -159,6 +158,7 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key)
- {
-       crypto_free_skcipher(prep_key->tfm);
-       fscrypt_destroy_inline_crypt_key(prep_key);
-+      memzero_explicit(prep_key, sizeof(*prep_key));
- }
- /* Given a per-file encryption key, set up the file's crypto transform object */
-@@ -412,20 +412,18 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
- /*
-  * Find the master key, then set up the inode's actual encryption key.
-  *
-- * If the master key is found in the filesystem-level keyring, then the
-- * corresponding 'struct key' is returned in *master_key_ret with its semaphore
-- * read-locked.  This is needed to ensure that only one task links the
-- * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create
-- * an fscrypt_info for the same inode), and to synchronize the master key being
-- * removed with a new inode starting to use it.
-+ * If the master key is found in the filesystem-level keyring, then it is
-+ * returned in *mk_ret with its semaphore read-locked.  This is needed to ensure
-+ * that only one task links the fscrypt_info into ->mk_decrypted_inodes (as
-+ * multiple tasks may race to create an fscrypt_info for the same inode), and to
-+ * synchronize the master key being removed with a new inode starting to use it.
-  */
- static int setup_file_encryption_key(struct fscrypt_info *ci,
-                                    bool need_dirhash_key,
--                                   struct key **master_key_ret)
-+                                   struct fscrypt_master_key **mk_ret)
- {
--      struct key *key;
--      struct fscrypt_master_key *mk = NULL;
-       struct fscrypt_key_specifier mk_spec;
-+      struct fscrypt_master_key *mk;
-       int err;
-       err = fscrypt_select_encryption_impl(ci);
-@@ -436,11 +434,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       if (err)
-               return err;
--      key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
--      if (IS_ERR(key)) {
--              if (key != ERR_PTR(-ENOKEY) ||
--                  ci->ci_policy.version != FSCRYPT_POLICY_V1)
--                      return PTR_ERR(key);
-+      mk = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
-+      if (!mk) {
-+              if (ci->ci_policy.version != FSCRYPT_POLICY_V1)
-+                      return -ENOKEY;
-               /*
-                * As a legacy fallback for v1 policies, search for the key in
-@@ -450,9 +447,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-                */
-               return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci);
-       }
--
--      mk = key->payload.data[0];
--      down_read(&key->sem);
-+      down_read(&mk->mk_sem);
-       /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
-       if (!is_master_key_secret_present(&mk->mk_secret)) {
-@@ -480,18 +475,18 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
-       if (err)
-               goto out_release_key;
--      *master_key_ret = key;
-+      *mk_ret = mk;
-       return 0;
- out_release_key:
--      up_read(&key->sem);
--      key_put(key);
-+      up_read(&mk->mk_sem);
-+      fscrypt_put_master_key(mk);
-       return err;
- }
- static void put_crypt_info(struct fscrypt_info *ci)
- {
--      struct key *key;
-+      struct fscrypt_master_key *mk;
-       if (!ci)
-               return;
-@@ -501,24 +496,18 @@ static void put_crypt_info(struct fscrypt_info *ci)
-       else if (ci->ci_owns_key)
-               fscrypt_destroy_prepared_key(&ci->ci_enc_key);
--      key = ci->ci_master_key;
--      if (key) {
--              struct fscrypt_master_key *mk = key->payload.data[0];
--
-+      mk = ci->ci_master_key;
-+      if (mk) {
-               /*
-                * Remove this inode from the list of inodes that were unlocked
--               * with the master key.
--               *
--               * In addition, if we're removing the last inode from a key that
--               * already had its secret removed, invalidate the key so that it
--               * gets removed from ->s_master_keys.
-+               * with the master key.  In addition, if we're removing the last
-+               * inode from a master key struct that already had its secret
-+               * removed, then complete the full removal of the struct.
-                */
-               spin_lock(&mk->mk_decrypted_inodes_lock);
-               list_del(&ci->ci_master_key_link);
-               spin_unlock(&mk->mk_decrypted_inodes_lock);
--              if (refcount_dec_and_test(&mk->mk_refcount))
--                      key_invalidate(key);
--              key_put(key);
-+              fscrypt_put_master_key_activeref(mk);
-       }
-       memzero_explicit(ci, sizeof(*ci));
-       kmem_cache_free(fscrypt_info_cachep, ci);
-@@ -532,7 +521,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
- {
-       struct fscrypt_info *crypt_info;
-       struct fscrypt_mode *mode;
--      struct key *master_key = NULL;
-+      struct fscrypt_master_key *mk = NULL;
-       int res;
-       res = fscrypt_initialize(inode->i_sb->s_cop->flags);
-@@ -555,8 +544,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
-       crypt_info->ci_mode = mode;
--      res = setup_file_encryption_key(crypt_info, need_dirhash_key,
--                                      &master_key);
-+      res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
-       if (res)
-               goto out;
-@@ -571,12 +559,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-                * We won the race and set ->i_crypt_info to our crypt_info.
-                * Now link it into the master key's inode list.
-                */
--              if (master_key) {
--                      struct fscrypt_master_key *mk =
--                              master_key->payload.data[0];
--
--                      refcount_inc(&mk->mk_refcount);
--                      crypt_info->ci_master_key = key_get(master_key);
-+              if (mk) {
-+                      crypt_info->ci_master_key = mk;
-+                      refcount_inc(&mk->mk_active_refs);
-                       spin_lock(&mk->mk_decrypted_inodes_lock);
-                       list_add(&crypt_info->ci_master_key_link,
-                                &mk->mk_decrypted_inodes);
-@@ -586,9 +571,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
-       }
-       res = 0;
- out:
--      if (master_key) {
--              up_read(&master_key->sem);
--              key_put(master_key);
-+      if (mk) {
-+              up_read(&mk->mk_sem);
-+              fscrypt_put_master_key(mk);
-       }
-       put_crypt_info(crypt_info);
-       return res;
-@@ -753,7 +738,6 @@ EXPORT_SYMBOL(fscrypt_free_inode);
- int fscrypt_drop_inode(struct inode *inode)
- {
-       const struct fscrypt_info *ci = fscrypt_get_info(inode);
--      const struct fscrypt_master_key *mk;
-       /*
-        * If ci is NULL, then the inode doesn't have an encryption key set up
-@@ -763,7 +747,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        */
-       if (!ci || !ci->ci_master_key)
-               return 0;
--      mk = ci->ci_master_key->payload.data[0];
-       /*
-        * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes
-@@ -782,6 +765,6 @@ int fscrypt_drop_inode(struct inode *inode)
-        * then the thread removing the key will either evict the inode itself
-        * or will correctly detect that it wasn't evicted due to the race.
-        */
--      return !is_master_key_secret_present(&mk->mk_secret);
-+      return !is_master_key_secret_present(&ci->ci_master_key->mk_secret);
- }
- EXPORT_SYMBOL_GPL(fscrypt_drop_inode);
-diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
-index 80b8ca0f340b..8485e7eaee2b 100644
---- a/fs/crypto/policy.c
-+++ b/fs/crypto/policy.c
-@@ -744,12 +744,8 @@ int fscrypt_set_context(struct inode *inode, void *fs_data)
-        * delayed key setup that requires the inode number.
-        */
-       if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
--          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
--              const struct fscrypt_master_key *mk =
--                      ci->ci_master_key->payload.data[0];
--
--              fscrypt_hash_inode_number(ci, mk);
--      }
-+          (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
-+              fscrypt_hash_inode_number(ci, ci->ci_master_key);
-       return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, fs_data);
- }
-diff --git a/fs/super.c b/fs/super.c
-index 734ed584a946..6a82660e1adb 100644
---- a/fs/super.c
-+++ b/fs/super.c
-@@ -291,7 +291,6 @@ static void __put_super(struct super_block *s)
-               WARN_ON(s->s_inode_lru.node);
-               WARN_ON(!list_empty(&s->s_mounts));
-               security_sb_free(s);
--              fscrypt_sb_free(s);
-               put_user_ns(s->s_user_ns);
-               kfree(s->s_subtype);
-               call_rcu(&s->rcu, destroy_super_rcu);
-@@ -480,6 +479,7 @@ void generic_shutdown_super(struct super_block *sb)
-               evict_inodes(sb);
-               /* only nonzero refcount inodes can have marks */
-               fsnotify_sb_delete(sb);
-+              fscrypt_sb_delete(sb);
-               security_sb_delete(sb);
-               if (sb->s_dio_done_wq) {
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index 56a4b4b02477..7203f5582fd4 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -1472,7 +1472,7 @@ struct super_block {
-       const struct xattr_handler **s_xattr;
- #ifdef CONFIG_FS_ENCRYPTION
-       const struct fscrypt_operations *s_cop;
--      struct key              *s_master_keys; /* master crypto keys in use */
-+      struct fscrypt_keyring  *s_master_keys; /* master crypto keys in use */
- #endif
- #ifdef CONFIG_FS_VERITY
-       const struct fsverity_operations *s_vop;
-diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
-index 7d2f1e0f23b1..d86f43bd9550 100644
---- a/include/linux/fscrypt.h
-+++ b/include/linux/fscrypt.h
-@@ -312,7 +312,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--void fscrypt_sb_free(struct super_block *sb);
-+void fscrypt_sb_delete(struct super_block *sb);
- int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
- int fscrypt_add_test_dummy_key(struct super_block *sb,
-                              const struct fscrypt_dummy_policy *dummy_policy);
-@@ -526,7 +526,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
- }
- /* keyring.c */
--static inline void fscrypt_sb_free(struct super_block *sb)
-+static inline void fscrypt_sb_delete(struct super_block *sb)
- {
- }
--- 
-2.35.1
-
index 4f760aa965ecd730589401d4f25e14e94342c818..b7e9bacd197d781f412cef28a50b7f270f0fc3f2 100644 (file)
@@ -211,7 +211,6 @@ mips-sgi-ip30-fix-platform-device-leak-in-bridge_pla.patch
 mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch
 erofs-fix-order-max_order-warning-due-to-crafted-neg.patch
 erofs-use-kill_anon_super-to-kill-super-in-fscache-m.patch
-fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch
 arm-9243-1-riscpc-unbreak-the-build.patch
 arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch
 arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch