From 56710d109ecdde1ff178d2c8f33eddae8e8b716f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Oct 2022 08:34:55 +0200 Subject: [PATCH] drop fscrypt patches --- .../fscrypt-simplify-master-key-locking.patch | 215 --- ...ng-keyrings-subsystem-for-fscrypt_ma.patch | 1304 ----------------- queue-5.10/series | 2 - ...ng-keyrings-subsystem-for-fscrypt_ma.patch | 1304 ----------------- queue-5.15/series | 1 - ...ng-keyrings-subsystem-for-fscrypt_ma.patch | 1304 ----------------- queue-5.19/series | 1 - ...ng-keyrings-subsystem-for-fscrypt_ma.patch | 1304 ----------------- queue-6.0/series | 1 - 9 files changed, 5436 deletions(-) delete mode 100644 queue-5.10/fscrypt-simplify-master-key-locking.patch delete mode 100644 queue-5.10/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch delete mode 100644 queue-5.15/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch delete mode 100644 queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch delete mode 100644 queue-6.0/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch 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 index 7a953d5d248..00000000000 --- a/queue-5.10/fscrypt-simplify-master-key-locking.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 49f9da1c3120bc16688a203dac6f292f4487d997 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 16 Nov 2020 19:26:26 -0800 -Subject: fscrypt: simplify master key locking - -From: Eric Biggers - -[ 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 -Stable-dep-of: d7e7b9af104c ("fscrypt: stop using keyrings subsystem for fscrypt_master_key") -Signed-off-by: Sasha Levin ---- - 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 index 570c7cc242b..00000000000 --- a/queue-5.10/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch +++ /dev/null @@ -1,1304 +0,0 @@ -From 19907e51e7fec7ef211076b11f8a4429993df750 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 1 Sep 2022 12:32:06 -0700 -Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key - -From: Eric Biggers - -[ 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 -Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org -Signed-off-by: Sasha Levin ---- - 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 -- - #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 - #include - #include - #include -@@ -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 --#include - #include - - #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 - diff --git a/queue-5.10/series b/queue-5.10/series index 48f81934be0..54d1205724a 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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 index 7466d53c1c6..00000000000 --- a/queue-5.15/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch +++ /dev/null @@ -1,1304 +0,0 @@ -From 3fed658e73d0c7e04b5f0380cf88b31fbdbd9ce0 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 1 Sep 2022 12:32:06 -0700 -Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key - -From: Eric Biggers - -[ 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 -Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org -Signed-off-by: Sasha Levin ---- - 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 -- - #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 - #include - #include - #include -@@ -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 --#include - #include - - #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 - diff --git a/queue-5.15/series b/queue-5.15/series index 5cc7d810d4c..bc3c6b0920a 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 index ac483ce2e50..00000000000 --- a/queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch +++ /dev/null @@ -1,1304 +0,0 @@ -From 15d10c3e27d4314c2ba2fdb4caecd290ba0b9795 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 1 Sep 2022 12:32:06 -0700 -Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key - -From: Eric Biggers - -[ 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 -Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org -Signed-off-by: Sasha Levin ---- - 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 -- - #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 - #include - #include - #include -@@ -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 --#include - #include - - #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 - diff --git a/queue-5.19/series b/queue-5.19/series index 4cfff2ebe58..9c6604362bd 100644 --- a/queue-5.19/series +++ b/queue-5.19/series @@ -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 index 55f462e7a4d..00000000000 --- a/queue-6.0/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch +++ /dev/null @@ -1,1304 +0,0 @@ -From b85bdbcda08d53cc7429a2592980f006f3d7c4ea Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 1 Sep 2022 12:32:06 -0700 -Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key - -From: Eric Biggers - -[ 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 -Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org -Signed-off-by: Sasha Levin ---- - 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 -- - #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 - #include - #include - #include -@@ -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 --#include - #include - - #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 - diff --git a/queue-6.0/series b/queue-6.0/series index 4f760aa965e..b7e9bacd197 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -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 -- 2.47.2