[PATCH] KEYS: avoid filesystem reclaim while holding keyring->sem
Mohammed EL Kadiri <[email protected]> Sun, 14 Jun 2026 16:00:41 +0100
| Newsgroups | org.kernel.vger.keyrings,org.kernel.vger.linux-kernel,org.kernel.vger.linux-security-module,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
__key_link_begin() runs with keyring->sem held and calls assoc_array_insert(), which does GFP_KERNEL allocations. Those allocations may enter filesystem reclaim, evict an fscrypt-protected inode, and reach keyring_clear() via fscrypt_put_master_key() -- taking a keyring semaphore of the same lockdep class and closing a keyring->sem -> fs_reclaim -> keyring->sem cycle reported by syzbot. Wrap the assoc_array_insert() call with memalloc_nofs_save() / memalloc_nofs_restore() so reclaim cannot recurse into the keys subsystem while keyring->sem is held. Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=f55b043dacf43776b50c Fixes: d7e7b9af104c ("fscrypt: stop using keyrings subsystem for fscrypt_master_key") Cc: [email protected] Signed-off-by: Mohammed EL Kadiri <[email protected]> --- security/keys/keyring.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 5a9887d6b7be..21bb2e7e7cca 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -12,6 +12,7 @@ #include <linux/security.h> #include <linux/seq_file.h> #include <linux/err.h> +#include <linux/sched/mm.h> #include <linux/user_namespace.h> #include <linux/nsproxy.h> #include <keys/keyring-type.h> @@ -1298,6 +1299,7 @@ int __key_link_begin(struct key *keyring, struct assoc_array_edit **_edit) { struct assoc_array_edit *edit; + unsigned int nofs_flags; int ret; kenter("%d,%s,%s,", @@ -1315,10 +1317,12 @@ int __key_link_begin(struct key *keyring, /* Create an edit script that will insert/replace the key in the * keyring tree. */ + nofs_flags = memalloc_nofs_save(); edit = assoc_array_insert(&keyring->keys, &keyring_assoc_array_ops, index_key, NULL); + memalloc_nofs_restore(nofs_flags); if (IS_ERR(edit)) { ret = PTR_ERR(edit); goto error; -- 2.43.0