From: Greg Kroah-Hartman Date: Tue, 21 Jul 2026 08:50:55 +0000 (+0200) Subject: 7.1-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fbee0e9ef8b40e9be5d813d35cb6cfffdb1f58be;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches added patches: bnx2x-fix-potential-memory-leak-in-bnx2x_alloc_mem_bp.patch espintcp-use-sk_msg_free_partial-to-fix-partial-send.patch fscrypt-replace-mk_users-keyring-with-simple-list.patch ipmi-fix-refcount-leak-in-i_ipmi_request.patch ipmi-fix-user-refcount-underflow-in-event-delivery.patch loongarch-fix-missing-dirty-page-tracking-in-pte-pmd-_wrprotect.patch loongarch-fix-nr-passing-in-set_direct_map_valid_noflush.patch pwm-rzg2l-gpt-fix-period_ticks-type-from-u32-to-u64.patch rtc-mpfs-fix-counter-upload-completion-condition.patch rtc-renesas-rtca3-fix-pie-clear-polling-condition-in-alarm-setup-error-path.patch --- diff --git a/queue-7.1/bnx2x-fix-potential-memory-leak-in-bnx2x_alloc_mem_bp.patch b/queue-7.1/bnx2x-fix-potential-memory-leak-in-bnx2x_alloc_mem_bp.patch new file mode 100644 index 0000000000..180ac31ce2 --- /dev/null +++ b/queue-7.1/bnx2x-fix-potential-memory-leak-in-bnx2x_alloc_mem_bp.patch @@ -0,0 +1,43 @@ +From a986fde914d88af47eb78fd29c5d1af7952c3500 Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Sat, 20 Jun 2026 11:53:50 +0530 +Subject: bnx2x: fix potential memory leak in bnx2x_alloc_mem_bp() + +From: Abdun Nihaal + +commit a986fde914d88af47eb78fd29c5d1af7952c3500 upstream. + +If the allocation of fp[i].tpa_info fails, the error path will not free +the struct bnx2x_fastpath allocated earlier, as it is not linked to the +bp structure yet. Fix that by linking it immediately after allocation. + +Cc: stable@vger.kernel.org +Fixes: 15192a8cf8a8 ("bnx2x: Split the FP structure") +Signed-off-by: Abdun Nihaal +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260620062402.89549-1-nihaal@cse.iitm.ac.in +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -4748,6 +4748,7 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp) + fp = kzalloc_objs(*fp, bp->fp_array_size); + if (!fp) + goto alloc_err; ++ bp->fp = fp; + for (i = 0; i < bp->fp_array_size; i++) { + fp[i].tpa_info = + kzalloc_objs(struct bnx2x_agg_info, +@@ -4756,8 +4757,6 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp) + goto alloc_err; + } + +- bp->fp = fp; +- + /* allocate sp objs */ + bp->sp_objs = kzalloc_objs(struct bnx2x_sp_objs, bp->fp_array_size); + if (!bp->sp_objs) diff --git a/queue-7.1/espintcp-use-sk_msg_free_partial-to-fix-partial-send.patch b/queue-7.1/espintcp-use-sk_msg_free_partial-to-fix-partial-send.patch new file mode 100644 index 0000000000..1dda01d594 --- /dev/null +++ b/queue-7.1/espintcp-use-sk_msg_free_partial-to-fix-partial-send.patch @@ -0,0 +1,78 @@ +From 007800408002d871f5699bdb944f985896730b8f Mon Sep 17 00:00:00 2001 +From: Sabrina Dubroca +Date: Fri, 12 Jun 2026 16:11:39 +0200 +Subject: espintcp: use sk_msg_free_partial to fix partial send + +From: Sabrina Dubroca + +commit 007800408002d871f5699bdb944f985896730b8f upstream. + +sk_msg_free_partial() ensures consistency of the skmsg at every +iteration, without having to manually handle uncharges and offsets. +This simplifies the code, and fixes some bugs in skmsg accounting when +we don't send the full contents. + +Cc: stable@vger.kernel.org +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Reported-by: Aaron Esau +Reported-by: Yiming Qian +Signed-off-by: Sabrina Dubroca +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/espintcp.c | 34 +++++++--------------------------- + 1 file changed, 7 insertions(+), 27 deletions(-) + +--- a/net/xfrm/espintcp.c ++++ b/net/xfrm/espintcp.c +@@ -212,43 +212,23 @@ static int espintcp_sendskmsg_locked(str + struct sk_msg *skmsg = &emsg->skmsg; + bool more = flags & MSG_MORE; + struct scatterlist *sg; +- int done = 0; + int ret; + +- sg = &skmsg->sg.data[skmsg->sg.start]; + do { + struct bio_vec bvec; +- size_t size = sg->length - emsg->offset; +- int offset = sg->offset + emsg->offset; +- struct page *p; +- +- emsg->offset = 0; + ++ sg = &skmsg->sg.data[skmsg->sg.start]; + if (sg_is_last(sg) && !more) + msghdr.msg_flags &= ~MSG_MORE; + +- p = sg_page(sg); +-retry: +- bvec_set_page(&bvec, p, size, offset); +- iov_iter_bvec(&msghdr.msg_iter, ITER_SOURCE, &bvec, 1, size); +- ret = tcp_sendmsg_locked(sk, &msghdr, size); +- if (ret < 0) { +- emsg->offset = offset - sg->offset; +- skmsg->sg.start += done; ++ bvec_set_page(&bvec, sg_page(sg), sg->length, sg->offset); ++ iov_iter_bvec(&msghdr.msg_iter, ITER_SOURCE, &bvec, 1, sg->length); ++ ret = tcp_sendmsg_locked(sk, &msghdr, sg->length); ++ if (ret < 0) + return ret; +- } + +- if (ret != size) { +- offset += ret; +- size -= ret; +- goto retry; +- } +- +- done++; +- put_page(p); +- sk_mem_uncharge(sk, sg->length); +- sg = sg_next(sg); +- } while (sg); ++ sk_msg_free_partial(sk, skmsg, ret); ++ } while (skmsg->sg.size); + + memset(emsg, 0, sizeof(*emsg)); + diff --git a/queue-7.1/fscrypt-replace-mk_users-keyring-with-simple-list.patch b/queue-7.1/fscrypt-replace-mk_users-keyring-with-simple-list.patch new file mode 100644 index 0000000000..f0593a45b0 --- /dev/null +++ b/queue-7.1/fscrypt-replace-mk_users-keyring-with-simple-list.patch @@ -0,0 +1,451 @@ +From 696c030e1e3438955aba443b308ee8b6faa3983e Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Thu, 18 Jun 2026 15:19:21 -0700 +Subject: fscrypt: Replace mk_users keyring with simple list + +From: Eric Biggers + +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 +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 +Signed-off-by: Greg Kroah-Hartman +--- + fs/crypto/fscrypt_private.h | 36 ++++--- + fs/crypto/keyring.c | 220 ++++++++++++++++++-------------------------- + 2 files changed, 117 insertions(+), 139 deletions(-) + +--- a/fs/crypto/fscrypt_private.h ++++ b/fs/crypto/fscrypt_private.h +@@ -497,6 +497,19 @@ fscrypt_is_key_prepared(const struct fsc + /* 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 + */ + struct fscrypt_master_key_secret { +@@ -611,19 +624,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. +- * +- * This is NULL for v1 policy keys; those can only be added by root. +- * +- * 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 other fields.) ++ * 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. ++ * ++ * 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. + */ +- struct key *mk_users; ++ struct list_head mk_users; + + /* + * List of inodes that were unlocked using this key. This allows the +--- a/fs/crypto/keyring.c ++++ b/fs/crypto/keyring.c +@@ -65,22 +65,19 @@ static void fscrypt_free_master_key(stru + 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); +- if (mk->mk_users) { +- /* Clear the keyring so the quota gets released right away. */ +- keyring_clear(mk->mk_users); +- key_put(mk->mk_users); +- mk->mk_users = NULL; +- } ++ clear_mk_users(mk); + call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key); + } + +@@ -165,8 +162,8 @@ static void fscrypt_user_key_describe(co + } + + /* +- * 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 +@@ -180,30 +177,9 @@ static struct key_type key_type_fscrypt_ + .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) + { +@@ -338,91 +314,94 @@ out: + return mk; + } + +-static int allocate_master_key_users_keyring(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; +-} +- +-/* +- * 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); ++/* 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) ++{ ++ struct fscrypt_master_key_user *mk_user; ++ kuid_t uid = current_fsuid(); ++ ++ 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; ++ } ++ ++ mk_user = kzalloc_obj(*mk_user); ++ 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; ++} + +- err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL); +- key_put(mk_user); +- return err; ++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); + } + + /* +@@ -445,15 +424,14 @@ static int add_new_master_key(struct sup + 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); + + INIT_LIST_HEAD(&mk->mk_mode_keys); + + 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; +@@ -482,19 +460,13 @@ static int add_existing_master_key(struc + 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; +@@ -893,7 +865,6 @@ int fscrypt_verify_key_added(struct supe + { + 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; +@@ -905,13 +876,10 @@ int fscrypt_verify_key_added(struct supe + 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: +@@ -1103,16 +1071,18 @@ static int do_remove_key(struct file *fi + 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 +@@ -1198,6 +1168,8 @@ int fscrypt_ioctl_get_key_status(struct + 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))) +@@ -1230,19 +1202,13 @@ int fscrypt_ioctl_get_key_status(struct + } + + 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: diff --git a/queue-7.1/ipmi-fix-refcount-leak-in-i_ipmi_request.patch b/queue-7.1/ipmi-fix-refcount-leak-in-i_ipmi_request.patch new file mode 100644 index 0000000000..6b1f041119 --- /dev/null +++ b/queue-7.1/ipmi-fix-refcount-leak-in-i_ipmi_request.patch @@ -0,0 +1,55 @@ +From a3f3859cecacb64f18fd446271ece9a3b3f2d4de Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Wed, 3 Jun 2026 12:06:34 +0000 +Subject: ipmi: fix refcount leak in i_ipmi_request() + +From: Wentao Liang + +commit a3f3859cecacb64f18fd446271ece9a3b3f2d4de upstream. + +When a caller provides a `supplied_recv` message to i_ipmi_request(), +the function increments the user's `nr_msgs` reference count. If an +error occurs later, the out_err cleanup path only frees the recv_msg +if the function allocated it itself (i.e., !supplied_recv). In the +supplied_recv case the cleanup is skipped, leaving the reference count +elevated. The caller ipmi_request_supply_msgs() does not release the +supplied_recv on error, so the reference is permanently leaked. + +Fix this by explicitly reverting the reference count operations when a +supplied recv_msg with a valid user pointer is present in the error +path: decrement nr_msgs and drop the user's kref. + +Cc: stable@vger.kernel.org +Fixes: b52da4054ee0 ("ipmi: Rework user message limit handling") +Signed-off-by: Wentao Liang +Message-ID: <20260603120634.3758747-1-vulab@iscas.ac.cn> +Signed-off-by: Corey Minyard +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/ipmi/ipmi_msghandler.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/char/ipmi/ipmi_msghandler.c ++++ b/drivers/char/ipmi/ipmi_msghandler.c +@@ -2347,6 +2347,10 @@ static int i_ipmi_request(struct ipmi_us + if (smi_msg == NULL) { + if (!supplied_recv) + ipmi_free_recv_msg(recv_msg); ++ else if (recv_msg->user) { ++ atomic_dec(&recv_msg->user->nr_msgs); ++ kref_put(&recv_msg->user->refcount, free_ipmi_user); ++ } + return -ENOMEM; + } + } +@@ -2420,6 +2424,10 @@ out_err: + ipmi_free_smi_msg(smi_msg); + if (!supplied_recv) + ipmi_free_recv_msg(recv_msg); ++ else if (recv_msg->user) { ++ atomic_dec(&recv_msg->user->nr_msgs); ++ kref_put(&recv_msg->user->refcount, free_ipmi_user); ++ } + } + return rv; + } diff --git a/queue-7.1/ipmi-fix-user-refcount-underflow-in-event-delivery.patch b/queue-7.1/ipmi-fix-user-refcount-underflow-in-event-delivery.patch new file mode 100644 index 0000000000..de415df1e9 --- /dev/null +++ b/queue-7.1/ipmi-fix-user-refcount-underflow-in-event-delivery.patch @@ -0,0 +1,48 @@ +From 6aa9e61c46465d231e9beddf56af7effd71be682 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Thu, 21 May 2026 14:06:27 +0100 +Subject: ipmi: Fix user refcount underflow in event delivery + +From: Matt Fleming + +commit 6aa9e61c46465d231e9beddf56af7effd71be682 upstream. + +ipmi_alloc_recv_msg(user) takes the temporary user reference owned by the +receive message, and ipmi_free_recv_msg() drops it again. If event delivery +fails after allocating receive messages for earlier users, +handle_read_event_rsp() rolls those messages back with +ipmi_free_recv_msg(). + +That rollback path still drops user->refcount explicitly after freeing each +message. The extra put can free a user that remains linked on intf->users, +so later event delivery may dereference a freed user or trip refcount_t's +addition-on-zero warning when ipmi_alloc_recv_msg() tries to acquire +another reference. + +Remove the stale explicit put and the now-dead user assignment. Keep the +list_del() and ipmi_free_recv_msg() calls; they are the required rollback +operations. + +Fixes: b52da4054ee0 ("ipmi: Rework user message limit handling") +Cc: stable@vger.kernel.org # v6.18+ +Signed-off-by: Matt Fleming +Message-ID: <20260521130628.3641050-1-matt@readmodwrite.com> +Signed-off-by: Corey Minyard +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/ipmi/ipmi_msghandler.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/char/ipmi/ipmi_msghandler.c ++++ b/drivers/char/ipmi/ipmi_msghandler.c +@@ -4477,10 +4477,8 @@ static int handle_read_event_rsp(struct + mutex_unlock(&intf->users_mutex); + list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, + link) { +- user = recv_msg->user; + list_del(&recv_msg->link); + ipmi_free_recv_msg(recv_msg); +- kref_put(&user->refcount, free_ipmi_user); + } + /* + * We couldn't allocate memory for the diff --git a/queue-7.1/loongarch-fix-missing-dirty-page-tracking-in-pte-pmd-_wrprotect.patch b/queue-7.1/loongarch-fix-missing-dirty-page-tracking-in-pte-pmd-_wrprotect.patch new file mode 100644 index 0000000000..d25c2f9a36 --- /dev/null +++ b/queue-7.1/loongarch-fix-missing-dirty-page-tracking-in-pte-pmd-_wrprotect.patch @@ -0,0 +1,82 @@ +From 018e9828eb523c638fa3d9bdf0fd4956b74555b2 Mon Sep 17 00:00:00 2001 +From: Hongchen Zhang +Date: Thu, 25 Jun 2026 13:03:49 +0800 +Subject: LoongArch: Fix missing dirty page tracking in {pte,pmd}_wrprotect() + +From: Hongchen Zhang + +commit 018e9828eb523c638fa3d9bdf0fd4956b74555b2 upstream. + +When hardware page table walker (PTW) is enabled on LoongArch, the CPU +may set _PAGE_DIRTY directly in the page table entry during a write TLB +miss, without going through the software TLB store handler. The software +TLB store handler (tlbex.S:254) sets both _PAGE_DIRTY and_PAGE_MODIFIED +together: + + ori t0, t0, (_PAGE_VALID | _PAGE_DIRTY | _PAGE_MODIFIED) + +Since hardware PTW only sets _PAGE_DIRTY, the software-only bit, i.e. +_PAGE_MODIFIED is left unchanged. This creates a window where a PTE has +_PAGE_DIRTY set (hardware knows the page is dirty) but _PAGE_MODIFIED +clear (software is unaware). + +When fork()/clone() triggers copy-on-write, __copy_present_ptes() calls +pte_wrprotect(), which unconditionally clears both the _PAGE_WRITE and +_PAGE_DIRTY bits: + + pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY); + +Since _PAGE_MODIFIED was never set, the dirtiness information is lost +completely. Subsequently, when memory pressure triggers page reclaim, +page_mkclean() / try_to_unmap() sees the page as clean (i.e. pte_dirty() +returns false) and the page may be freed without writeback, causing data +corruption. + +Fix this by propagating the _PAGE_DIRTY bit to the _PAGE_MODIFIED bit in +both pte_wrprotect() and pmd_wrprotect() before clearing writeable bits: + + if (pte_val(pte) & _PAGE_DIRTY) + pte_val(pte) |= _PAGE_MODIFIED; + +The pmd_wrprotect() fix handles the CONFIG_TRANSPARENT_HUGEPAGE case, +where pmd entries need the same treatment. + +This ensures the software dirty tracking bit (checked by pte_dirty() and +pmd_dirty(), which read both the _PAGE_DIRTY and _PAGE_MODIFIED bits) is +preserved across fork COW write-protection. + +The issue was found by the LTP madvise09 test case, which exercises page +reclaim after "madvise(MADV_FREE), write and fork" operation sequence on +private anonymous mappings. + +Cc: stable@vger.kernel.org +Fixes: 09cfefb7fa70 ("LoongArch: Add memory management") +Co-developed-by: Tianyang Zhang +Signed-off-by: Tianyang Zhang +Signed-off-by: Hongchen Zhang +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/include/asm/pgtable.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/loongarch/include/asm/pgtable.h ++++ b/arch/loongarch/include/asm/pgtable.h +@@ -429,6 +429,8 @@ static inline pte_t pte_mkwrite_novma(pt + + static inline pte_t pte_wrprotect(pte_t pte) + { ++ if (pte_val(pte) & _PAGE_DIRTY) ++ pte_val(pte) |= _PAGE_MODIFIED; + pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY); + return pte; + } +@@ -535,6 +537,8 @@ static inline pmd_t pmd_mkwrite_novma(pm + + static inline pmd_t pmd_wrprotect(pmd_t pmd) + { ++ if (pmd_val(pmd) & _PAGE_DIRTY) ++ pmd_val(pmd) |= _PAGE_MODIFIED; + pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_DIRTY); + return pmd; + } diff --git a/queue-7.1/loongarch-fix-nr-passing-in-set_direct_map_valid_noflush.patch b/queue-7.1/loongarch-fix-nr-passing-in-set_direct_map_valid_noflush.patch new file mode 100644 index 0000000000..04ea740326 --- /dev/null +++ b/queue-7.1/loongarch-fix-nr-passing-in-set_direct_map_valid_noflush.patch @@ -0,0 +1,33 @@ +From 70378a710598432f13509bdc16a1c0f06b3ecb53 Mon Sep 17 00:00:00 2001 +From: Xuewen Wang +Date: Thu, 25 Jun 2026 13:03:49 +0800 +Subject: LoongArch: Fix nr passing in set_direct_map_valid_noflush() + +From: Xuewen Wang + +commit 70378a710598432f13509bdc16a1c0f06b3ecb53 upstream. + +set_direct_map_valid_noflush() incorrectly passes 1 to __set_memory() +instead of nr. This causes only the first page's attr to be updated when +nr > 1. + +Other architectures all pass nr correctly. + +Cc: stable@vger.kernel.org +Fixes: 0c6378a71574 ("arch: introduce set_direct_map_valid_noflush()") +Signed-off-by: Xuewen Wang +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/mm/pageattr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/loongarch/mm/pageattr.c ++++ b/arch/loongarch/mm/pageattr.c +@@ -234,5 +234,5 @@ int set_direct_map_valid_noflush(struct + clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID); + } + +- return __set_memory(addr, 1, set, clear); ++ return __set_memory(addr, nr, set, clear); + } diff --git a/queue-7.1/pwm-rzg2l-gpt-fix-period_ticks-type-from-u32-to-u64.patch b/queue-7.1/pwm-rzg2l-gpt-fix-period_ticks-type-from-u32-to-u64.patch new file mode 100644 index 0000000000..a8b8e1aabb --- /dev/null +++ b/queue-7.1/pwm-rzg2l-gpt-fix-period_ticks-type-from-u32-to-u64.patch @@ -0,0 +1,36 @@ +From 2b40d72de9354a76f5e3bb71230a4210eaa92849 Mon Sep 17 00:00:00 2001 +From: Biju Das +Date: Thu, 4 Jun 2026 10:56:31 +0100 +Subject: pwm: rzg2l-gpt: Fix period_ticks type from u32 to u64 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Biju Das + +commit 2b40d72de9354a76f5e3bb71230a4210eaa92849 upstream. + +period_ticks is used to store PWM period values that can exceed the 32-bit +range, so change its type from u32 to u64 to prevent overflow. + +Cc: stable@kernel.org +Fixes: 061f087f5d0b ("pwm: Add support for RZ/G2L GPT") +Signed-off-by: Biju Das +Link: https://patch.msgid.link/20260604095647.108654-2-biju.das.jz@bp.renesas.com +Signed-off-by: Uwe Kleine-König +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pwm/pwm-rzg2l-gpt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pwm/pwm-rzg2l-gpt.c ++++ b/drivers/pwm/pwm-rzg2l-gpt.c +@@ -81,7 +81,7 @@ struct rzg2l_gpt_chip { + void __iomem *mmio; + struct mutex lock; /* lock to protect shared channel resources */ + unsigned long rate_khz; +- u32 period_ticks[RZG2L_MAX_HW_CHANNELS]; ++ u64 period_ticks[RZG2L_MAX_HW_CHANNELS]; + u32 channel_request_count[RZG2L_MAX_HW_CHANNELS]; + u32 channel_enable_count[RZG2L_MAX_HW_CHANNELS]; + }; diff --git a/queue-7.1/rtc-mpfs-fix-counter-upload-completion-condition.patch b/queue-7.1/rtc-mpfs-fix-counter-upload-completion-condition.patch new file mode 100644 index 0000000000..489b8865dd --- /dev/null +++ b/queue-7.1/rtc-mpfs-fix-counter-upload-completion-condition.patch @@ -0,0 +1,45 @@ +From 9792ff8afa9017fe14f436f3ef3cd75f41f9f145 Mon Sep 17 00:00:00 2001 +From: Conor Dooley +Date: Wed, 13 May 2026 18:55:55 +0100 +Subject: rtc: mpfs: fix counter upload completion condition + +From: Conor Dooley + +commit 9792ff8afa9017fe14f436f3ef3cd75f41f9f145 upstream. + +The condition that needs to be checked for upload completion is the +UPLOAD bit in the completion register going low. The original iterations +of this driver used a do-while and this was converted to a +read_poll_timeout() during upstreaming without the condition being +inverted as it should have been. + +I suspect that this went unnoticed until now because a) the first read +was done when the bit was still set, immediately completing the +read_poll_timeout() and b) because the RTC doesn't hold time when power +is removed from the SoC reducing its utility (I for one keep it +disabled). If my first suspicion was true when the driver was +upstreamed, it's not true any longer though, hence the detection of the +problem. + +Fixes: 0b31d703598dc ("rtc: Add driver for Microchip PolarFire SoC") +CC: stable@vger.kernel.org +Signed-off-by: Conor Dooley +Tested-by: Valentina Fernandez +Link: https://patch.msgid.link/20260513-panhandle-ashy-70c6abf84d59@spud +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/rtc/rtc-mpfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/rtc/rtc-mpfs.c ++++ b/drivers/rtc/rtc-mpfs.c +@@ -112,7 +112,7 @@ static int mpfs_rtc_settime(struct devic + ctrl |= CONTROL_UPLOAD_BIT; + writel(ctrl, rtcdev->base + CONTROL_REG); + +- ret = read_poll_timeout(readl, prog, prog & CONTROL_UPLOAD_BIT, 0, UPLOAD_TIMEOUT_US, ++ ret = read_poll_timeout(readl, prog, !(prog & CONTROL_UPLOAD_BIT), 0, UPLOAD_TIMEOUT_US, + false, rtcdev->base + CONTROL_REG); + if (ret) { + dev_err(dev, "timed out uploading time to rtc"); diff --git a/queue-7.1/rtc-renesas-rtca3-fix-pie-clear-polling-condition-in-alarm-setup-error-path.patch b/queue-7.1/rtc-renesas-rtca3-fix-pie-clear-polling-condition-in-alarm-setup-error-path.patch new file mode 100644 index 0000000000..81d721ac2f --- /dev/null +++ b/queue-7.1/rtc-renesas-rtca3-fix-pie-clear-polling-condition-in-alarm-setup-error-path.patch @@ -0,0 +1,50 @@ +From 7e342d87aa8e6b831cf6d21ca41b1f7e032d0fcf Mon Sep 17 00:00:00 2001 +From: Lad Prabhakar +Date: Tue, 2 Jun 2026 20:25:55 +0100 +Subject: rtc: renesas-rtca3: Fix PIE clear polling condition in alarm setup error path + +From: Lad Prabhakar + +commit 7e342d87aa8e6b831cf6d21ca41b1f7e032d0fcf upstream. + +In rtca3_set_alarm(), the setup_failed path attempts to disable the +Periodic Interrupt Enable (PIE) bit and wait until it is cleared. +However, the polling condition passed to readb_poll_timeout_atomic() +uses an incorrect expression: + + !(tmp & ~RTCA3_RCR1_PIE) + +As ~RTCA3_RCR1_PIE evaluates to a mask of all bits except PIE, the +condition effectively waits for all non-PIE bits to become zero, which +is unrelated to the intended operation and is unlikely to ever be true. +This causes the poll to time out unnecessarily. + +Fix the condition to check for the PIE bit itself being cleared: + + !(tmp & RTCA3_RCR1_PIE) + +This correctly waits until PIE is deasserted after being cleared. + +Fixes: d4488377609e3 ("rtc: renesas-rtca3: Add driver for RTCA-3 available on Renesas RZ/G3S SoC") +Cc: stable@vger.kernel.org +Signed-off-by: Lad Prabhakar +Reviewed-by: Claudiu Beznea +Tested-by: Claudiu Beznea # on RZ/G3S +Link: https://patch.msgid.link/20260602192559.1791344-2-prabhakar.mahadev-lad.rj@bp.renesas.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/rtc/rtc-renesas-rtca3.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/rtc/rtc-renesas-rtca3.c ++++ b/drivers/rtc/rtc-renesas-rtca3.c +@@ -455,7 +455,7 @@ setup_failed: + * specified timeout for setup. + */ + writeb(rcr1 & ~RTCA3_RCR1_PIE, priv->base + RTCA3_RCR1); +- readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & ~RTCA3_RCR1_PIE), ++ readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & RTCA3_RCR1_PIE), + 10, RTCA3_DEFAULT_TIMEOUT_US); + atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE); + } diff --git a/queue-7.1/series b/queue-7.1/series index 1116fe98b9..c09e8cdde6 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -1946,3 +1946,13 @@ drm-xe-userptr-stub-notifier_lock-helpers-when-drm_gpusvm-n.patch netfilter-nfnetlink_cthelper-cap-to-maximum-number-of-expectation-per-master-on-updates.patch kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch riscv-vdso-always-declare-vdso_start-symbols.patch +pwm-rzg2l-gpt-fix-period_ticks-type-from-u32-to-u64.patch +loongarch-fix-nr-passing-in-set_direct_map_valid_noflush.patch +loongarch-fix-missing-dirty-page-tracking-in-pte-pmd-_wrprotect.patch +ipmi-fix-user-refcount-underflow-in-event-delivery.patch +espintcp-use-sk_msg_free_partial-to-fix-partial-send.patch +ipmi-fix-refcount-leak-in-i_ipmi_request.patch +bnx2x-fix-potential-memory-leak-in-bnx2x_alloc_mem_bp.patch +rtc-renesas-rtca3-fix-pie-clear-polling-condition-in-alarm-setup-error-path.patch +fscrypt-replace-mk_users-keyring-with-simple-list.patch +rtc-mpfs-fix-counter-upload-completion-condition.patch