From: Linus Torvalds <torvalds@linux-foundation.org> mainline inclusion from mainline-v7.1-rc6 commit 43a1e3744548e6fd85873e6fb43e293eb4010694 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/16340 CVE: CVE-2026-64015 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Nicholas Carlini reports that the keyring code calls assoc_array_find() in find_key_to_update() without holding the RCU read lock, while the assoc_array_gc() code really is designed around removing the node from the tree and then freeing it after an RCU grace-period. The regular key handling doesn't see this because holding the keyring semaphore hides any lifetime issues, but the persistent key handling uses a different model. Instead of extending the keyring locking, just do the simple RCU locking that the assoc_array was designed for. Reported-by: Nicholas Carlini <npc@anthropic.com> Cc: David Howells <dhowells@redhat.com> Cc: Jarkko Sakkinen <jarkko@kernel.org> Cc: Paul Moore <paul@paul-moore.com> Cc: James Morris James Morris <jmorris@namei.org> Cc: Serge E. Hallyn <serge@hallyn.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Conflicts: security/keys/keyring.c [Commit 54da6a092431 ("locking: Introduce __cleanup() based infrastructure") was nor merged. The guard() function was not introduced.] Signed-off-by: Yi Yang <yiyang13@huawei.com> --- security/keys/keyring.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 0f414a114729..cdaf751811fc 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -1064,12 +1064,14 @@ key_ref_t find_key_to_update(key_ref_t keyring_ref, kenter("{%d},{%s,%s}", keyring->serial, index_key->type->name, index_key->description); + rcu_read_lock(); object = assoc_array_find(&keyring->keys, &keyring_assoc_array_ops, index_key); if (object) goto found; + rcu_read_unlock(); kleave(" = NULL"); return NULL; @@ -1077,10 +1079,12 @@ key_ref_t find_key_to_update(key_ref_t keyring_ref, key = keyring_ptr_to_key(object); if (key->flags & ((1 << KEY_FLAG_INVALIDATED) | (1 << KEY_FLAG_REVOKED))) { + rcu_read_unlock(); kleave(" = NULL [x]"); return NULL; } __key_get(key); + rcu_read_unlock(); kleave(" = {%d}", key->serial); return make_key_ref(key, is_key_possessed(keyring_ref)); } -- 2.25.1