--- /dev/null
+From f4f836c1c2185ccffa01006331ec19295775e80b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Aug 2026 11:31:41 -0700
+Subject: fscrypt: Replace mk_users keyring with simple list
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit 696c030e1e3438955aba443b308ee8b6faa3983e upstream.
+
+Change mk_users (the set of user claims to an fscrypt master key) from a
+'struct key' keyring to a simple linked list.
+
+It's still a collection of 'struct key' for quota tracking. It was
+originally thought to be natural that a collection of 'struct key'
+should be held in a 'struct key' keyring. In reality, it's just been
+causing problems, similar to how using 'struct key' for the filesystem
+keyring caused problems and was removed in commit d7e7b9af104c
+("fscrypt: stop using keyrings subsystem for fscrypt_master_key").
+
+Commit d3a7bd420076 ("fscrypt: clear keyring before calling key_put()")
+fixed mk_users cleanup to be synchronous. But that apparently wasn't
+enough: the keyring subsystem's redundant locking is still generating
+lockdep false positives due to the interaction with filesystem reclaim.
+
+With the simple list, the redundant locking and lockdep issue goes away.
+
+Of course, searching a linked list is linear-time whereas the
+'struct key' keyring used a fancy constant-time associative array. But
+that's fine here, since in practice there's just one entry in the list.
+In fact the new code is much faster in practice, since it's much smaller
+and doesn't have to convert the kuid_t into a string to search for it.
+
+Reported-by: syzbot+f55b043dacf43776b50c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f55b043dacf43776b50c
+Reported-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
+Closes: https://lore.kernel.org/keyrings/20260614150041.21172-1-med08elkadiri@gmail.com/
+Fixes: 23c688b54016 ("fscrypt: allow unprivileged users to add/remove keys for v2 policies")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260618221921.87896-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/crypto/fscrypt_private.h | 32 ++++--
+ fs/crypto/keyring.c | 212 ++++++++++++++++--------------------
+ 2 files changed, 113 insertions(+), 131 deletions(-)
+
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+index b746d7df37582..72db3df9dfad7 100644
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -403,6 +403,19 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
+
+ /* keyring.c */
+
++/*
++ * fscrypt_master_key_user - a user's claim to a master key
++ */
++struct fscrypt_master_key_user {
++ struct list_head link;
++ kuid_t uid;
++ /*
++ * This 'struct key' contains no secret. It exists solely to charge the
++ * appropriate user's key quota.
++ */
++ struct key *quota_key;
++};
++
+ /*
+ * fscrypt_master_key_secret - secret key material of an in-use master key
+ */
+@@ -489,19 +502,18 @@ struct fscrypt_master_key {
+ struct fscrypt_key_specifier mk_spec;
+
+ /*
+- * Keyring which contains a key of type 'key_type_fscrypt_user' for each
+- * user who has added this key. Normally each key will be added by just
+- * one user, but it's possible that multiple users share a key, and in
+- * that case we need to keep track of those users so that one user can't
+- * remove the key before the others want it removed too.
++ * List of user claims to this key (struct fscrypt_master_key_user).
++ * Normally each key will be added by just one user, but it's possible
++ * that multiple users share a key, and in that case we need to keep
++ * track of those users so that one user can't remove the key before the
++ * others want it removed too.
+ *
+- * This is NULL for v1 policy keys; those can only be added by root.
++ * Used only for v2 policy keys. v1 policy keys can be added only by
++ * root, so user tracking doesn't apply to them.
+ *
+- * 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.)
++ * Locking: protected by ->mk_sem.
+ */
+- struct key *mk_users;
++ struct list_head mk_users;
+
+ /*
+ * List of inodes that were unlocked using this key. This allows the
+diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
+index 02f8bf8bd54da..51cd45785f0c9 100644
+--- a/fs/crypto/keyring.c
++++ b/fs/crypto/keyring.c
+@@ -64,18 +64,19 @@ static void fscrypt_free_master_key(struct rcu_head *head)
+ kfree_sensitive(mk);
+ }
+
++static void clear_mk_users(struct fscrypt_master_key *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
++ * No structural references left, so clear ->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;
++ clear_mk_users(mk);
+ call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
+ }
+
+@@ -141,8 +142,8 @@ static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m)
+ }
+
+ /*
+- * Type of key in ->mk_users. Each key of this type represents a particular
+- * user who has added a particular master key.
++ * Type of fscrypt_master_key_user::quota_key. This contains no secret; it
++ * exists solely to charge a user's key quota.
+ *
+ * Note that the name of this key type really should be something like
+ * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen
+@@ -156,30 +157,9 @@ static struct key_type key_type_fscrypt_user = {
+ .describe = fscrypt_user_key_describe,
+ };
+
+-#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \
+- (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
+- CONST_STRLEN("-users") + 1)
+-
+ #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \
+ (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
+
+-static void format_mk_users_keyring_description(
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+- sprintf(description, "fscrypt-%*phN-users",
+- FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier);
+-}
+-
+-static void format_mk_user_description(
+- char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+-
+- sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE,
+- mk_identifier, __kuid_val(current_fsuid()));
+-}
+-
+ /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */
+ static int allocate_filesystem_keyring(struct super_block *sb)
+ {
+@@ -318,91 +298,94 @@ fscrypt_find_master_key(struct super_block *sb,
+ return mk;
+ }
+
+-static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
++/* Find the current user's claim in ->mk_users. ->mk_sem must be held. */
++static struct fscrypt_master_key_user *
++find_master_key_user(struct fscrypt_master_key *mk)
+ {
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE];
+- struct key *keyring;
+-
+- format_mk_users_keyring_description(description,
+- mk->mk_spec.u.identifier);
+- 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);
+-
+- mk->mk_users = keyring;
+- return 0;
+-}
++ struct fscrypt_master_key_user *mk_user;
++ kuid_t uid = current_fsuid();
+
+-/*
+- * Find the current user's "key" in the master key's ->mk_users.
+- * Returns ERR_PTR(-ENOKEY) if not found.
+- */
+-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);
+-
+- /*
+- * 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);
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ if (uid_eq(mk_user->uid, uid))
++ return mk_user;
+ }
+- return key_ref_to_ptr(keyref);
++ return NULL;
+ }
+
+ /*
+- * Give the current user a "key" in ->mk_users. This charges the user's quota
++ * Give the current user a claim 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 ->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)
+ {
++ kuid_t uid = current_fsuid();
+ char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
+- struct key *mk_user;
++ struct key *quota_key;
++ struct fscrypt_master_key_user *mk_user;
+ int err;
+
+- format_mk_user_description(description, mk->mk_spec.u.identifier);
+- mk_user = key_alloc(&key_type_fscrypt_user, description,
+- current_fsuid(), current_gid(), current_cred(),
+- KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
++ snprintf(description, sizeof(description), "%*phN.uid.%u",
++ FSCRYPT_KEY_IDENTIFIER_SIZE, mk->mk_spec.u.identifier,
++ __kuid_val(uid));
++ quota_key = key_alloc(&key_type_fscrypt_user, description, uid,
++ current_gid(), current_cred(),
++ KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
++ if (IS_ERR(quota_key))
++ return PTR_ERR(quota_key);
++
++ err = key_instantiate_and_link(quota_key, NULL, 0, NULL, NULL);
++ if (err) {
++ key_put(quota_key);
++ return err;
++ }
+
+- err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL);
+- key_put(mk_user);
+- return err;
++ mk_user = kzalloc(sizeof(*mk_user), GFP_KERNEL);
++ if (!mk_user) {
++ key_put(quota_key);
++ return -ENOMEM;
++ }
++ mk_user->uid = uid;
++ mk_user->quota_key = quota_key;
++ list_add(&mk_user->link, &mk->mk_users);
++ return 0;
++}
++
++static void unlink_and_free_mk_user(struct fscrypt_master_key_user *mk_user)
++{
++ list_del(&mk_user->link);
++ key_put(mk_user->quota_key);
++ kfree(mk_user);
+ }
+
+ /*
+- * Remove the current user's "key" from ->mk_users.
++ * Remove the current user's claim from ->mk_users.
+ * ->mk_sem must be held for write.
+ *
+- * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
++ * Returns 0 if removed or -ENOKEY if not found.
+ */
+ static int remove_master_key_user(struct fscrypt_master_key *mk)
+ {
+- struct key *mk_user;
+- int err;
++ struct fscrypt_master_key_user *mk_user;
+
+ mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
+- err = key_unlink(mk->mk_users, mk_user);
+- key_put(mk_user);
+- return err;
++ if (!mk_user)
++ return -ENOKEY;
++ unlink_and_free_mk_user(mk_user);
++ return 0;
++}
++
++/*
++ * Clear ->mk_users. Either ->mk_sem must be held for write, or 'mk' must have
++ * no structural references left.
++ */
++static void clear_mk_users(struct fscrypt_master_key *mk)
++{
++ struct fscrypt_master_key_user *mk_user, *tmp;
++
++ list_for_each_entry_safe(mk_user, tmp, &mk->mk_users, link)
++ unlink_and_free_mk_user(mk_user);
+ }
+
+ /*
+@@ -426,13 +409,12 @@ static int add_new_master_key(struct super_block *sb,
+ refcount_set(&mk->mk_struct_refs, 1);
+ mk->mk_spec = *mk_spec;
+
++ INIT_LIST_HEAD(&mk->mk_users);
++
+ 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_put;
+ err = add_master_key_user(mk);
+ if (err)
+ goto out_put;
+@@ -460,19 +442,13 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
+ int err;
+
+ /*
+- * If the current user is already in ->mk_users, then there's nothing to
+- * do. Otherwise, we need to add the user to ->mk_users. (Neither is
+- * applicable for v1 policy keys, which have NULL ->mk_users.)
++ * For v2 policy keys (FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER): If the current
++ * user is already in ->mk_users, then there's nothing to do.
++ * Otherwise, add the user to ->mk_users.
+ */
+- if (mk->mk_users) {
+- 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);
++ if (mk->mk_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
++ if (find_master_key_user(mk) != NULL)
+ return 0;
+- }
+ err = add_master_key_user(mk);
+ if (err)
+ return err;
+@@ -787,7 +763,6 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ {
+ struct fscrypt_key_specifier mk_spec;
+ struct fscrypt_master_key *mk;
+- struct key *mk_user;
+ int err;
+
+ mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
+@@ -799,13 +774,10 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ goto out;
+ }
+ down_read(&mk->mk_sem);
+- mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user)) {
+- err = PTR_ERR(mk_user);
+- } else {
+- key_put(mk_user);
++ if (find_master_key_user(mk) != NULL)
+ err = 0;
+- }
++ else
++ err = -ENOKEY;
+ up_read(&mk->mk_sem);
+ fscrypt_put_master_key(mk);
+ out:
+@@ -998,16 +970,18 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ 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) {
+- if (all_users)
+- err = keyring_clear(mk->mk_users);
+- else
++ if (!list_empty(&mk->mk_users)) {
++ if (all_users) {
++ clear_mk_users(mk);
++ err = 0;
++ } else {
+ err = remove_master_key_user(mk);
++ }
+ if (err) {
+ up_write(&mk->mk_sem);
+ goto out_put_key;
+ }
+- if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
++ if (!list_empty(&mk->mk_users)) {
+ /*
+ * Other users have still added the key too. We removed
+ * the current user's claim to the key, but we still
+@@ -1095,6 +1069,8 @@ 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 fscrypt_master_key *mk;
++ kuid_t uid;
++ const struct fscrypt_master_key_user *mk_user;
+ int err;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+@@ -1127,19 +1103,13 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
+ }
+
+ arg.status = FSCRYPT_KEY_STATUS_PRESENT;
+- if (mk->mk_users) {
+- struct key *mk_user;
+
+- arg.user_count = mk->mk_users->keys.nr_leaves_on_tree;
+- mk_user = find_master_key_user(mk);
+- if (!IS_ERR(mk_user)) {
++ uid = current_fsuid();
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ arg.user_count++;
++ if (uid_eq(mk_user->uid, uid))
+ arg.status_flags |=
+ FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF;
+- key_put(mk_user);
+- } else if (mk_user != ERR_PTR(-ENOKEY)) {
+- err = PTR_ERR(mk_user);
+- goto out_release_key;
+- }
+ }
+ err = 0;
+ out_release_key:
+--
+2.53.0
+
--- /dev/null
+From 36481f7263218b5ab8ebf66cbe88df52e981fd14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Aug 2026 20:36:33 -0400
+Subject: mips: sched: Fix CPUMASK_OFFSTACK memory corruption
+
+From: Aaron Tomlin <atomlin@atomlin.com>
+
+[ Upstream commit 98e37db4a34d3af3fb2f4648295c25b5e40b20e3 ]
+
+This patch addresses a critical memory management flaw. When
+CONFIG_CPUMASK_OFFSTACK is enabled, cpumask_var_t is a pointer.
+Consequently, sizeof(new_mask) evaluates to the pointer size, causing
+copy_from_user() to clobber the mask pointer. Furthermore, the old
+logic performed copy_from_user() before allocating the mask.
+
+Fix this by allocating new_mask first. To handle variable-sized user
+masks correctly, use cpumask_size() to truncate overly large user masks
+or pad undersized masks with zeros before copying the data directly into
+the allocated buffer.
+
+Fixes: 295cbf6d63165 ("[MIPS] Move FPU affinity code into separate file.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/kernel/mips-mt-fpaff.c | 28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
+index 6c590ef276482..5feffc8708ada 100644
+--- a/arch/mips/kernel/mips-mt-fpaff.c
++++ b/arch/mips/kernel/mips-mt-fpaff.c
+@@ -70,11 +70,16 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+ struct task_struct *p;
+ int retval;
+
+- if (len < sizeof(new_mask))
+- return -EINVAL;
+-
+- if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+- return -EFAULT;
++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
++ return -ENOMEM;
++ if (len < cpumask_size())
++ cpumask_clear(new_mask);
++ else if (len > cpumask_size())
++ len = cpumask_size();
++ if (copy_from_user(new_mask, user_mask_ptr, len)) {
++ retval = -EFAULT;
++ goto out_free_new_mask;
++ }
+
+ get_online_cpus();
+ rcu_read_lock();
+@@ -83,7 +88,8 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+ if (!p) {
+ rcu_read_unlock();
+ put_online_cpus();
+- return -ESRCH;
++ retval = -ESRCH;
++ goto out_free_new_mask;
+ }
+
+ /* Prevent p going away */
+@@ -94,13 +100,9 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+ retval = -ENOMEM;
+ goto out_put_task;
+ }
+- if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
+- retval = -ENOMEM;
+- goto out_free_cpus_allowed;
+- }
+ if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) {
+ retval = -ENOMEM;
+- goto out_free_new_mask;
++ goto out_free_cpus_allowed;
+ }
+ if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) {
+ retval = -EPERM;
+@@ -141,13 +143,13 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+ }
+ out_unlock:
+ free_cpumask_var(effective_mask);
+-out_free_new_mask:
+- free_cpumask_var(new_mask);
+ out_free_cpus_allowed:
+ free_cpumask_var(cpus_allowed);
+ out_put_task:
+ put_task_struct(p);
+ put_online_cpus();
++out_free_new_mask:
++ free_cpumask_var(new_mask);
+ return retval;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From d2065fbd2e7334b6c9d18fa13d2fd2ff512748ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Aug 2026 13:23:59 -0700
+Subject: RDMA/rxe: Fix a use-after-free problem in rxe_mmap
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhu Yanjun <yanjun.zhu@linux.dev>
+
+[ Upstream commit 35744ab3d03c5fca8c1752f53fc8fc674e14c561 ]
+
+rxe_mmap() removes a rxe_mmap_info struct from the pending_mmaps list
+and releases pending_lock while the struct's kref is still at 1:
+
+ list_del_init(&ip->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock); /* ref == 1, no lock held */
+ ret = remap_vmalloc_range(vma, ip->obj, 0); /* walks PTEs */
+ [...]
+ rxe_vma_open(vma); /* kref_get, ref → 2 */
+ remap_vmalloc_range_partial() walks PTEs without any lock.
+
+A concurrent DESTROY_CQ ioctl on another CPU calls:
+
+ kref_put(&q->ip->ref, rxe_mmap_release) /* ref 1→0 */
+ vfree(ip->obj) /* clears vmalloc PTEs mid-walk */
+ kfree(ip) /* frees rxe_mmap_info */
+
+This yields:
+
+ 1. Kernel crash, vmalloc_to_page() returns NULL when vfree wins the
+ per-PTE race -> vm_insert_page(NULL) → GPF in validate_page_before_insert
+
+ 2. Page UAF, vmalloc_to_page() reads a stale PTE before vfree clears
+ it. User VMA holds a PTE to a free'd page which might eventually get
+ reallocated later by vmalloc which allows the attacker to get a clean
+ page-level UAF.
+
+ It is worth noting that even though a page-level UAF is possible given
+ the strong primitive, it is statistically very difficult to achieve
+ given the very short time window (after the last insert_page and before
+ the kref_get).
+
+The call trace are as below:
+
+ Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI
+ KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
+ CPU: 0 UID: 1000 PID: 413 Comm: poc Not tainted 7.0.0-rc5-dirty #28 PREEMPT(lazy)
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+ RIP: 0010:validate_page_before_insert+0x32/0x300
+ Code: e5 41 57 41 56 49 89 fe 41 55 41 54 53 48 89 f3 e8 93 b5 a3 ff 48 8d 7b 08 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 7b 02 00 00 4c 8b 63 08 31 ff 4d 89 e5 41 83 e5
+ RSP: 0018:ffff88811b15f2f0 EFLAGS: 00000202
+ RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
+ RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000000000000008
+ RBP: ffff88811b15f318 R08: 0000000000000000 R09: 0000000000000000
+ R10: 0000000000000000 R11: 0000000000000000 R12: ffff8881181eee00
+ R13: 0000000000000000 R14: ffff8881181eee00 R15: ffff8881181eee20
+ FS: 00007b1e000f76c0(0000) GS:ffff8884268e0000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007b1e00a24ac0 CR3: 0000000116eb3000 CR4: 00000000000006f0
+ Call Trace:
+ <TASK>
+ insert_page+0x8f/0x190
+ ? __pfx_insert_page+0x10/0x10
+ ? kasan_save_alloc_info+0x38/0x60
+ vm_insert_page+0x2e7/0x400
+ remap_vmalloc_range_partial+0x212/0x3e0
+ remap_vmalloc_range+0x6e/0xb0
+ ? __kasan_check_write+0x14/0x30
+ rxe_mmap+0x2e9/0x5d0
+ ib_uverbs_mmap+0x1ad/0x2c0
+ __mmap_region+0x12c2/0x2ad0
+ ? __pfx___mmap_region+0x10/0x10
+ ? __sanitizer_cov_trace_switch+0x58/0xb0
+ ? mas_prev_slot+0x360/0x39c0
+ ? __sanitizer_cov_trace_switch+0x58/0xb0
+ ? mas_next_slot+0x1e5b/0x2f40
+ ? __sanitizer_cov_trace_cmp8+0x18/0x30
+ ? unmapped_area_topdown+0x4dd/0x610
+ ? kfree+0x1b1/0x440
+ ? free_cpumask_var+0x16/0x30
+ ? __kasan_slab_free+0x7d/0xa0
+ ? __sanitizer_cov_trace_cmp8+0x18/0x30
+ mmap_region+0x2e6/0x3c0
+ do_mmap+0xa3e/0x12a0
+ ? __pfx_do_mmap+0x10/0x10
+ ? __kasan_check_write+0x14/0x30
+ ? down_write_killable+0xba/0x160
+ ? __pfx_down_write_killable+0x10/0x10
+ ? __sanitizer_cov_trace_cmp4+0x16/0x30
+ vm_mmap_pgoff+0x2d4/0x4a0
+ ? __pfx_vm_mmap_pgoff+0x10/0x10
+ ? fget+0x1bf/0x270
+ ksys_mmap_pgoff+0x40c/0x690
+ ? __sanitizer_cov_trace_const_cmp4+0x16/0x30
+ ? __pfx_ksys_mmap_pgoff+0x10/0x10
+ ? __kasan_check_write+0x14/0x30
+ ? _raw_spin_trylock+0xbb/0x130
+ ? __pfx__raw_spin_trylock+0x10/0x10
+ __x64_sys_mmap+0x135/0x1e0
+ x64_sys_call+0x1c14/0x2790
+ do_syscall_64+0xd2/0x1050
+ ? rcu_core+0x352/0x7d0
+ ? rcu_core_si+0xe/0x20
+ ? handle_softirqs+0x1aa/0x650
+ ? __sanitizer_cov_trace_cmp4+0x16/0x30
+ ? fpregs_assert_state_consistent+0xe1/0x160
+ ? irqentry_exit+0xb1/0x670
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Link: https://patch.msgid.link/r/20260515002537.6209-1-yanjun.zhu@linux.dev
+Reported-and-tested-by: nasm <n4sm@protonmail.com>
+Suggested-by: nasm <n4sm@protonmail.com>
+Fixes: 8700e3e7c485 ("Soft RoCE driver")
+Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+(cherry picked from commit 35744ab3d03c5fca8c1752f53fc8fc674e14c561)
+[Harshit: Minor conflict resolution pr_err() vs rxe_dbg_dev() usage]
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/sw/rxe/rxe_mmap.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/sw/rxe/rxe_mmap.c b/drivers/infiniband/sw/rxe/rxe_mmap.c
+index 035f226af1336..edd9345da295c 100644
+--- a/drivers/infiniband/sw/rxe/rxe_mmap.c
++++ b/drivers/infiniband/sw/rxe/rxe_mmap.c
+@@ -94,18 +94,31 @@ int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ goto done;
+
+ found_it:
++ /*
++ * Increment refcount and check whether it is being freed atm while
++ * holding lock to prevent UAF
++ */
++ if (!kref_get_unless_zero(&ip->ref)) {
++ spin_unlock_bh(&rxe->pending_lock);
++ ret = -ENXIO;
++ goto done;
++ }
++
+ list_del_init(&ip->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock);
+
++ vma->vm_ops = &rxe_vm_ops;
++ vma->vm_private_data = ip;
++
+ ret = remap_vmalloc_range(vma, ip->obj, 0);
+ if (ret) {
++ vma->vm_private_data = NULL;
++ vma->vm_ops = NULL;
++ kref_put(&ip->ref, rxe_mmap_release);
+ pr_err("err %d from remap_vmalloc_range\n", ret);
+ goto done;
+ }
+
+- vma->vm_ops = &rxe_vm_ops;
+- vma->vm_private_data = ip;
+- rxe_vma_open(vma);
+ done:
+ return ret;
+ }
+--
+2.53.0
+
bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch
ima-fix-out-of-bounds-read-in-xattr_verify.patch
futex-prevent-robust-futex-exit-race-some-more.patch
+rdma-rxe-fix-a-use-after-free-problem-in-rxe_mmap.patch
+mips-sched-fix-cpumask_offstack-memory-corruption.patch
+fscrypt-replace-mk_users-keyring-with-simple-list.patch
--- /dev/null
+From 61d4250cea229fc032210fc00b1252bba6d0e98e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Aug 2026 11:31:26 -0700
+Subject: fscrypt: Replace mk_users keyring with simple list
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit 696c030e1e3438955aba443b308ee8b6faa3983e upstream.
+
+Change mk_users (the set of user claims to an fscrypt master key) from a
+'struct key' keyring to a simple linked list.
+
+It's still a collection of 'struct key' for quota tracking. It was
+originally thought to be natural that a collection of 'struct key'
+should be held in a 'struct key' keyring. In reality, it's just been
+causing problems, similar to how using 'struct key' for the filesystem
+keyring caused problems and was removed in commit d7e7b9af104c
+("fscrypt: stop using keyrings subsystem for fscrypt_master_key").
+
+Commit d3a7bd420076 ("fscrypt: clear keyring before calling key_put()")
+fixed mk_users cleanup to be synchronous. But that apparently wasn't
+enough: the keyring subsystem's redundant locking is still generating
+lockdep false positives due to the interaction with filesystem reclaim.
+
+With the simple list, the redundant locking and lockdep issue goes away.
+
+Of course, searching a linked list is linear-time whereas the
+'struct key' keyring used a fancy constant-time associative array. But
+that's fine here, since in practice there's just one entry in the list.
+In fact the new code is much faster in practice, since it's much smaller
+and doesn't have to convert the kuid_t into a string to search for it.
+
+Reported-by: syzbot+f55b043dacf43776b50c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f55b043dacf43776b50c
+Reported-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
+Closes: https://lore.kernel.org/keyrings/20260614150041.21172-1-med08elkadiri@gmail.com/
+Fixes: 23c688b54016 ("fscrypt: allow unprivileged users to add/remove keys for v2 policies")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260618221921.87896-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/crypto/fscrypt_private.h | 32 ++++--
+ fs/crypto/keyring.c | 212 ++++++++++++++++--------------------
+ 2 files changed, 113 insertions(+), 131 deletions(-)
+
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+index 373c434b375c0..555d942342ccc 100644
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -402,6 +402,19 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
+
+ /* keyring.c */
+
++/*
++ * fscrypt_master_key_user - a user's claim to a master key
++ */
++struct fscrypt_master_key_user {
++ struct list_head link;
++ kuid_t uid;
++ /*
++ * This 'struct key' contains no secret. It exists solely to charge the
++ * appropriate user's key quota.
++ */
++ struct key *quota_key;
++};
++
+ /*
+ * fscrypt_master_key_secret - secret key material of an in-use master key
+ */
+@@ -488,19 +501,18 @@ struct fscrypt_master_key {
+ struct fscrypt_key_specifier mk_spec;
+
+ /*
+- * Keyring which contains a key of type 'key_type_fscrypt_user' for each
+- * user who has added this key. Normally each key will be added by just
+- * one user, but it's possible that multiple users share a key, and in
+- * that case we need to keep track of those users so that one user can't
+- * remove the key before the others want it removed too.
++ * List of user claims to this key (struct fscrypt_master_key_user).
++ * Normally each key will be added by just one user, but it's possible
++ * that multiple users share a key, and in that case we need to keep
++ * track of those users so that one user can't remove the key before the
++ * others want it removed too.
+ *
+- * This is NULL for v1 policy keys; those can only be added by root.
++ * Used only for v2 policy keys. v1 policy keys can be added only by
++ * root, so user tracking doesn't apply to them.
+ *
+- * 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.)
++ * Locking: protected by ->mk_sem.
+ */
+- struct key *mk_users;
++ struct list_head mk_users;
+
+ /*
+ * List of inodes that were unlocked using this key. This allows the
+diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
+index 02f8bf8bd54da..51cd45785f0c9 100644
+--- a/fs/crypto/keyring.c
++++ b/fs/crypto/keyring.c
+@@ -64,18 +64,19 @@ static void fscrypt_free_master_key(struct rcu_head *head)
+ kfree_sensitive(mk);
+ }
+
++static void clear_mk_users(struct fscrypt_master_key *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
++ * No structural references left, so clear ->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;
++ clear_mk_users(mk);
+ call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
+ }
+
+@@ -141,8 +142,8 @@ static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m)
+ }
+
+ /*
+- * Type of key in ->mk_users. Each key of this type represents a particular
+- * user who has added a particular master key.
++ * Type of fscrypt_master_key_user::quota_key. This contains no secret; it
++ * exists solely to charge a user's key quota.
+ *
+ * Note that the name of this key type really should be something like
+ * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen
+@@ -156,30 +157,9 @@ static struct key_type key_type_fscrypt_user = {
+ .describe = fscrypt_user_key_describe,
+ };
+
+-#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \
+- (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
+- CONST_STRLEN("-users") + 1)
+-
+ #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \
+ (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
+
+-static void format_mk_users_keyring_description(
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+- sprintf(description, "fscrypt-%*phN-users",
+- FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier);
+-}
+-
+-static void format_mk_user_description(
+- char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+-
+- sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE,
+- mk_identifier, __kuid_val(current_fsuid()));
+-}
+-
+ /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */
+ static int allocate_filesystem_keyring(struct super_block *sb)
+ {
+@@ -318,91 +298,94 @@ fscrypt_find_master_key(struct super_block *sb,
+ return mk;
+ }
+
+-static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
++/* Find the current user's claim in ->mk_users. ->mk_sem must be held. */
++static struct fscrypt_master_key_user *
++find_master_key_user(struct fscrypt_master_key *mk)
+ {
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE];
+- struct key *keyring;
+-
+- format_mk_users_keyring_description(description,
+- mk->mk_spec.u.identifier);
+- 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);
+-
+- mk->mk_users = keyring;
+- return 0;
+-}
++ struct fscrypt_master_key_user *mk_user;
++ kuid_t uid = current_fsuid();
+
+-/*
+- * Find the current user's "key" in the master key's ->mk_users.
+- * Returns ERR_PTR(-ENOKEY) if not found.
+- */
+-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);
+-
+- /*
+- * 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);
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ if (uid_eq(mk_user->uid, uid))
++ return mk_user;
+ }
+- return key_ref_to_ptr(keyref);
++ return NULL;
+ }
+
+ /*
+- * Give the current user a "key" in ->mk_users. This charges the user's quota
++ * Give the current user a claim 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 ->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)
+ {
++ kuid_t uid = current_fsuid();
+ char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
+- struct key *mk_user;
++ struct key *quota_key;
++ struct fscrypt_master_key_user *mk_user;
+ int err;
+
+- format_mk_user_description(description, mk->mk_spec.u.identifier);
+- mk_user = key_alloc(&key_type_fscrypt_user, description,
+- current_fsuid(), current_gid(), current_cred(),
+- KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
++ snprintf(description, sizeof(description), "%*phN.uid.%u",
++ FSCRYPT_KEY_IDENTIFIER_SIZE, mk->mk_spec.u.identifier,
++ __kuid_val(uid));
++ quota_key = key_alloc(&key_type_fscrypt_user, description, uid,
++ current_gid(), current_cred(),
++ KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
++ if (IS_ERR(quota_key))
++ return PTR_ERR(quota_key);
++
++ err = key_instantiate_and_link(quota_key, NULL, 0, NULL, NULL);
++ if (err) {
++ key_put(quota_key);
++ return err;
++ }
+
+- err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL);
+- key_put(mk_user);
+- return err;
++ mk_user = kzalloc(sizeof(*mk_user), GFP_KERNEL);
++ if (!mk_user) {
++ key_put(quota_key);
++ return -ENOMEM;
++ }
++ mk_user->uid = uid;
++ mk_user->quota_key = quota_key;
++ list_add(&mk_user->link, &mk->mk_users);
++ return 0;
++}
++
++static void unlink_and_free_mk_user(struct fscrypt_master_key_user *mk_user)
++{
++ list_del(&mk_user->link);
++ key_put(mk_user->quota_key);
++ kfree(mk_user);
+ }
+
+ /*
+- * Remove the current user's "key" from ->mk_users.
++ * Remove the current user's claim from ->mk_users.
+ * ->mk_sem must be held for write.
+ *
+- * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
++ * Returns 0 if removed or -ENOKEY if not found.
+ */
+ static int remove_master_key_user(struct fscrypt_master_key *mk)
+ {
+- struct key *mk_user;
+- int err;
++ struct fscrypt_master_key_user *mk_user;
+
+ mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
+- err = key_unlink(mk->mk_users, mk_user);
+- key_put(mk_user);
+- return err;
++ if (!mk_user)
++ return -ENOKEY;
++ unlink_and_free_mk_user(mk_user);
++ return 0;
++}
++
++/*
++ * Clear ->mk_users. Either ->mk_sem must be held for write, or 'mk' must have
++ * no structural references left.
++ */
++static void clear_mk_users(struct fscrypt_master_key *mk)
++{
++ struct fscrypt_master_key_user *mk_user, *tmp;
++
++ list_for_each_entry_safe(mk_user, tmp, &mk->mk_users, link)
++ unlink_and_free_mk_user(mk_user);
+ }
+
+ /*
+@@ -426,13 +409,12 @@ static int add_new_master_key(struct super_block *sb,
+ refcount_set(&mk->mk_struct_refs, 1);
+ mk->mk_spec = *mk_spec;
+
++ INIT_LIST_HEAD(&mk->mk_users);
++
+ 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_put;
+ err = add_master_key_user(mk);
+ if (err)
+ goto out_put;
+@@ -460,19 +442,13 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
+ int err;
+
+ /*
+- * If the current user is already in ->mk_users, then there's nothing to
+- * do. Otherwise, we need to add the user to ->mk_users. (Neither is
+- * applicable for v1 policy keys, which have NULL ->mk_users.)
++ * For v2 policy keys (FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER): If the current
++ * user is already in ->mk_users, then there's nothing to do.
++ * Otherwise, add the user to ->mk_users.
+ */
+- if (mk->mk_users) {
+- 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);
++ if (mk->mk_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
++ if (find_master_key_user(mk) != NULL)
+ return 0;
+- }
+ err = add_master_key_user(mk);
+ if (err)
+ return err;
+@@ -787,7 +763,6 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ {
+ struct fscrypt_key_specifier mk_spec;
+ struct fscrypt_master_key *mk;
+- struct key *mk_user;
+ int err;
+
+ mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
+@@ -799,13 +774,10 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ goto out;
+ }
+ down_read(&mk->mk_sem);
+- mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user)) {
+- err = PTR_ERR(mk_user);
+- } else {
+- key_put(mk_user);
++ if (find_master_key_user(mk) != NULL)
+ err = 0;
+- }
++ else
++ err = -ENOKEY;
+ up_read(&mk->mk_sem);
+ fscrypt_put_master_key(mk);
+ out:
+@@ -998,16 +970,18 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ 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) {
+- if (all_users)
+- err = keyring_clear(mk->mk_users);
+- else
++ if (!list_empty(&mk->mk_users)) {
++ if (all_users) {
++ clear_mk_users(mk);
++ err = 0;
++ } else {
+ err = remove_master_key_user(mk);
++ }
+ if (err) {
+ up_write(&mk->mk_sem);
+ goto out_put_key;
+ }
+- if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
++ if (!list_empty(&mk->mk_users)) {
+ /*
+ * Other users have still added the key too. We removed
+ * the current user's claim to the key, but we still
+@@ -1095,6 +1069,8 @@ 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 fscrypt_master_key *mk;
++ kuid_t uid;
++ const struct fscrypt_master_key_user *mk_user;
+ int err;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+@@ -1127,19 +1103,13 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
+ }
+
+ arg.status = FSCRYPT_KEY_STATUS_PRESENT;
+- if (mk->mk_users) {
+- struct key *mk_user;
+
+- arg.user_count = mk->mk_users->keys.nr_leaves_on_tree;
+- mk_user = find_master_key_user(mk);
+- if (!IS_ERR(mk_user)) {
++ uid = current_fsuid();
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ arg.user_count++;
++ if (uid_eq(mk_user->uid, uid))
+ arg.status_flags |=
+ FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF;
+- key_put(mk_user);
+- } else if (mk_user != ERR_PTR(-ENOKEY)) {
+- err = PTR_ERR(mk_user);
+- goto out_release_key;
+- }
+ }
+ err = 0;
+ out_release_key:
+--
+2.53.0
+
--- /dev/null
+From 44d7d080a04bfcc2df9e77ab36fb59c0645bfd9b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Aug 2026 13:23:59 -0700
+Subject: RDMA/rxe: Fix a use-after-free problem in rxe_mmap
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhu Yanjun <yanjun.zhu@linux.dev>
+
+[ Upstream commit 35744ab3d03c5fca8c1752f53fc8fc674e14c561 ]
+
+rxe_mmap() removes a rxe_mmap_info struct from the pending_mmaps list
+and releases pending_lock while the struct's kref is still at 1:
+
+ list_del_init(&ip->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock); /* ref == 1, no lock held */
+ ret = remap_vmalloc_range(vma, ip->obj, 0); /* walks PTEs */
+ [...]
+ rxe_vma_open(vma); /* kref_get, ref → 2 */
+ remap_vmalloc_range_partial() walks PTEs without any lock.
+
+A concurrent DESTROY_CQ ioctl on another CPU calls:
+
+ kref_put(&q->ip->ref, rxe_mmap_release) /* ref 1→0 */
+ vfree(ip->obj) /* clears vmalloc PTEs mid-walk */
+ kfree(ip) /* frees rxe_mmap_info */
+
+This yields:
+
+ 1. Kernel crash, vmalloc_to_page() returns NULL when vfree wins the
+ per-PTE race -> vm_insert_page(NULL) → GPF in validate_page_before_insert
+
+ 2. Page UAF, vmalloc_to_page() reads a stale PTE before vfree clears
+ it. User VMA holds a PTE to a free'd page which might eventually get
+ reallocated later by vmalloc which allows the attacker to get a clean
+ page-level UAF.
+
+ It is worth noting that even though a page-level UAF is possible given
+ the strong primitive, it is statistically very difficult to achieve
+ given the very short time window (after the last insert_page and before
+ the kref_get).
+
+The call trace are as below:
+
+ Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI
+ KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
+ CPU: 0 UID: 1000 PID: 413 Comm: poc Not tainted 7.0.0-rc5-dirty #28 PREEMPT(lazy)
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+ RIP: 0010:validate_page_before_insert+0x32/0x300
+ Code: e5 41 57 41 56 49 89 fe 41 55 41 54 53 48 89 f3 e8 93 b5 a3 ff 48 8d 7b 08 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 7b 02 00 00 4c 8b 63 08 31 ff 4d 89 e5 41 83 e5
+ RSP: 0018:ffff88811b15f2f0 EFLAGS: 00000202
+ RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
+ RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000000000000008
+ RBP: ffff88811b15f318 R08: 0000000000000000 R09: 0000000000000000
+ R10: 0000000000000000 R11: 0000000000000000 R12: ffff8881181eee00
+ R13: 0000000000000000 R14: ffff8881181eee00 R15: ffff8881181eee20
+ FS: 00007b1e000f76c0(0000) GS:ffff8884268e0000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007b1e00a24ac0 CR3: 0000000116eb3000 CR4: 00000000000006f0
+ Call Trace:
+ <TASK>
+ insert_page+0x8f/0x190
+ ? __pfx_insert_page+0x10/0x10
+ ? kasan_save_alloc_info+0x38/0x60
+ vm_insert_page+0x2e7/0x400
+ remap_vmalloc_range_partial+0x212/0x3e0
+ remap_vmalloc_range+0x6e/0xb0
+ ? __kasan_check_write+0x14/0x30
+ rxe_mmap+0x2e9/0x5d0
+ ib_uverbs_mmap+0x1ad/0x2c0
+ __mmap_region+0x12c2/0x2ad0
+ ? __pfx___mmap_region+0x10/0x10
+ ? __sanitizer_cov_trace_switch+0x58/0xb0
+ ? mas_prev_slot+0x360/0x39c0
+ ? __sanitizer_cov_trace_switch+0x58/0xb0
+ ? mas_next_slot+0x1e5b/0x2f40
+ ? __sanitizer_cov_trace_cmp8+0x18/0x30
+ ? unmapped_area_topdown+0x4dd/0x610
+ ? kfree+0x1b1/0x440
+ ? free_cpumask_var+0x16/0x30
+ ? __kasan_slab_free+0x7d/0xa0
+ ? __sanitizer_cov_trace_cmp8+0x18/0x30
+ mmap_region+0x2e6/0x3c0
+ do_mmap+0xa3e/0x12a0
+ ? __pfx_do_mmap+0x10/0x10
+ ? __kasan_check_write+0x14/0x30
+ ? down_write_killable+0xba/0x160
+ ? __pfx_down_write_killable+0x10/0x10
+ ? __sanitizer_cov_trace_cmp4+0x16/0x30
+ vm_mmap_pgoff+0x2d4/0x4a0
+ ? __pfx_vm_mmap_pgoff+0x10/0x10
+ ? fget+0x1bf/0x270
+ ksys_mmap_pgoff+0x40c/0x690
+ ? __sanitizer_cov_trace_const_cmp4+0x16/0x30
+ ? __pfx_ksys_mmap_pgoff+0x10/0x10
+ ? __kasan_check_write+0x14/0x30
+ ? _raw_spin_trylock+0xbb/0x130
+ ? __pfx__raw_spin_trylock+0x10/0x10
+ __x64_sys_mmap+0x135/0x1e0
+ x64_sys_call+0x1c14/0x2790
+ do_syscall_64+0xd2/0x1050
+ ? rcu_core+0x352/0x7d0
+ ? rcu_core_si+0xe/0x20
+ ? handle_softirqs+0x1aa/0x650
+ ? __sanitizer_cov_trace_cmp4+0x16/0x30
+ ? fpregs_assert_state_consistent+0xe1/0x160
+ ? irqentry_exit+0xb1/0x670
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Link: https://patch.msgid.link/r/20260515002537.6209-1-yanjun.zhu@linux.dev
+Reported-and-tested-by: nasm <n4sm@protonmail.com>
+Suggested-by: nasm <n4sm@protonmail.com>
+Fixes: 8700e3e7c485 ("Soft RoCE driver")
+Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+(cherry picked from commit 35744ab3d03c5fca8c1752f53fc8fc674e14c561)
+[Harshit: Minor conflict resolution pr_err() vs rxe_dbg_dev() usage]
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/sw/rxe/rxe_mmap.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/sw/rxe/rxe_mmap.c b/drivers/infiniband/sw/rxe/rxe_mmap.c
+index 035f226af1336..edd9345da295c 100644
+--- a/drivers/infiniband/sw/rxe/rxe_mmap.c
++++ b/drivers/infiniband/sw/rxe/rxe_mmap.c
+@@ -94,18 +94,31 @@ int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ goto done;
+
+ found_it:
++ /*
++ * Increment refcount and check whether it is being freed atm while
++ * holding lock to prevent UAF
++ */
++ if (!kref_get_unless_zero(&ip->ref)) {
++ spin_unlock_bh(&rxe->pending_lock);
++ ret = -ENXIO;
++ goto done;
++ }
++
+ list_del_init(&ip->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock);
+
++ vma->vm_ops = &rxe_vm_ops;
++ vma->vm_private_data = ip;
++
+ ret = remap_vmalloc_range(vma, ip->obj, 0);
+ if (ret) {
++ vma->vm_private_data = NULL;
++ vma->vm_ops = NULL;
++ kref_put(&ip->ref, rxe_mmap_release);
+ pr_err("err %d from remap_vmalloc_range\n", ret);
+ goto done;
+ }
+
+- vma->vm_ops = &rxe_vm_ops;
+- vma->vm_private_data = ip;
+- rxe_vma_open(vma);
+ done:
+ return ret;
+ }
+--
+2.53.0
+
bluetooth-6lowpan-fix-using-chan-conn-as-indication-.patch
futex-prevent-robust-futex-exit-race-some-more.patch
pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch
+rdma-rxe-fix-a-use-after-free-problem-in-rxe_mmap.patch
+fscrypt-replace-mk_users-keyring-with-simple-list.patch
--- /dev/null
+From 9c99f9f90ca8f04f0a4967fa642ac57e7eed3c59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Aug 2026 11:30:57 -0700
+Subject: fscrypt: Replace mk_users keyring with simple list
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit 696c030e1e3438955aba443b308ee8b6faa3983e upstream.
+
+Change mk_users (the set of user claims to an fscrypt master key) from a
+'struct key' keyring to a simple linked list.
+
+It's still a collection of 'struct key' for quota tracking. It was
+originally thought to be natural that a collection of 'struct key'
+should be held in a 'struct key' keyring. In reality, it's just been
+causing problems, similar to how using 'struct key' for the filesystem
+keyring caused problems and was removed in commit d7e7b9af104c
+("fscrypt: stop using keyrings subsystem for fscrypt_master_key").
+
+Commit d3a7bd420076 ("fscrypt: clear keyring before calling key_put()")
+fixed mk_users cleanup to be synchronous. But that apparently wasn't
+enough: the keyring subsystem's redundant locking is still generating
+lockdep false positives due to the interaction with filesystem reclaim.
+
+With the simple list, the redundant locking and lockdep issue goes away.
+
+Of course, searching a linked list is linear-time whereas the
+'struct key' keyring used a fancy constant-time associative array. But
+that's fine here, since in practice there's just one entry in the list.
+In fact the new code is much faster in practice, since it's much smaller
+and doesn't have to convert the kuid_t into a string to search for it.
+
+Reported-by: syzbot+f55b043dacf43776b50c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f55b043dacf43776b50c
+Reported-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
+Closes: https://lore.kernel.org/keyrings/20260614150041.21172-1-med08elkadiri@gmail.com/
+Fixes: 23c688b54016 ("fscrypt: allow unprivileged users to add/remove keys for v2 policies")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260618221921.87896-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/crypto/fscrypt_private.h | 32 ++++--
+ fs/crypto/keyring.c | 212 ++++++++++++++++--------------------
+ 2 files changed, 113 insertions(+), 131 deletions(-)
+
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+index 88414cbd97aee..aabc3a4751df7 100644
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -423,6 +423,19 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
+
+ /* keyring.c */
+
++/*
++ * fscrypt_master_key_user - a user's claim to a master key
++ */
++struct fscrypt_master_key_user {
++ struct list_head link;
++ kuid_t uid;
++ /*
++ * This 'struct key' contains no secret. It exists solely to charge the
++ * appropriate user's key quota.
++ */
++ struct key *quota_key;
++};
++
+ /*
+ * fscrypt_master_key_secret - secret key material of an in-use master key
+ */
+@@ -513,19 +526,18 @@ struct fscrypt_master_key {
+ struct fscrypt_key_specifier mk_spec;
+
+ /*
+- * Keyring which contains a key of type 'key_type_fscrypt_user' for each
+- * user who has added this key. Normally each key will be added by just
+- * one user, but it's possible that multiple users share a key, and in
+- * that case we need to keep track of those users so that one user can't
+- * remove the key before the others want it removed too.
++ * List of user claims to this key (struct fscrypt_master_key_user).
++ * Normally each key will be added by just one user, but it's possible
++ * that multiple users share a key, and in that case we need to keep
++ * track of those users so that one user can't remove the key before the
++ * others want it removed too.
+ *
+- * This is NULL for v1 policy keys; those can only be added by root.
++ * Used only for v2 policy keys. v1 policy keys can be added only by
++ * root, so user tracking doesn't apply to them.
+ *
+- * 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.)
++ * Locking: protected by ->mk_sem.
+ */
+- struct key *mk_users;
++ struct list_head mk_users;
+
+ /*
+ * List of inodes that were unlocked using this key. This allows the
+diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
+index 2a24b1f0ae688..e1cce06f43439 100644
+--- a/fs/crypto/keyring.c
++++ b/fs/crypto/keyring.c
+@@ -64,18 +64,19 @@ static void fscrypt_free_master_key(struct rcu_head *head)
+ kfree_sensitive(mk);
+ }
+
++static void clear_mk_users(struct fscrypt_master_key *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
++ * No structural references left, so clear ->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;
++ clear_mk_users(mk);
+ call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
+ }
+
+@@ -144,8 +145,8 @@ static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m)
+ }
+
+ /*
+- * Type of key in ->mk_users. Each key of this type represents a particular
+- * user who has added a particular master key.
++ * Type of fscrypt_master_key_user::quota_key. This contains no secret; it
++ * exists solely to charge a user's key quota.
+ *
+ * Note that the name of this key type really should be something like
+ * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen
+@@ -159,30 +160,9 @@ static struct key_type key_type_fscrypt_user = {
+ .describe = fscrypt_user_key_describe,
+ };
+
+-#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \
+- (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
+- CONST_STRLEN("-users") + 1)
+-
+ #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \
+ (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
+
+-static void format_mk_users_keyring_description(
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+- sprintf(description, "fscrypt-%*phN-users",
+- FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier);
+-}
+-
+-static void format_mk_user_description(
+- char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+-
+- sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE,
+- mk_identifier, __kuid_val(current_fsuid()));
+-}
+-
+ /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */
+ static int allocate_filesystem_keyring(struct super_block *sb)
+ {
+@@ -321,91 +301,94 @@ fscrypt_find_master_key(struct super_block *sb,
+ return mk;
+ }
+
+-static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
++/* Find the current user's claim in ->mk_users. ->mk_sem must be held. */
++static struct fscrypt_master_key_user *
++find_master_key_user(struct fscrypt_master_key *mk)
+ {
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE];
+- struct key *keyring;
+-
+- format_mk_users_keyring_description(description,
+- mk->mk_spec.u.identifier);
+- 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);
+-
+- mk->mk_users = keyring;
+- return 0;
+-}
++ struct fscrypt_master_key_user *mk_user;
++ kuid_t uid = current_fsuid();
+
+-/*
+- * Find the current user's "key" in the master key's ->mk_users.
+- * Returns ERR_PTR(-ENOKEY) if not found.
+- */
+-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);
+-
+- /*
+- * 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);
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ if (uid_eq(mk_user->uid, uid))
++ return mk_user;
+ }
+- return key_ref_to_ptr(keyref);
++ return NULL;
+ }
+
+ /*
+- * Give the current user a "key" in ->mk_users. This charges the user's quota
++ * Give the current user a claim 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 ->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)
+ {
++ kuid_t uid = current_fsuid();
+ char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
+- struct key *mk_user;
++ struct key *quota_key;
++ struct fscrypt_master_key_user *mk_user;
+ int err;
+
+- format_mk_user_description(description, mk->mk_spec.u.identifier);
+- mk_user = key_alloc(&key_type_fscrypt_user, description,
+- current_fsuid(), current_gid(), current_cred(),
+- KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
++ snprintf(description, sizeof(description), "%*phN.uid.%u",
++ FSCRYPT_KEY_IDENTIFIER_SIZE, mk->mk_spec.u.identifier,
++ __kuid_val(uid));
++ quota_key = key_alloc(&key_type_fscrypt_user, description, uid,
++ current_gid(), current_cred(),
++ KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
++ if (IS_ERR(quota_key))
++ return PTR_ERR(quota_key);
++
++ err = key_instantiate_and_link(quota_key, NULL, 0, NULL, NULL);
++ if (err) {
++ key_put(quota_key);
++ return err;
++ }
+
+- err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL);
+- key_put(mk_user);
+- return err;
++ mk_user = kzalloc(sizeof(*mk_user), GFP_KERNEL);
++ if (!mk_user) {
++ key_put(quota_key);
++ return -ENOMEM;
++ }
++ mk_user->uid = uid;
++ mk_user->quota_key = quota_key;
++ list_add(&mk_user->link, &mk->mk_users);
++ return 0;
++}
++
++static void unlink_and_free_mk_user(struct fscrypt_master_key_user *mk_user)
++{
++ list_del(&mk_user->link);
++ key_put(mk_user->quota_key);
++ kfree(mk_user);
+ }
+
+ /*
+- * Remove the current user's "key" from ->mk_users.
++ * Remove the current user's claim from ->mk_users.
+ * ->mk_sem must be held for write.
+ *
+- * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
++ * Returns 0 if removed or -ENOKEY if not found.
+ */
+ static int remove_master_key_user(struct fscrypt_master_key *mk)
+ {
+- struct key *mk_user;
+- int err;
++ struct fscrypt_master_key_user *mk_user;
+
+ mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
+- err = key_unlink(mk->mk_users, mk_user);
+- key_put(mk_user);
+- return err;
++ if (!mk_user)
++ return -ENOKEY;
++ unlink_and_free_mk_user(mk_user);
++ return 0;
++}
++
++/*
++ * Clear ->mk_users. Either ->mk_sem must be held for write, or 'mk' must have
++ * no structural references left.
++ */
++static void clear_mk_users(struct fscrypt_master_key *mk)
++{
++ struct fscrypt_master_key_user *mk_user, *tmp;
++
++ list_for_each_entry_safe(mk_user, tmp, &mk->mk_users, link)
++ unlink_and_free_mk_user(mk_user);
+ }
+
+ /*
+@@ -429,13 +412,12 @@ static int add_new_master_key(struct super_block *sb,
+ refcount_set(&mk->mk_struct_refs, 1);
+ mk->mk_spec = *mk_spec;
+
++ INIT_LIST_HEAD(&mk->mk_users);
++
+ 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_put;
+ err = add_master_key_user(mk);
+ if (err)
+ goto out_put;
+@@ -463,19 +445,13 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
+ int err;
+
+ /*
+- * If the current user is already in ->mk_users, then there's nothing to
+- * do. Otherwise, we need to add the user to ->mk_users. (Neither is
+- * applicable for v1 policy keys, which have NULL ->mk_users.)
++ * For v2 policy keys (FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER): If the current
++ * user is already in ->mk_users, then there's nothing to do.
++ * Otherwise, add the user to ->mk_users.
+ */
+- if (mk->mk_users) {
+- 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);
++ if (mk->mk_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
++ if (find_master_key_user(mk) != NULL)
+ return 0;
+- }
+ err = add_master_key_user(mk);
+ if (err)
+ return err;
+@@ -830,7 +806,6 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ {
+ struct fscrypt_key_specifier mk_spec;
+ struct fscrypt_master_key *mk;
+- struct key *mk_user;
+ int err;
+
+ mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
+@@ -842,13 +817,10 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ goto out;
+ }
+ down_read(&mk->mk_sem);
+- mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user)) {
+- err = PTR_ERR(mk_user);
+- } else {
+- key_put(mk_user);
++ if (find_master_key_user(mk) != NULL)
+ err = 0;
+- }
++ else
++ err = -ENOKEY;
+ up_read(&mk->mk_sem);
+ fscrypt_put_master_key(mk);
+ out:
+@@ -1041,16 +1013,18 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ 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) {
+- if (all_users)
+- err = keyring_clear(mk->mk_users);
+- else
++ if (!list_empty(&mk->mk_users)) {
++ if (all_users) {
++ clear_mk_users(mk);
++ err = 0;
++ } else {
+ err = remove_master_key_user(mk);
++ }
+ if (err) {
+ up_write(&mk->mk_sem);
+ goto out_put_key;
+ }
+- if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
++ if (!list_empty(&mk->mk_users)) {
+ /*
+ * Other users have still added the key too. We removed
+ * the current user's claim to the key, but we still
+@@ -1138,6 +1112,8 @@ 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 fscrypt_master_key *mk;
++ kuid_t uid;
++ const struct fscrypt_master_key_user *mk_user;
+ int err;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+@@ -1170,19 +1146,13 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
+ }
+
+ arg.status = FSCRYPT_KEY_STATUS_PRESENT;
+- if (mk->mk_users) {
+- struct key *mk_user;
+
+- arg.user_count = mk->mk_users->keys.nr_leaves_on_tree;
+- mk_user = find_master_key_user(mk);
+- if (!IS_ERR(mk_user)) {
++ uid = current_fsuid();
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ arg.user_count++;
++ if (uid_eq(mk_user->uid, uid))
+ arg.status_flags |=
+ FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF;
+- key_put(mk_user);
+- } else if (mk_user != ERR_PTR(-ENOKEY)) {
+- err = PTR_ERR(mk_user);
+- goto out_release_key;
+- }
+ }
+ err = 0;
+ out_release_key:
+--
+2.53.0
+
--- /dev/null
+From 6d97b8d82a84c782b3e17770ce2f8e006b31c9e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Aug 2026 13:23:59 -0700
+Subject: RDMA/rxe: Fix a use-after-free problem in rxe_mmap
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhu Yanjun <yanjun.zhu@linux.dev>
+
+[ Upstream commit 35744ab3d03c5fca8c1752f53fc8fc674e14c561 ]
+
+rxe_mmap() removes a rxe_mmap_info struct from the pending_mmaps list
+and releases pending_lock while the struct's kref is still at 1:
+
+ list_del_init(&ip->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock); /* ref == 1, no lock held */
+ ret = remap_vmalloc_range(vma, ip->obj, 0); /* walks PTEs */
+ [...]
+ rxe_vma_open(vma); /* kref_get, ref → 2 */
+ remap_vmalloc_range_partial() walks PTEs without any lock.
+
+A concurrent DESTROY_CQ ioctl on another CPU calls:
+
+ kref_put(&q->ip->ref, rxe_mmap_release) /* ref 1→0 */
+ vfree(ip->obj) /* clears vmalloc PTEs mid-walk */
+ kfree(ip) /* frees rxe_mmap_info */
+
+This yields:
+
+ 1. Kernel crash, vmalloc_to_page() returns NULL when vfree wins the
+ per-PTE race -> vm_insert_page(NULL) → GPF in validate_page_before_insert
+
+ 2. Page UAF, vmalloc_to_page() reads a stale PTE before vfree clears
+ it. User VMA holds a PTE to a free'd page which might eventually get
+ reallocated later by vmalloc which allows the attacker to get a clean
+ page-level UAF.
+
+ It is worth noting that even though a page-level UAF is possible given
+ the strong primitive, it is statistically very difficult to achieve
+ given the very short time window (after the last insert_page and before
+ the kref_get).
+
+The call trace are as below:
+
+ Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI
+ KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
+ CPU: 0 UID: 1000 PID: 413 Comm: poc Not tainted 7.0.0-rc5-dirty #28 PREEMPT(lazy)
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+ RIP: 0010:validate_page_before_insert+0x32/0x300
+ Code: e5 41 57 41 56 49 89 fe 41 55 41 54 53 48 89 f3 e8 93 b5 a3 ff 48 8d 7b 08 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 7b 02 00 00 4c 8b 63 08 31 ff 4d 89 e5 41 83 e5
+ RSP: 0018:ffff88811b15f2f0 EFLAGS: 00000202
+ RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
+ RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000000000000008
+ RBP: ffff88811b15f318 R08: 0000000000000000 R09: 0000000000000000
+ R10: 0000000000000000 R11: 0000000000000000 R12: ffff8881181eee00
+ R13: 0000000000000000 R14: ffff8881181eee00 R15: ffff8881181eee20
+ FS: 00007b1e000f76c0(0000) GS:ffff8884268e0000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007b1e00a24ac0 CR3: 0000000116eb3000 CR4: 00000000000006f0
+ Call Trace:
+ <TASK>
+ insert_page+0x8f/0x190
+ ? __pfx_insert_page+0x10/0x10
+ ? kasan_save_alloc_info+0x38/0x60
+ vm_insert_page+0x2e7/0x400
+ remap_vmalloc_range_partial+0x212/0x3e0
+ remap_vmalloc_range+0x6e/0xb0
+ ? __kasan_check_write+0x14/0x30
+ rxe_mmap+0x2e9/0x5d0
+ ib_uverbs_mmap+0x1ad/0x2c0
+ __mmap_region+0x12c2/0x2ad0
+ ? __pfx___mmap_region+0x10/0x10
+ ? __sanitizer_cov_trace_switch+0x58/0xb0
+ ? mas_prev_slot+0x360/0x39c0
+ ? __sanitizer_cov_trace_switch+0x58/0xb0
+ ? mas_next_slot+0x1e5b/0x2f40
+ ? __sanitizer_cov_trace_cmp8+0x18/0x30
+ ? unmapped_area_topdown+0x4dd/0x610
+ ? kfree+0x1b1/0x440
+ ? free_cpumask_var+0x16/0x30
+ ? __kasan_slab_free+0x7d/0xa0
+ ? __sanitizer_cov_trace_cmp8+0x18/0x30
+ mmap_region+0x2e6/0x3c0
+ do_mmap+0xa3e/0x12a0
+ ? __pfx_do_mmap+0x10/0x10
+ ? __kasan_check_write+0x14/0x30
+ ? down_write_killable+0xba/0x160
+ ? __pfx_down_write_killable+0x10/0x10
+ ? __sanitizer_cov_trace_cmp4+0x16/0x30
+ vm_mmap_pgoff+0x2d4/0x4a0
+ ? __pfx_vm_mmap_pgoff+0x10/0x10
+ ? fget+0x1bf/0x270
+ ksys_mmap_pgoff+0x40c/0x690
+ ? __sanitizer_cov_trace_const_cmp4+0x16/0x30
+ ? __pfx_ksys_mmap_pgoff+0x10/0x10
+ ? __kasan_check_write+0x14/0x30
+ ? _raw_spin_trylock+0xbb/0x130
+ ? __pfx__raw_spin_trylock+0x10/0x10
+ __x64_sys_mmap+0x135/0x1e0
+ x64_sys_call+0x1c14/0x2790
+ do_syscall_64+0xd2/0x1050
+ ? rcu_core+0x352/0x7d0
+ ? rcu_core_si+0xe/0x20
+ ? handle_softirqs+0x1aa/0x650
+ ? __sanitizer_cov_trace_cmp4+0x16/0x30
+ ? fpregs_assert_state_consistent+0xe1/0x160
+ ? irqentry_exit+0xb1/0x670
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Link: https://patch.msgid.link/r/20260515002537.6209-1-yanjun.zhu@linux.dev
+Reported-and-tested-by: nasm <n4sm@protonmail.com>
+Suggested-by: nasm <n4sm@protonmail.com>
+Fixes: 8700e3e7c485 ("Soft RoCE driver")
+Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+(cherry picked from commit 35744ab3d03c5fca8c1752f53fc8fc674e14c561)
+[Harshit: Minor conflict resolution pr_err() vs rxe_dbg_dev() usage]
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/sw/rxe/rxe_mmap.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/sw/rxe/rxe_mmap.c b/drivers/infiniband/sw/rxe/rxe_mmap.c
+index 9149b60954296..2749ed48b014a 100644
+--- a/drivers/infiniband/sw/rxe/rxe_mmap.c
++++ b/drivers/infiniband/sw/rxe/rxe_mmap.c
+@@ -93,18 +93,31 @@ int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ goto done;
+
+ found_it:
++ /*
++ * Increment refcount and check whether it is being freed atm while
++ * holding lock to prevent UAF
++ */
++ if (!kref_get_unless_zero(&ip->ref)) {
++ spin_unlock_bh(&rxe->pending_lock);
++ ret = -ENXIO;
++ goto done;
++ }
++
+ list_del_init(&ip->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock);
+
++ vma->vm_ops = &rxe_vm_ops;
++ vma->vm_private_data = ip;
++
+ ret = remap_vmalloc_range(vma, ip->obj, 0);
+ if (ret) {
++ vma->vm_private_data = NULL;
++ vma->vm_ops = NULL;
++ kref_put(&ip->ref, rxe_mmap_release);
+ pr_err("err %d from remap_vmalloc_range\n", ret);
+ goto done;
+ }
+
+- vma->vm_ops = &rxe_vm_ops;
+- vma->vm_private_data = ip;
+- rxe_vma_open(vma);
+ done:
+ return ret;
+ }
+--
+2.53.0
+
--- /dev/null
+From 676d49ec011c70b9563b0054f0aa2db2747761ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jul 2026 06:23:58 +0200
+Subject: selftests/bpf: Adapt sockmap update error handling
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 30581eda4a07ff15db623612cac578e81869e96f ]
+
+Update sockmap_listen to accommodate the recent change in sockmap that
+rejects unbound UDP sockets.
+
+TCP: Reject unbound and bound (unless established or listening).
+UDP: Accept only bound sockets.
+
+While at it, migrate to ASSERT_* and enforce reverse xmas tree.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-3-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/sockmap_listen.c | 21 ++++++++++---------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+index cef5d35951711..2112b01a4b03a 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+@@ -341,8 +341,8 @@ static void test_insert_invalid(int family, int sotype, int mapfd)
+ static void test_insert_opened(int family, int sotype, int mapfd)
+ {
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ s = xsocket(family, sotype, 0);
+ if (s == -1)
+@@ -351,11 +351,8 @@ static void test_insert_opened(int family, int sotype, int mapfd)
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (sotype == SOCK_STREAM) {
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
+- } else if (err)
+- FAIL_ERRNO("map_update: expected success");
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
+ xclose(s);
+ }
+
+@@ -364,8 +361,8 @@ static void test_insert_bound(int family, int sotype, int mapfd)
+ struct sockaddr_storage addr;
+ socklen_t len;
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ init_addr_loopback(family, &addr, &len);
+
+@@ -380,8 +377,12 @@ static void test_insert_bound(int family, int sotype, int mapfd)
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
++ if (sotype == SOCK_STREAM) {
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
++ } else {
++ ASSERT_OK(err, "map_update");
++ }
+ close:
+ xclose(s);
+ }
+@@ -1480,7 +1481,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
+ /* insert */
+ TEST(test_insert_invalid),
+ TEST(test_insert_opened),
+- TEST(test_insert_bound, SOCK_STREAM),
++ TEST(test_insert_bound),
+ TEST(test_insert),
+ /* delete */
+ TEST(test_delete_after_insert),
+--
+2.53.0
+
--- /dev/null
+From f792f83a4123bfa0cbc617b53ac85f5ee56f64e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jul 2026 06:23:59 +0200
+Subject: selftests/bpf: Fail unbound UDP on sockmap update
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 203b06932777b9ad5085319389dea566f5c2ca63 ]
+
+sockmap now rejects unbound UDP sockets. Adjust test_maps. While at it,
+check socket()'s return value.
+
+This effectively reverts commit c39aa2159974 ("bpf, selftests: Fix
+test_maps now that sockmap supports UDP").
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-4-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/test_maps.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
+index 81cd48cc80c23..73878ec8ec7d0 100644
+--- a/tools/testing/selftests/bpf/test_maps.c
++++ b/tools/testing/selftests/bpf/test_maps.c
+@@ -752,16 +752,15 @@ static void test_sockmap(unsigned int tasks, void *data)
+ goto out_sockmap;
+ }
+
+- /* Test update with unsupported UDP socket */
++ /* Test update with unsupported unbound UDP socket */
+ udp = socket(AF_INET, SOCK_DGRAM, 0);
+- i = 0;
+- err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
+- if (err) {
+- printf("Failed socket update SOCK_DGRAM '%i:%i'\n",
+- i, udp);
++ CHECK(udp < 0, "socket(AF_INET, SOCK_DGRAM)", "errno:%d\n", errno);
++ err = bpf_map_update_elem(fd, &(int){0}, &udp, BPF_ANY);
++ close(udp);
++ if (!err) {
++ printf("Unexpectedly succeeded unbound UDP update '0:%i'\n", udp);
+ goto out_sockmap;
+ }
+- close(udp);
+
+ /* Test update without programs */
+ for (i = 0; i < 6; i++) {
+--
+2.53.0
+
fortify-refactor-test_fortify-makefile-to-fix-some-b.patch
fortify-disable-wstringop-overread-in-tests.patch
pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch
+rdma-rxe-fix-a-use-after-free-problem-in-rxe_mmap.patch
+fscrypt-replace-mk_users-keyring-with-simple-list.patch
+selftests-bpf-adapt-sockmap-update-error-handling.patch
+selftests-bpf-fail-unbound-udp-on-sockmap-update.patch
--- /dev/null
+From de5a0c4a4ae0202b97eba7018dba6fbb67a21b54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jul 2026 06:23:58 +0200
+Subject: selftests/bpf: Adapt sockmap update error handling
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 30581eda4a07ff15db623612cac578e81869e96f ]
+
+Update sockmap_listen to accommodate the recent change in sockmap that
+rejects unbound UDP sockets.
+
+TCP: Reject unbound and bound (unless established or listening).
+UDP: Accept only bound sockets.
+
+While at it, migrate to ASSERT_* and enforce reverse xmas tree.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-3-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/sockmap_listen.c | 21 ++++++++++---------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+index 1cfed83156b03..b04b8188b1514 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+@@ -53,8 +53,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ int family, int sotype, int mapfd)
+ {
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ s = xsocket(family, sotype, 0);
+ if (s == -1)
+@@ -63,11 +63,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (sotype == SOCK_STREAM) {
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
+- } else if (err)
+- FAIL_ERRNO("map_update: expected success");
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
+ xclose(s);
+ }
+
+@@ -77,8 +74,8 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ struct sockaddr_storage addr;
+ socklen_t len = 0;
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ init_addr_loopback(family, &addr, &len);
+
+@@ -93,8 +90,12 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
++ if (sotype == SOCK_STREAM) {
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
++ } else {
++ ASSERT_OK(err, "map_update");
++ }
+ close:
+ xclose(s);
+ }
+@@ -1289,7 +1290,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
+ /* insert */
+ TEST(test_insert_invalid),
+ TEST(test_insert_opened),
+- TEST(test_insert_bound, SOCK_STREAM),
++ TEST(test_insert_bound),
+ TEST(test_insert),
+ /* delete */
+ TEST(test_delete_after_insert),
+--
+2.53.0
+
--- /dev/null
+From 8cf293a8d6d96dd7fc12163be0dbe030c70bc9b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jul 2026 06:23:56 +0200
+Subject: selftests/bpf: Ensure UDP sockets are bound
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit fe3ff273767ef22fe8a7cb3816f264927c190e50 ]
+
+Update sockmap_basic tests to bind sockets before they are used. This
+accommodates the recent change in sockmap that rejects unbound UDP sockets.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-1-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/prog_tests/sockmap_basic.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+index fb08c565d6aad..99522cf68dc8c 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+@@ -703,7 +703,7 @@ static void test_sockmap_many_socket(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+@@ -772,7 +772,7 @@ static void test_sockmap_many_maps(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+@@ -843,7 +843,7 @@ static void test_sockmap_same_sock(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+--
+2.53.0
+
kunit-fortify-replace-volatile-with-optimizer_hide_v.patch
kunit-fortify-add-back-volatile-for-sizeof-constants.patch
pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch
+selftests-bpf-ensure-udp-sockets-are-bound.patch
+selftests-bpf-adapt-sockmap-update-error-handling.patch
--- /dev/null
+From 2c63bc8380241946ff7004e8471ff29c29601cbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jul 2026 06:23:58 +0200
+Subject: selftests/bpf: Adapt sockmap update error handling
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 30581eda4a07ff15db623612cac578e81869e96f ]
+
+Update sockmap_listen to accommodate the recent change in sockmap that
+rejects unbound UDP sockets.
+
+TCP: Reject unbound and bound (unless established or listening).
+UDP: Accept only bound sockets.
+
+While at it, migrate to ASSERT_* and enforce reverse xmas tree.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-3-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/sockmap_listen.c | 21 ++++++++++---------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+index f1bdccc7e4e79..0a744f786e107 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+@@ -53,8 +53,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ int family, int sotype, int mapfd)
+ {
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ s = xsocket(family, sotype, 0);
+ if (s == -1)
+@@ -63,11 +63,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (sotype == SOCK_STREAM) {
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
+- } else if (err)
+- FAIL_ERRNO("map_update: expected success");
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
+ xclose(s);
+ }
+
+@@ -77,8 +74,8 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ struct sockaddr_storage addr;
+ socklen_t len = 0;
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ init_addr_loopback(family, &addr, &len);
+
+@@ -93,8 +90,12 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
++ if (sotype == SOCK_STREAM) {
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
++ } else {
++ ASSERT_OK(err, "map_update");
++ }
+ close:
+ xclose(s);
+ }
+@@ -1289,7 +1290,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
+ /* insert */
+ TEST(test_insert_invalid),
+ TEST(test_insert_opened),
+- TEST(test_insert_bound, SOCK_STREAM),
++ TEST(test_insert_bound),
+ TEST(test_insert),
+ /* delete */
+ TEST(test_delete_after_insert),
+--
+2.53.0
+
--- /dev/null
+From 55a1723b5c60cccdd2b3c8de351744d761684970 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jul 2026 06:23:56 +0200
+Subject: selftests/bpf: Ensure UDP sockets are bound
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit fe3ff273767ef22fe8a7cb3816f264927c190e50 ]
+
+Update sockmap_basic tests to bind sockets before they are used. This
+accommodates the recent change in sockmap that rejects unbound UDP sockets.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-1-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/prog_tests/sockmap_basic.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+index 1e3e4392dcca0..54fd84203dc2b 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+@@ -786,7 +786,7 @@ static void test_sockmap_many_socket(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+@@ -855,7 +855,7 @@ static void test_sockmap_many_maps(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+@@ -926,7 +926,7 @@ static void test_sockmap_same_sock(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+--
+2.53.0
+
netfilter-nf_tables-avoid-softlockup-warnings-in-nft.patch
bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch
bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch
+selftests-bpf-ensure-udp-sockets-are-bound.patch
+selftests-bpf-adapt-sockmap-update-error-handling.patch
--- /dev/null
+From 02d650b855a6ece429f82bf4893991155e53dff1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Aug 2026 11:30:36 -0700
+Subject: fscrypt: Replace mk_users keyring with simple list
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit 696c030e1e3438955aba443b308ee8b6faa3983e upstream.
+
+Change mk_users (the set of user claims to an fscrypt master key) from a
+'struct key' keyring to a simple linked list.
+
+It's still a collection of 'struct key' for quota tracking. It was
+originally thought to be natural that a collection of 'struct key'
+should be held in a 'struct key' keyring. In reality, it's just been
+causing problems, similar to how using 'struct key' for the filesystem
+keyring caused problems and was removed in commit d7e7b9af104c
+("fscrypt: stop using keyrings subsystem for fscrypt_master_key").
+
+Commit d3a7bd420076 ("fscrypt: clear keyring before calling key_put()")
+fixed mk_users cleanup to be synchronous. But that apparently wasn't
+enough: the keyring subsystem's redundant locking is still generating
+lockdep false positives due to the interaction with filesystem reclaim.
+
+With the simple list, the redundant locking and lockdep issue goes away.
+
+Of course, searching a linked list is linear-time whereas the
+'struct key' keyring used a fancy constant-time associative array. But
+that's fine here, since in practice there's just one entry in the list.
+In fact the new code is much faster in practice, since it's much smaller
+and doesn't have to convert the kuid_t into a string to search for it.
+
+Reported-by: syzbot+f55b043dacf43776b50c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f55b043dacf43776b50c
+Reported-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
+Closes: https://lore.kernel.org/keyrings/20260614150041.21172-1-med08elkadiri@gmail.com/
+Fixes: 23c688b54016 ("fscrypt: allow unprivileged users to add/remove keys for v2 policies")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260618221921.87896-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/crypto/fscrypt_private.h | 32 ++++--
+ fs/crypto/keyring.c | 212 ++++++++++++++++--------------------
+ 2 files changed, 113 insertions(+), 131 deletions(-)
+
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+index 14b26036055e4..8be25746fd72e 100644
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -422,6 +422,19 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
+
+ /* keyring.c */
+
++/*
++ * fscrypt_master_key_user - a user's claim to a master key
++ */
++struct fscrypt_master_key_user {
++ struct list_head link;
++ kuid_t uid;
++ /*
++ * This 'struct key' contains no secret. It exists solely to charge the
++ * appropriate user's key quota.
++ */
++ struct key *quota_key;
++};
++
+ /*
+ * fscrypt_master_key_secret - secret key material of an in-use master key
+ */
+@@ -506,19 +519,18 @@ struct fscrypt_master_key {
+ struct fscrypt_key_specifier mk_spec;
+
+ /*
+- * Keyring which contains a key of type 'key_type_fscrypt_user' for each
+- * user who has added this key. Normally each key will be added by just
+- * one user, but it's possible that multiple users share a key, and in
+- * that case we need to keep track of those users so that one user can't
+- * remove the key before the others want it removed too.
++ * List of user claims to this key (struct fscrypt_master_key_user).
++ * Normally each key will be added by just one user, but it's possible
++ * that multiple users share a key, and in that case we need to keep
++ * track of those users so that one user can't remove the key before the
++ * others want it removed too.
+ *
+- * This is NULL for v1 policy keys; those can only be added by root.
++ * Used only for v2 policy keys. v1 policy keys can be added only by
++ * root, so user tracking doesn't apply to them.
+ *
+- * 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.)
++ * Locking: protected by ->mk_sem.
+ */
+- struct key *mk_users;
++ struct list_head mk_users;
+
+ /*
+ * List of inodes that were unlocked using this key. This allows the
+diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
+index 7cbb1fd872acc..f2a0d89d5f5e1 100644
+--- a/fs/crypto/keyring.c
++++ b/fs/crypto/keyring.c
+@@ -64,18 +64,19 @@ static void fscrypt_free_master_key(struct rcu_head *head)
+ kfree_sensitive(mk);
+ }
+
++static void clear_mk_users(struct fscrypt_master_key *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
++ * No structural references left, so clear ->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_ONCE(refcount_read(&mk->mk_active_refs) != 0);
+- key_put(mk->mk_users);
+- mk->mk_users = NULL;
++ clear_mk_users(mk);
+ call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
+ }
+
+@@ -145,8 +146,8 @@ static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m)
+ }
+
+ /*
+- * Type of key in ->mk_users. Each key of this type represents a particular
+- * user who has added a particular master key.
++ * Type of fscrypt_master_key_user::quota_key. This contains no secret; it
++ * exists solely to charge a user's key quota.
+ *
+ * Note that the name of this key type really should be something like
+ * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen
+@@ -160,30 +161,9 @@ static struct key_type key_type_fscrypt_user = {
+ .describe = fscrypt_user_key_describe,
+ };
+
+-#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \
+- (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
+- CONST_STRLEN("-users") + 1)
+-
+ #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \
+ (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
+
+-static void format_mk_users_keyring_description(
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+- sprintf(description, "fscrypt-%*phN-users",
+- FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier);
+-}
+-
+-static void format_mk_user_description(
+- char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+-
+- sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE,
+- mk_identifier, __kuid_val(current_fsuid()));
+-}
+-
+ /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */
+ static int allocate_filesystem_keyring(struct super_block *sb)
+ {
+@@ -319,91 +299,94 @@ fscrypt_find_master_key(struct super_block *sb,
+ return mk;
+ }
+
+-static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
++/* Find the current user's claim in ->mk_users. ->mk_sem must be held. */
++static struct fscrypt_master_key_user *
++find_master_key_user(struct fscrypt_master_key *mk)
+ {
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE];
+- struct key *keyring;
+-
+- format_mk_users_keyring_description(description,
+- mk->mk_spec.u.identifier);
+- 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);
+-
+- mk->mk_users = keyring;
+- return 0;
+-}
++ struct fscrypt_master_key_user *mk_user;
++ kuid_t uid = current_fsuid();
+
+-/*
+- * Find the current user's "key" in the master key's ->mk_users.
+- * Returns ERR_PTR(-ENOKEY) if not found.
+- */
+-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);
+-
+- /*
+- * 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);
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ if (uid_eq(mk_user->uid, uid))
++ return mk_user;
+ }
+- return key_ref_to_ptr(keyref);
++ return NULL;
+ }
+
+ /*
+- * Give the current user a "key" in ->mk_users. This charges the user's quota
++ * Give the current user a claim 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 ->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)
+ {
++ kuid_t uid = current_fsuid();
+ char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
+- struct key *mk_user;
++ struct key *quota_key;
++ struct fscrypt_master_key_user *mk_user;
+ int err;
+
+- format_mk_user_description(description, mk->mk_spec.u.identifier);
+- mk_user = key_alloc(&key_type_fscrypt_user, description,
+- current_fsuid(), current_gid(), current_cred(),
+- KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
++ snprintf(description, sizeof(description), "%*phN.uid.%u",
++ FSCRYPT_KEY_IDENTIFIER_SIZE, mk->mk_spec.u.identifier,
++ __kuid_val(uid));
++ quota_key = key_alloc(&key_type_fscrypt_user, description, uid,
++ current_gid(), current_cred(),
++ KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
++ if (IS_ERR(quota_key))
++ return PTR_ERR(quota_key);
++
++ err = key_instantiate_and_link(quota_key, NULL, 0, NULL, NULL);
++ if (err) {
++ key_put(quota_key);
++ return err;
++ }
+
+- err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL);
+- key_put(mk_user);
+- return err;
++ mk_user = kzalloc(sizeof(*mk_user), GFP_KERNEL);
++ if (!mk_user) {
++ key_put(quota_key);
++ return -ENOMEM;
++ }
++ mk_user->uid = uid;
++ mk_user->quota_key = quota_key;
++ list_add(&mk_user->link, &mk->mk_users);
++ return 0;
++}
++
++static void unlink_and_free_mk_user(struct fscrypt_master_key_user *mk_user)
++{
++ list_del(&mk_user->link);
++ key_put(mk_user->quota_key);
++ kfree(mk_user);
+ }
+
+ /*
+- * Remove the current user's "key" from ->mk_users.
++ * Remove the current user's claim from ->mk_users.
+ * ->mk_sem must be held for write.
+ *
+- * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
++ * Returns 0 if removed or -ENOKEY if not found.
+ */
+ static int remove_master_key_user(struct fscrypt_master_key *mk)
+ {
+- struct key *mk_user;
+- int err;
++ struct fscrypt_master_key_user *mk_user;
+
+ mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
+- err = key_unlink(mk->mk_users, mk_user);
+- key_put(mk_user);
+- return err;
++ if (!mk_user)
++ return -ENOKEY;
++ unlink_and_free_mk_user(mk_user);
++ return 0;
++}
++
++/*
++ * Clear ->mk_users. Either ->mk_sem must be held for write, or 'mk' must have
++ * no structural references left.
++ */
++static void clear_mk_users(struct fscrypt_master_key *mk)
++{
++ struct fscrypt_master_key_user *mk_user, *tmp;
++
++ list_for_each_entry_safe(mk_user, tmp, &mk->mk_users, link)
++ unlink_and_free_mk_user(mk_user);
+ }
+
+ /*
+@@ -426,13 +409,12 @@ static int add_new_master_key(struct super_block *sb,
+ refcount_set(&mk->mk_struct_refs, 1);
+ mk->mk_spec = *mk_spec;
+
++ INIT_LIST_HEAD(&mk->mk_users);
++
+ 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_put;
+ err = add_master_key_user(mk);
+ if (err)
+ goto out_put;
+@@ -460,19 +442,13 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
+ int err;
+
+ /*
+- * If the current user is already in ->mk_users, then there's nothing to
+- * do. Otherwise, we need to add the user to ->mk_users. (Neither is
+- * applicable for v1 policy keys, which have NULL ->mk_users.)
++ * For v2 policy keys (FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER): If the current
++ * user is already in ->mk_users, then there's nothing to do.
++ * Otherwise, add the user to ->mk_users.
+ */
+- if (mk->mk_users) {
+- 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);
++ if (mk->mk_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
++ if (find_master_key_user(mk) != NULL)
+ return 0;
+- }
+ err = add_master_key_user(mk);
+ if (err)
+ return err;
+@@ -819,7 +795,6 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ {
+ struct fscrypt_key_specifier mk_spec;
+ struct fscrypt_master_key *mk;
+- struct key *mk_user;
+ int err;
+
+ mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
+@@ -831,13 +806,10 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ goto out;
+ }
+ down_read(&mk->mk_sem);
+- mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user)) {
+- err = PTR_ERR(mk_user);
+- } else {
+- key_put(mk_user);
++ if (find_master_key_user(mk) != NULL)
+ err = 0;
+- }
++ else
++ err = -ENOKEY;
+ up_read(&mk->mk_sem);
+ fscrypt_put_master_key(mk);
+ out:
+@@ -1030,16 +1002,18 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ 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) {
+- if (all_users)
+- err = keyring_clear(mk->mk_users);
+- else
++ if (!list_empty(&mk->mk_users)) {
++ if (all_users) {
++ clear_mk_users(mk);
++ err = 0;
++ } else {
+ err = remove_master_key_user(mk);
++ }
+ if (err) {
+ up_write(&mk->mk_sem);
+ goto out_put_key;
+ }
+- if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
++ if (!list_empty(&mk->mk_users)) {
+ /*
+ * Other users have still added the key too. We removed
+ * the current user's claim to the key, but we still
+@@ -1127,6 +1101,8 @@ 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 fscrypt_master_key *mk;
++ kuid_t uid;
++ const struct fscrypt_master_key_user *mk_user;
+ int err;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+@@ -1159,19 +1135,13 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
+ }
+
+ arg.status = FSCRYPT_KEY_STATUS_PRESENT;
+- if (mk->mk_users) {
+- struct key *mk_user;
+
+- arg.user_count = mk->mk_users->keys.nr_leaves_on_tree;
+- mk_user = find_master_key_user(mk);
+- if (!IS_ERR(mk_user)) {
++ uid = current_fsuid();
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ arg.user_count++;
++ if (uid_eq(mk_user->uid, uid))
+ arg.status_flags |=
+ FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF;
+- key_put(mk_user);
+- } else if (mk_user != ERR_PTR(-ENOKEY)) {
+- err = PTR_ERR(mk_user);
+- goto out_release_key;
+- }
+ }
+ err = 0;
+ out_release_key:
+--
+2.53.0
+
--- /dev/null
+From 6d6059bf544170964a2ca38cb99a494fe19377c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jul 2026 06:23:58 +0200
+Subject: selftests/bpf: Adapt sockmap update error handling
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 30581eda4a07ff15db623612cac578e81869e96f ]
+
+Update sockmap_listen to accommodate the recent change in sockmap that
+rejects unbound UDP sockets.
+
+TCP: Reject unbound and bound (unless established or listening).
+UDP: Accept only bound sockets.
+
+While at it, migrate to ASSERT_* and enforce reverse xmas tree.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-3-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/sockmap_listen.c | 21 ++++++++++---------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+index a6d8aa8c2a9ac..6386d6069b9db 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+@@ -51,8 +51,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ int family, int sotype, int mapfd)
+ {
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ s = xsocket(family, sotype, 0);
+ if (s == -1)
+@@ -61,11 +61,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (sotype == SOCK_STREAM) {
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
+- } else if (err)
+- FAIL_ERRNO("map_update: expected success");
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
+ xclose(s);
+ }
+
+@@ -75,8 +72,8 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ struct sockaddr_storage addr;
+ socklen_t len;
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ init_addr_loopback(family, &addr, &len);
+
+@@ -91,8 +88,12 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
++ if (sotype == SOCK_STREAM) {
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
++ } else {
++ ASSERT_OK(err, "map_update");
++ }
+ close:
+ xclose(s);
+ }
+@@ -1261,7 +1262,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
+ /* insert */
+ TEST(test_insert_invalid),
+ TEST(test_insert_opened),
+- TEST(test_insert_bound, SOCK_STREAM),
++ TEST(test_insert_bound),
+ TEST(test_insert),
+ /* delete */
+ TEST(test_delete_after_insert),
+--
+2.53.0
+
fortify-refactor-test_fortify-makefile-to-fix-some-b.patch
fortify-disable-wstringop-overread-in-tests.patch
pinctrl-renesas-rzg2l-use-enotsupp-instead-of-eopnot.patch
+fscrypt-replace-mk_users-keyring-with-simple-list.patch
+selftests-bpf-adapt-sockmap-update-error-handling.patch
--- /dev/null
+From b740be59b86ffbc418fb0858155353bce146aa68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Aug 2026 09:50:39 -0300
+Subject: selftests/bpf: Adapt sockmap update error handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 30581eda4a07ff15db623612cac578e81869e96f ]
+
+Update sockmap_listen to accommodate the recent change in sockmap that
+rejects unbound UDP sockets.
+
+TCP: Reject unbound and bound (unless established or listening).
+UDP: Accept only bound sockets.
+
+While at it, migrate to ASSERT_* and enforce reverse xmas tree.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-3-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Ricardo B. Marlière (SUSE) <ricardo@marliere.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/sockmap_listen.c | 21 ++++++++++---------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+index cc0c68bab9079..1c96a3cf4b979 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+@@ -53,8 +53,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ int family, int sotype, int mapfd)
+ {
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ s = xsocket(family, sotype, 0);
+ if (s == -1)
+@@ -63,11 +63,8 @@ static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (sotype == SOCK_STREAM) {
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
+- } else if (err)
+- FAIL_ERRNO("map_update: expected success");
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
+ xclose(s);
+ }
+
+@@ -77,8 +74,8 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ struct sockaddr_storage addr;
+ socklen_t len = 0;
+ u32 key = 0;
+- u64 value;
+ int err, s;
++ u64 value;
+
+ init_addr_loopback(family, &addr, &len);
+
+@@ -93,8 +90,12 @@ static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+ errno = 0;
+ value = s;
+ err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
+- if (!err || errno != EOPNOTSUPP)
+- FAIL_ERRNO("map_update: expected EOPNOTSUPP");
++ if (sotype == SOCK_STREAM) {
++ ASSERT_ERR(err, "map_update");
++ ASSERT_EQ(errno, EOPNOTSUPP, "errno");
++ } else {
++ ASSERT_OK(err, "map_update");
++ }
+ close:
+ xclose(s);
+ }
+@@ -1289,7 +1290,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
+ /* insert */
+ TEST(test_insert_invalid),
+ TEST(test_insert_opened),
+- TEST(test_insert_bound, SOCK_STREAM),
++ TEST(test_insert_bound),
+ TEST(test_insert),
+ /* delete */
+ TEST(test_delete_after_insert),
+--
+2.53.0
+
--- /dev/null
+From f07f886e3f433ff86f4df4ea6837e39f2a410706 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Aug 2026 09:50:38 -0300
+Subject: selftests/bpf: Ensure UDP sockets are bound
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit fe3ff273767ef22fe8a7cb3816f264927c190e50 ]
+
+Update sockmap_basic tests to bind sockets before they are used. This
+accommodates the recent change in sockmap that rejects unbound UDP sockets.
+
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-1-f878346f27ab@rbox.co
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Signed-off-by: Ricardo B. Marlière (SUSE) <ricardo@marliere.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/prog_tests/sockmap_basic.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+index d2846579285f2..b4019d1a5575e 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+@@ -807,7 +807,7 @@ static void test_sockmap_many_socket(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+@@ -876,7 +876,7 @@ static void test_sockmap_many_maps(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+@@ -947,7 +947,7 @@ static void test_sockmap_same_sock(void)
+ return;
+ }
+
+- udp = xsocket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
++ udp = socket_loopback(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK);
+ if (udp < 0) {
+ close(dgram);
+ close(tcp);
+--
+2.53.0
+
selftests-xsk-account-reclaimed-invalid-tx-descripto.patch
bluetooth-btrtl-fix-rtl8761b-bu-broken-le-extended-s.patch
bluetooth-btusb-add-tp-link-ub600-for-realtek-8761bu.patch
+selftests-bpf-ensure-udp-sockets-are-bound.patch
+selftests-bpf-adapt-sockmap-update-error-handling.patch