From: Greg Kroah-Hartman Date: Mon, 20 Jul 2026 15:25:44 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v5.10.261~124 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c890414eb360c779a01da6c301c692c64d15dc4;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: can-bcm-add-missing-rcu-list-annotations-and-operations.patch can-bcm-fix-lockless-bound-ifindex-race-and-silent-rx_setup-failure.patch can-isotp-use-unconditional-synchronize_rcu-in-isotp_release.patch dm-bufio-fix-wrong-count-calculation-in-dm_bufio_issue_discard.patch dm-era-fix-out-of-bounds-memory-access-for-non-zero-start-sector.patch dm-log-fix-a-bitset_size-overflow-on-32bit-machines.patch dm-stats-fix-dm_jiffies_to_msec64.patch dm-stats-fix-merge-accounting.patch dm-thin-metadata-fix-metadata-snapshot-consistency-on-commit-failure.patch dm-thin-metadata-fix-superblock-refcount-leak-on-snapshot-shadow-failure.patch dm-verity-increase-sprintf-buffer-size.patch dm_early_create-fix-freeing-used-table-on-dm_resume-failure.patch i2c-mediatek-fix-wrrd-for-socs-without-auto_restart-option.patch i2c-mlxbf-fix-use-after-free-in-mlxbf_i2c_init_resource.patch irqchip-crossbar-use-correct-index-in-crossbar_domain_free.patch mtd-maps-vmu-flash-fix-null-pointer-dereference-in-initialization.patch nvmet-rdma-handle-inline-data-with-a-nonzero-offset.patch scsi-hpsa-fix-dma-mapping-leak-on-ioaccel2-reset-path.patch scsi-sg-report-request-table-problems-when-any-status-is-set.patch scsi-target-core-fix-iscsi-isid-use-after-free-in-register-and-move.patch sctp-validate-stale_cookie-cause-length-before-reading-staleness.patch spi-uniphier-fix-completion-initialization-order-before-devm_request_irq.patch time-fix-off-by-one-in-compat-settimeofday-usec-validation.patch tpm-fix-event_size-output-in-tpm1_binary_bios_measurements_show.patch tpm-make-the-tpm-character-devices-non-seekable.patch xen-gntdev-fix-error-handling-in-ioctl.patch xfrm-use-compat-translator-only-for-u64-alignment-mismatch.patch xfrm-xfrm_interface-require-cap_net_admin-in-the-device-netns-for-changelink.patch --- diff --git a/queue-5.10/can-bcm-add-missing-rcu-list-annotations-and-operations.patch b/queue-5.10/can-bcm-add-missing-rcu-list-annotations-and-operations.patch new file mode 100644 index 0000000000..369089b916 --- /dev/null +++ b/queue-5.10/can-bcm-add-missing-rcu-list-annotations-and-operations.patch @@ -0,0 +1,122 @@ +From 7b2c3eabc4dafc062a25e10711154f2107526a78 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Tue, 14 Jul 2026 18:55:27 +0200 +Subject: can: bcm: add missing rcu list annotations and operations + +From: Oliver Hartkopp + +commit 7b2c3eabc4dafc062a25e10711154f2107526a78 upstream. + +sashiko-bot remarked the missing use of list_add_rcu() in +bcm_[rx|tx]_setup() to have a proper initialized bcm_op structure +when bcm_proc_show() traverses the bcm_op's under rcu_read_lock(). + +To cover all initial settings of the bcm_op's the list_add_rcu() calls +are moved to the end of the setup code. + +While at it, also fix the mirroring removal side: bcm_release() called +bcm_remove_op() - which frees the op via call_rcu() - on ops that were +still linked in bo->tx_ops/bo->rx_ops, without list_del_rcu() first. +Unlink each op with list_del_rcu() before handing it to bcm_remove_op(), +matching the existing pattern in bcm_delete_tx_op()/bcm_delete_rx_op(). + +Reported-by: sashiko-reviews@lists.linux.dev +Closes: https://lore.kernel.org/linux-can/20260610094654.A1FFE1F00893@smtp.kernel.org/ +Fixes: dac5e6249159 ("can: bcm: add missing rcu read protection for procfs content") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260714-bcm_fixes-v15-5-562f7e3e42da@hartkopp.net +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/bcm.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/net/can/bcm.c ++++ b/net/can/bcm.c +@@ -244,7 +244,7 @@ static int bcm_proc_show(struct seq_file + (reduction == 100) ? "near " : "", reduction); + } + +- list_for_each_entry(op, &bo->tx_ops, list) { ++ list_for_each_entry_rcu(op, &bo->tx_ops, list) { + + seq_printf(m, "tx_op: %03X %s ", op->can_id, + bcm_proc_getifname(net, ifname, op->ifindex)); +@@ -877,6 +877,7 @@ static int bcm_tx_setup(struct bcm_msg_h + struct bcm_sock *bo = bcm_sk(sk); + struct bcm_op *op; + struct canfd_frame *cf; ++ bool add_op_to_list = false; + unsigned int i; + int err; + +@@ -1018,8 +1019,7 @@ static int bcm_tx_setup(struct bcm_msg_h + hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_SOFT); + +- /* add this bcm_op to the list of the tx_ops */ +- list_add(&op->list, &bo->tx_ops); ++ add_op_to_list = true; + + } /* if ((op = bcm_find_op(&bo->tx_ops, msg_head->can_id, ifindex))) */ + +@@ -1041,6 +1041,10 @@ static int bcm_tx_setup(struct bcm_msg_h + op->flags |= TX_ANNOUNCE; + } + ++ /* add this bcm_op to the list of the tx_ops? */ ++ if (add_op_to_list) ++ list_add_rcu(&op->list, &bo->tx_ops); ++ + if (op->flags & TX_ANNOUNCE) + bcm_can_tx(op); + +@@ -1183,9 +1187,6 @@ static int bcm_rx_setup(struct bcm_msg_h + HRTIMER_MODE_REL_SOFT); + op->thrtimer.function = bcm_rx_thr_handler; + +- /* add this bcm_op to the list of the rx_ops */ +- list_add(&op->list, &bo->rx_ops); +- + /* call can_rx_register() */ + do_rx_register = 1; + +@@ -1264,10 +1265,12 @@ static int bcm_rx_setup(struct bcm_msg_h + bcm_rx_handler, op, "bcm", sk); + if (err) { + /* this bcm rx op is broken -> remove it */ +- list_del_rcu(&op->list); + bcm_remove_op(op); + return err; + } ++ ++ /* add this bcm_op to the list of the rx_ops */ ++ list_add_rcu(&op->list, &bo->rx_ops); + } + + return msg_head->nframes * op->cfsiz + MHSIZ; +@@ -1597,8 +1600,10 @@ static int bcm_release(struct socket *so + remove_proc_entry(bo->procname, net->can.bcmproc_dir); + #endif /* CONFIG_PROC_FS */ + +- list_for_each_entry_safe(op, next, &bo->tx_ops, list) ++ list_for_each_entry_safe(op, next, &bo->tx_ops, list) { ++ list_del_rcu(&op->list); + bcm_remove_op(op); ++ } + + list_for_each_entry_safe(op, next, &bo->rx_ops, list) { + /* +@@ -1629,8 +1634,10 @@ static int bcm_release(struct socket *so + + synchronize_rcu(); + +- list_for_each_entry_safe(op, next, &bo->rx_ops, list) ++ list_for_each_entry_safe(op, next, &bo->rx_ops, list) { ++ list_del_rcu(&op->list); + bcm_remove_op(op); ++ } + + /* remove device reference */ + if (bo->bound) { diff --git a/queue-5.10/can-bcm-fix-lockless-bound-ifindex-race-and-silent-rx_setup-failure.patch b/queue-5.10/can-bcm-fix-lockless-bound-ifindex-race-and-silent-rx_setup-failure.patch new file mode 100644 index 0000000000..eaf449ec2b --- /dev/null +++ b/queue-5.10/can-bcm-fix-lockless-bound-ifindex-race-and-silent-rx_setup-failure.patch @@ -0,0 +1,186 @@ +From d9b091d9d22fee81ec53fb55d2032951993ceadb Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Tue, 14 Jul 2026 18:55:24 +0200 +Subject: can: bcm: fix lockless bound/ifindex race and silent RX_SETUP failure + +From: Oliver Hartkopp + +commit d9b091d9d22fee81ec53fb55d2032951993ceadb upstream. + +bcm_sendmsg() reads bo->ifindex and checks bo->bound before taking +lock_sock(), while bcm_notify(), bcm_connect() and bcm_release() all +mutate both fields under that same lock. Because the lockless reads +and the locked writes are unordered with respect to each other, a +racing bcm_notify() (device unregister) or bcm_connect() (concurrent +bind on another thread sharing the socket) can make bcm_sendmsg() +observe an inconsistent combination, e.g. a stale bound=1 together +with the now-cleared ifindex=0, silently turning a socket bound to a +specific CAN interface into one that also matches "any" interface. + +Keep the lockless bo->bound check purely as a fast-path reject, and +move the ifindex read (and a bo->bound re-check) into the locked +section, where every writer already serializes. This removes the +possibility of observing the two fields torn against each other, +rather than trying to fix it with more READ_ONCE()/WRITE_ONCE() pairs +on two independently updated fields. Annotate the now-purely-lockless +bo->bound accesses consistently across all its write sites. + +Also fix bcm_rx_setup() silently returning success when the target +device disappears concurrently instead of reporting -ENODEV, so a +broken RX op is no longer left registered as if it had succeeded. + +Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol") +Reported-by: Ginger +Closes: https://lore.kernel.org/linux-can/CAGp+u1aBK8QVjsvAxM2Ldzep4rEbsP9x_pV3At4g=h1kVEtyhA@mail.gmail.com/ +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260714-bcm_fixes-v15-2-562f7e3e42da@hartkopp.net +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/bcm.c | 65 +++++++++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 51 insertions(+), 14 deletions(-) + +--- a/net/can/bcm.c ++++ b/net/can/bcm.c +@@ -1251,6 +1251,11 @@ static int bcm_rx_setup(struct bcm_msg_h + + op->rx_reg_dev = dev; + dev_put(dev); ++ } else { ++ /* the requested device is gone - do not ++ * silently succeed without registering ++ */ ++ err = -ENODEV; + } + + } else +@@ -1320,12 +1325,13 @@ static int bcm_sendmsg(struct socket *so + { + struct sock *sk = sock->sk; + struct bcm_sock *bo = bcm_sk(sk); +- int ifindex = bo->ifindex; /* default ifindex for this bcm_op */ ++ int ifindex; + struct bcm_msg_head msg_head; + int cfsiz; + int ret; /* read bytes or error codes as return value */ + +- if (!bo->bound) ++ /* Lockless fast-path check for bound socket */ ++ if (!READ_ONCE(bo->bound)) + return -ENOTCONN; + + /* check for valid message length from userspace */ +@@ -1341,17 +1347,38 @@ static int bcm_sendmsg(struct socket *so + if ((size - MHSIZ) % cfsiz) + return -EINVAL; + ++ lock_sock(sk); ++ ++ /* Re-validate under the socket lock: a concurrent bcm_notify() ++ * may have unbound this socket (device removal) after the ++ * lockless fast-path check above. bo->ifindex is only ever ++ * mutated under lock_sock(), so reading it here - instead of ++ * before taking the lock - guarantees it can't be observed ++ * torn against bo->bound. ++ */ ++ if (!bo->bound) { ++ ret = -ENOTCONN; ++ goto out_release; ++ } ++ ++ /* default ifindex for this bcm_op */ ++ ifindex = bo->ifindex; ++ + /* check for alternative ifindex for this bcm_op */ + + if (!ifindex && msg->msg_name) { + /* no bound device as default => check msg_name */ + DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name); + +- if (msg->msg_namelen < BCM_MIN_NAMELEN) +- return -EINVAL; ++ if (msg->msg_namelen < BCM_MIN_NAMELEN) { ++ ret = -EINVAL; ++ goto out_release; ++ } + +- if (addr->can_family != AF_CAN) +- return -EINVAL; ++ if (addr->can_family != AF_CAN) { ++ ret = -EINVAL; ++ goto out_release; ++ } + + /* ifindex from sendto() */ + ifindex = addr->can_ifindex; +@@ -1360,20 +1387,21 @@ static int bcm_sendmsg(struct socket *so + struct net_device *dev; + + dev = dev_get_by_index(sock_net(sk), ifindex); +- if (!dev) +- return -ENODEV; ++ if (!dev) { ++ ret = -ENODEV; ++ goto out_release; ++ } + + if (dev->type != ARPHRD_CAN) { + dev_put(dev); +- return -ENODEV; ++ ret = -ENODEV; ++ goto out_release; + } + + dev_put(dev); + } + } + +- lock_sock(sk); +- + switch (msg_head.opcode) { + + case TX_SETUP: +@@ -1423,6 +1451,7 @@ static int bcm_sendmsg(struct socket *so + break; + } + ++out_release: + release_sock(sk); + + return ret; +@@ -1459,7 +1488,12 @@ static void bcm_notify(struct bcm_sock * + bo->bcm_proc_read = NULL; + } + #endif +- bo->bound = 0; ++ /* Paired with the lockless fast-path check in ++ * bcm_sendmsg(); bo->ifindex itself is only ever ++ * accessed under lock_sock() so it needs no ++ * annotation. ++ */ ++ WRITE_ONCE(bo->bound, 0); + bo->ifindex = 0; + notify_enodev = 1; + } +@@ -1600,7 +1634,7 @@ static int bcm_release(struct socket *so + + /* remove device reference */ + if (bo->bound) { +- bo->bound = 0; ++ WRITE_ONCE(bo->bound, 0); + bo->ifindex = 0; + } + +@@ -1669,7 +1703,10 @@ static int bcm_connect(struct socket *so + } + #endif /* CONFIG_PROC_FS */ + +- bo->bound = 1; ++ /* bo->ifindex above is fully assigned before this point; pairs ++ * with the lockless fast-path check in bcm_sendmsg() ++ */ ++ WRITE_ONCE(bo->bound, 1); + + fail: + release_sock(sk); diff --git a/queue-5.10/can-isotp-use-unconditional-synchronize_rcu-in-isotp_release.patch b/queue-5.10/can-isotp-use-unconditional-synchronize_rcu-in-isotp_release.patch new file mode 100644 index 0000000000..16b11a9d96 --- /dev/null +++ b/queue-5.10/can-isotp-use-unconditional-synchronize_rcu-in-isotp_release.patch @@ -0,0 +1,59 @@ +From 9b1a02e0d980ac6b0e36a90378f847062f81d7e4 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Sun, 12 Jul 2026 19:59:41 +0200 +Subject: can: isotp: use unconditional synchronize_rcu() in isotp_release() + +From: Oliver Hartkopp + +commit 9b1a02e0d980ac6b0e36a90378f847062f81d7e4 upstream. + +isotp_notify() unregisters the (RCU) CAN filters via can_rx_unregister() +and clears so->bound without waiting for a grace period. isotp_release() +uses so->bound to decide whether it needs to call synchronize_rcu() +before cancelling so->rxtimer, so when NETDEV_UNREGISTER runs first it +skips that synchronize_rcu() and can cancel the timer while an +in-flight isotp_rcv() is still executing and about to re-arm it via +isotp_send_fc(), leading to a use-after-free timer callback on the +freed socket. + +sakisho-bot remarked a problem with rtnl_lock held in isotp_notify(), +therefore make isotp_release() always call synchronize_rcu() before +cancelling the timers, regardless of so->bound. This still closes the +original race (isotp_notify() clearing so->bound without waiting for +in-flight isotp_rcv() callers before isotp_release() cancels the RX +timer) without adding any RCU wait to the netdevice notifier path. + +Fixes: 14a4696bc311 ("can: isotp: isotp_release(): omit unintended hrtimer restart on socket release") +Closes: https://lore.kernel.org/linux-can/20260707085210.6B6C01F000E9@smtp.kernel.org/ +Reported-by: Nico Yip +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260712-isotp-fixes-v10-1-793a1b1ce17f@hartkopp.net +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -1184,11 +1184,18 @@ static int isotp_release(struct socket * + SINGLE_MASK(so->txid), + isotp_rcv_echo, sk); + dev_put(dev); +- synchronize_rcu(); + } + } + } + ++ /* Always wait for a grace period before touching the timers below. ++ * A concurrent NETDEV_UNREGISTER may have already unregistered our ++ * filters and cleared so->bound in isotp_notify() without waiting ++ * for in-flight isotp_rcv() callers to finish, so this call must not ++ * be skipped just because so->bound is already 0 here. ++ */ ++ synchronize_rcu(); ++ + hrtimer_cancel(&so->txfrtimer); + hrtimer_cancel(&so->txtimer); + hrtimer_cancel(&so->rxtimer); diff --git a/queue-5.10/dm-bufio-fix-wrong-count-calculation-in-dm_bufio_issue_discard.patch b/queue-5.10/dm-bufio-fix-wrong-count-calculation-in-dm_bufio_issue_discard.patch new file mode 100644 index 0000000000..266cbd4fe7 --- /dev/null +++ b/queue-5.10/dm-bufio-fix-wrong-count-calculation-in-dm_bufio_issue_discard.patch @@ -0,0 +1,39 @@ +From 422f1d4f141eaa3a6e4199ceec86cc6b9bf26570 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 10 Jul 2026 18:32:49 +0200 +Subject: dm-bufio: fix wrong count calculation in dm_bufio_issue_discard + +From: Mikulas Patocka + +commit 422f1d4f141eaa3a6e4199ceec86cc6b9bf26570 upstream. + +block_to_sector converts a block number to a sector number and adds +c->start to the result. It is inappropriate to use this function for +converting the number of blocks to a number to sectors because c->start +would be incorrectly added to the result. + +Luckily, the only target that uses dm_bufio_issue_discard is dm-ebs, +which sets c->start to 0, so this bug is latent. + +Signed-off-by: Mikulas Patocka +Assisted-by: Claude:claude-opus-4-6 +Fixes: 6fbeb0048e6b ("dm bufio: implement discard") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-bufio.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -1375,7 +1375,9 @@ int dm_bufio_issue_discard(struct dm_buf + struct dm_io_region io_reg = { + .bdev = c->bdev, + .sector = block_to_sector(c, block), +- .count = block_to_sector(c, count), ++ .count = likely(c->sectors_per_block_bits >= 0) ? ++ count << c->sectors_per_block_bits : ++ count * (c->block_size >> SECTOR_SHIFT), + }; + + BUG_ON(dm_bufio_in_request()); diff --git a/queue-5.10/dm-era-fix-out-of-bounds-memory-access-for-non-zero-start-sector.patch b/queue-5.10/dm-era-fix-out-of-bounds-memory-access-for-non-zero-start-sector.patch new file mode 100644 index 0000000000..32f0710517 --- /dev/null +++ b/queue-5.10/dm-era-fix-out-of-bounds-memory-access-for-non-zero-start-sector.patch @@ -0,0 +1,59 @@ +From a868196f03c2b19418ae3d2b69e195d668a271e5 Mon Sep 17 00:00:00 2001 +From: Samuel Moelius +Date: Thu, 2 Jul 2026 00:27:35 +0000 +Subject: dm era: fix out-of-bounds memory access for non-zero start sector + +From: Samuel Moelius + +commit a868196f03c2b19418ae3d2b69e195d668a271e5 upstream. + +dm-era tracks writes in target-relative blocks, but era_map() calculates +the writeset block before applying the target offset. Tables with a +non-zero start sector can therefore pass an absolute mapped-device block +to metadata_current_marked(). + +If the absolute block is beyond the current writeset size, +writeset_marked() tests past the end of the in-core bitset. KASAN reports +this as a vmalloc-out-of-bounds access. + +Apply the target offset before calculating the era block so writeset +lookups use the target-relative block number. + +Assisted-by: Codex:gpt-5.5-cyber-preview +Signed-off-by: Samuel Moelius +Reviewed-by: Ming-Hung Tsai +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Fixes: eec40579d848 ("dm: add era target") +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-era-target.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/md/dm-era-target.c ++++ b/drivers/md/dm-era-target.c +@@ -1210,6 +1210,7 @@ static dm_block_t get_block(struct era * + static void remap_to_origin(struct era *era, struct bio *bio) + { + bio_set_dev(bio, era->origin_dev->bdev); ++ bio->bi_iter.bi_sector = dm_target_offset(era->ti, bio->bi_iter.bi_sector); + } + + /*---------------------------------------------------------------- +@@ -1534,7 +1535,7 @@ static void era_dtr(struct dm_target *ti + static int era_map(struct dm_target *ti, struct bio *bio) + { + struct era *era = ti->private; +- dm_block_t block = get_block(era, bio); ++ dm_block_t block; + + /* + * All bios get remapped to the origin device. We do this now, but +@@ -1542,6 +1543,7 @@ static int era_map(struct dm_target *ti, + * block is marked in this era. + */ + remap_to_origin(era, bio); ++ block = get_block(era, bio); + + /* + * REQ_PREFLUSH bios carry no data, so we're not interested in them. diff --git a/queue-5.10/dm-log-fix-a-bitset_size-overflow-on-32bit-machines.patch b/queue-5.10/dm-log-fix-a-bitset_size-overflow-on-32bit-machines.patch new file mode 100644 index 0000000000..8c5330b481 --- /dev/null +++ b/queue-5.10/dm-log-fix-a-bitset_size-overflow-on-32bit-machines.patch @@ -0,0 +1,45 @@ +From 9743132a41f4d9d0e54c5f2adcb821b04796bab1 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 2 Jul 2026 21:43:39 -0400 +Subject: dm-log: fix a bitset_size overflow on 32bit machines + +From: Benjamin Marzinski + +commit 9743132a41f4d9d0e54c5f2adcb821b04796bab1 upstream. + +Commit c20e36b7631d ("dm log: fix out-of-bounds write due to +region_count overflow") made sure that region_count could fit in an +unsigned int. But the bitmap memory isn't allocated based on +region_count. It uses bitset_size (a size_t variable). The first step of +calculating bitset_size is to set it to region_count, rounded up to a +multiple of BITS_PER_LONG. If region_size is less than BITS_PER_LONG +smaller than UINT_MAX, it will get rounded up to 2^32. On a 32bit +architecture, this will make bitset_size wrap around to 0 and fail, +despite region_count being valid. + +Since bitset_size gets divided by 8, it can hold any valid region_count. +It just needs a special case to handle the rollover. If it is 0, the +value rolled over, and bitset size should be set to the number of bytes +needed to hold 2^32 bits. + +Signed-off-by: Benjamin Marzinski +Signed-off-by: Mikulas Patocka +Fixes: c20e36b7631d ("dm log: fix out-of-bounds write due to region_count overflow") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-log.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/md/dm-log.c ++++ b/drivers/md/dm-log.c +@@ -421,6 +421,9 @@ static int create_log_context(struct dm_ + */ + bitset_size = dm_round_up(region_count, BITS_PER_LONG); + bitset_size >>= BYTE_SHIFT; ++ /* Handle dm_round_up rollover on 32-bit systems */ ++ if (!bitset_size) ++ bitset_size = 1UL << (BITS_PER_LONG - BYTE_SHIFT); + + lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits); + diff --git a/queue-5.10/dm-stats-fix-dm_jiffies_to_msec64.patch b/queue-5.10/dm-stats-fix-dm_jiffies_to_msec64.patch new file mode 100644 index 0000000000..140560313e --- /dev/null +++ b/queue-5.10/dm-stats-fix-dm_jiffies_to_msec64.patch @@ -0,0 +1,36 @@ +From 386df1a57b631c456d14f857cb0c0c2e11c16bef Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 10 Jul 2026 18:37:15 +0200 +Subject: dm-stats: fix dm_jiffies_to_msec64 + +From: Mikulas Patocka + +commit 386df1a57b631c456d14f857cb0c0c2e11c16bef upstream. + +There were wrong calculations in dm_jiffies_to_msec64 that produced +incorrect output when HZ was different from 1000. This commit fixes them. + +Signed-off-by: Mikulas Patocka +Assisted-by: Claude:claude-opus-4-6 +Fixes: fd2ed4d25270 ("dm: add statistics support") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-stats.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/md/dm-stats.c ++++ b/drivers/md/dm-stats.c +@@ -799,10 +799,10 @@ static unsigned long long dm_jiffies_to_ + result = jiffies_to_msecs(j & 0x3fffff); + if (j >= 1 << 22) { + mult = jiffies_to_msecs(1 << 22); +- result += (unsigned long long)mult * (unsigned long long)jiffies_to_msecs((j >> 22) & 0x3fffff); ++ result += (unsigned long long)mult * ((j >> 22) & 0x3fffff); + } + if (j >= 1ULL << 44) +- result += (unsigned long long)mult * (unsigned long long)mult * (unsigned long long)jiffies_to_msecs(j >> 44); ++ result += (unsigned long long)mult * (unsigned long long)(1 << 22) * (j >> 44); + + return result; + } diff --git a/queue-5.10/dm-stats-fix-merge-accounting.patch b/queue-5.10/dm-stats-fix-merge-accounting.patch new file mode 100644 index 0000000000..9b8924526e --- /dev/null +++ b/queue-5.10/dm-stats-fix-merge-accounting.patch @@ -0,0 +1,36 @@ +From 1917eb2db750ecbdf710f79a8042eaa545a063c7 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 10 Jul 2026 18:35:49 +0200 +Subject: dm-stats: fix merge accounting + +From: Mikulas Patocka + +commit 1917eb2db750ecbdf710f79a8042eaa545a063c7 upstream. + +There were wrong parentheses when setting stats_aux->merged, so that +merging was never properly accounted. This commit fixes it. + +Signed-off-by: Mikulas Patocka +Assisted-by: Claude:claude-opus-4-6 +Fixes: fd2ed4d25270 ("dm: add statistics support") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-stats.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/md/dm-stats.c ++++ b/drivers/md/dm-stats.c +@@ -651,10 +651,8 @@ void dm_stats_account_io(struct dm_stats + */ + last = raw_cpu_ptr(stats->last); + stats_aux->merged = +- (bi_sector == (READ_ONCE(last->last_sector) && +- ((bi_rw == WRITE) == +- (READ_ONCE(last->last_rw) == WRITE)) +- )); ++ bi_sector == READ_ONCE(last->last_sector) && ++ (bi_rw == WRITE) == (READ_ONCE(last->last_rw) == WRITE); + WRITE_ONCE(last->last_sector, end_sector); + WRITE_ONCE(last->last_rw, bi_rw); + } diff --git a/queue-5.10/dm-thin-metadata-fix-metadata-snapshot-consistency-on-commit-failure.patch b/queue-5.10/dm-thin-metadata-fix-metadata-snapshot-consistency-on-commit-failure.patch new file mode 100644 index 0000000000..2a964c2994 --- /dev/null +++ b/queue-5.10/dm-thin-metadata-fix-metadata-snapshot-consistency-on-commit-failure.patch @@ -0,0 +1,235 @@ +From 5bcd4d3058ebaf46ad2e163829d87dd4870c7a45 Mon Sep 17 00:00:00 2001 +From: Ming-Hung Tsai +Date: Tue, 30 Jun 2026 20:17:44 +0800 +Subject: dm thin metadata: fix metadata snapshot consistency on commit failure + +From: Ming-Hung Tsai + +commit 5bcd4d3058ebaf46ad2e163829d87dd4870c7a45 upstream. + +__reserve_metadata_snap() and __release_metadata_snap() modify the +superblock's held_root directly in the block_manager's buffer. If the +subsequent metadata commit fails, the held_root gets flushed to disk +through the abort_transaction path, resulting in inconsistent metadata. + +Reproducer 1: __reserve_metadata_snap() + +1. Create a 2 MiB metadata device and make the region after the 14th + block inaccessible, to trigger metadata commit failure in the + subsequent reserve_metadata_snap operation. The 14th block will be + the shadow destination for the index block. + +dmsetup create tmeta --table "0 112 linear /dev/sdc 0 +112 3984 error" + +2. Create a 16 MiB thin-pool + +dmsetup create tdata --table "0 32768 zero" +dd if=/dev/zero of=/dev/mapper/tmeta bs=4k count=1 +dmsetup create tpool --table "0 32768 thin-pool /dev/mapper/tmeta \ +/dev/mapper/tdata 128 0 1 skip_block_zeroing" + +3. Take a metadata snapshot to trigger metadata commit failure and + transaction abort. However, the held_root is written to disk, + breaking metadata consistency. + +dmsetup message tpool 0 "reserve_metadata_snap" + +thin_check v1.2.2 result: + +Bad reference count for metadata block 6. Expected 2, but space map contains 1. +Bad reference count for metadata block 7. Expected 2, but space map contains 1. +Bad reference count for metadata block 13. Expected 1, but space map contains 0. + +Reproducer 2: __release_metadata_snap() + +1. Create a 2 MiB metadata device and make the region after the 16th + block inaccessible, to trigger metadata commit failure in the + subsequent release_metadata_snap operation. The 16th block will be + the shadow destination for the index block. + +dmsetup create tmeta --table "0 128 linear /dev/sdc 0 +128 3968 error" + +2. Create a 16 MiB thin-pool + +dmsetup create tdata --table "0 32768 zero" +dd if=/dev/zero of=/dev/mapper/tmeta bs=4k count=1 +dmsetup create tpool --table "0 32768 thin-pool /dev/mapper/tmeta \ +/dev/mapper/tdata 128 0 1 skip_block_zeroing" + +3. Reserve then release the metadata snapshot, to trigger metadata + commit failure and transaction abort. The held_root gets removed + from the on-disk superblock, causing inconsistent metadata. + +dmsetup message tpool 0 "reserve_metadata_snap" +dmsetup message tpool 0 "release_metadata_snap" + +thin_check v1.2.2 result: + +Bad reference count for metadata block 6. Expected 1, but space map contains 2. +Bad reference count for metadata block 7. Expected 1, but space map contains 2. +1 metadata blocks have leaked. + +Fix by deferring the held_root update to commit time. + +Additionally, move the existing-snapshot check in __reserve_metadata_snap +before the shadow operation to avoid unnecessary work. In +__release_metadata_snap, clear pmd->held_root before btree deletion so +partial failure leaks blocks rather than leaving a stale reference, and +unlock the snapshot block before decrementing its refcount. + +Fixes: 991d9fa02da0 ("dm: add thin provisioning target") +Cc: stable@vger.kernel.org +Signed-off-by: Ming-Hung Tsai +Signed-off-by: Mikulas Patocka +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-thin-metadata.c | 63 ++++++++++++------------------------------ + 1 file changed, 18 insertions(+), 45 deletions(-) + +--- a/drivers/md/dm-thin-metadata.c ++++ b/drivers/md/dm-thin-metadata.c +@@ -183,6 +183,7 @@ struct dm_pool_metadata { + uint32_t time; + dm_block_t root; + dm_block_t details_root; ++ dm_block_t held_root; + struct list_head thin_devices; + uint64_t trans_id; + unsigned long flags; +@@ -709,6 +710,7 @@ static int __open_metadata(struct dm_poo + */ + pmd->root = le64_to_cpu(disk_super->data_mapping_root); + pmd->details_root = le64_to_cpu(disk_super->device_details_root); ++ pmd->held_root = le64_to_cpu(disk_super->held_root); + + __setup_btree_details(pmd); + dm_bm_unlock(sblock); +@@ -792,6 +794,7 @@ static int __begin_transaction(struct dm + pmd->time = le32_to_cpu(disk_super->time); + pmd->root = le64_to_cpu(disk_super->data_mapping_root); + pmd->details_root = le64_to_cpu(disk_super->device_details_root); ++ pmd->held_root = le64_to_cpu(disk_super->held_root); + pmd->trans_id = le64_to_cpu(disk_super->trans_id); + pmd->flags = le32_to_cpu(disk_super->flags); + pmd->data_block_size = le32_to_cpu(disk_super->data_block_size); +@@ -882,6 +885,7 @@ static int __commit_transaction(struct d + disk_super->time = cpu_to_le32(pmd->time); + disk_super->data_mapping_root = cpu_to_le64(pmd->root); + disk_super->device_details_root = cpu_to_le64(pmd->details_root); ++ disk_super->held_root = cpu_to_le64(pmd->held_root); + disk_super->trans_id = cpu_to_le64(pmd->trans_id); + disk_super->flags = cpu_to_le32(pmd->flags); + +@@ -1288,9 +1292,14 @@ static int __reserve_metadata_snap(struc + { + int r, inc; + struct thin_disk_superblock *disk_super; +- struct dm_block *copy, *sblock; ++ struct dm_block *copy; + dm_block_t held_root; + ++ if (pmd->held_root) { ++ DMWARN("Pool metadata snapshot already exists: release this before taking another."); ++ return -EBUSY; ++ } ++ + /* + * We commit to ensure the btree roots which we increment in a + * moment are up to date. +@@ -1318,14 +1327,6 @@ static int __reserve_metadata_snap(struc + held_root = dm_block_location(copy); + disk_super = dm_block_data(copy); + +- if (le64_to_cpu(disk_super->held_root)) { +- DMWARN("Pool metadata snapshot already exists: release this before taking another."); +- +- dm_tm_dec(pmd->tm, held_root); +- dm_tm_unlock(pmd->tm, copy); +- return -EBUSY; +- } +- + /* + * Wipe the spacemap since we're not publishing this. + */ +@@ -1341,18 +1342,8 @@ static int __reserve_metadata_snap(struc + dm_tm_inc(pmd->tm, le64_to_cpu(disk_super->device_details_root)); + dm_tm_unlock(pmd->tm, copy); + +- /* +- * Write the held root into the superblock. +- */ +- r = superblock_lock(pmd, &sblock); +- if (r) { +- dm_tm_dec(pmd->tm, held_root); +- return r; +- } ++ pmd->held_root = held_root; + +- disk_super = dm_block_data(sblock); +- disk_super->held_root = cpu_to_le64(held_root); +- dm_bm_unlock(sblock); + return 0; + } + +@@ -1372,18 +1363,10 @@ static int __release_metadata_snap(struc + { + int r; + struct thin_disk_superblock *disk_super; +- struct dm_block *sblock, *copy; ++ struct dm_block *copy; + dm_block_t held_root; + +- r = superblock_lock(pmd, &sblock); +- if (r) +- return r; +- +- disk_super = dm_block_data(sblock); +- held_root = le64_to_cpu(disk_super->held_root); +- disk_super->held_root = cpu_to_le64(0); +- +- dm_bm_unlock(sblock); ++ held_root = pmd->held_root; + + if (!held_root) { + DMWARN("No pool metadata snapshot found: nothing to release."); +@@ -1394,13 +1377,15 @@ static int __release_metadata_snap(struc + if (r) + return r; + ++ pmd->held_root = 0; ++ + disk_super = dm_block_data(copy); + dm_btree_del(&pmd->info, le64_to_cpu(disk_super->data_mapping_root)); + dm_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root)); +- dm_sm_dec_block(pmd->metadata_sm, held_root); +- + dm_tm_unlock(pmd->tm, copy); + ++ dm_sm_dec_block(pmd->metadata_sm, held_root); ++ + return 0; + } + +@@ -1419,19 +1404,7 @@ int dm_pool_release_metadata_snap(struct + static int __get_metadata_snap(struct dm_pool_metadata *pmd, + dm_block_t *result) + { +- int r; +- struct thin_disk_superblock *disk_super; +- struct dm_block *sblock; +- +- r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, +- &sb_validator, &sblock); +- if (r) +- return r; +- +- disk_super = dm_block_data(sblock); +- *result = le64_to_cpu(disk_super->held_root); +- +- dm_bm_unlock(sblock); ++ *result = pmd->held_root; + + return 0; + } diff --git a/queue-5.10/dm-thin-metadata-fix-superblock-refcount-leak-on-snapshot-shadow-failure.patch b/queue-5.10/dm-thin-metadata-fix-superblock-refcount-leak-on-snapshot-shadow-failure.patch new file mode 100644 index 0000000000..ee7c1ba9d7 --- /dev/null +++ b/queue-5.10/dm-thin-metadata-fix-superblock-refcount-leak-on-snapshot-shadow-failure.patch @@ -0,0 +1,38 @@ +From 4b22d0801fadfcae2e106e6ba32e49439c7c7ebf Mon Sep 17 00:00:00 2001 +From: Genjian Zhang +Date: Sat, 11 Jul 2026 18:05:26 +0800 +Subject: dm thin metadata: fix superblock refcount leak on snapshot shadow failure + +From: Genjian Zhang + +commit 4b22d0801fadfcae2e106e6ba32e49439c7c7ebf upstream. + +__reserve_metadata_snap() increments THIN_SUPERBLOCK_LOCATION in the +metadata space map before shadowing it. When dm_tm_shadow_block() +fails, a reference is leaked in the metadata space map. + +Fix by adding the missing dm_sm_dec_block(). + +Signed-off-by: Genjian Zhang +Signed-off-by: Mikulas Patocka +Fixes: cc8394d86f04 ("dm thin: provide userspace access to pool metadata") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-thin-metadata.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/md/dm-thin-metadata.c ++++ b/drivers/md/dm-thin-metadata.c +@@ -1308,8 +1308,10 @@ static int __reserve_metadata_snap(struc + dm_sm_inc_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION); + r = dm_tm_shadow_block(pmd->tm, THIN_SUPERBLOCK_LOCATION, + &sb_validator, ©, &inc); +- if (r) ++ if (r) { ++ dm_sm_dec_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION); + return r; ++ } + + BUG_ON(!inc); + diff --git a/queue-5.10/dm-verity-increase-sprintf-buffer-size.patch b/queue-5.10/dm-verity-increase-sprintf-buffer-size.patch new file mode 100644 index 0000000000..e5ae015c46 --- /dev/null +++ b/queue-5.10/dm-verity-increase-sprintf-buffer-size.patch @@ -0,0 +1,35 @@ +From 88dd117c92a142253fb7a17e791773902b3babc6 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Thu, 9 Jul 2026 21:36:01 +0200 +Subject: dm-verity: increase sprintf buffer size + +From: Mikulas Patocka + +commit 88dd117c92a142253fb7a17e791773902b3babc6 upstream. + +The prefix "DM_VERITY_ERR_BLOCK_NR" is 22 chars. Add '=', one digit for +type, ',', up to 20 digits for a u64 block number, and a NUL terminator: +that's 46 bytes. The buffer is 42 bytes. For block numbers >= 16 decimal +digits (devices larger than ~16 EB with 4K blocks), snprintf silently +truncates the uevent environment variable. + +Signed-off-by: Mikulas Patocka +Assisted-by: Claude:claude-opus-4.6 +Fixes: 65ff5b7ddf05 ("dm verity: add error handling modes for corrupted blocks") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-verity-target.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/md/dm-verity-target.c ++++ b/drivers/md/dm-verity-target.c +@@ -21,7 +21,7 @@ + + #define DM_MSG_PREFIX "verity" + +-#define DM_VERITY_ENV_LENGTH 42 ++#define DM_VERITY_ENV_LENGTH 46 + #define DM_VERITY_ENV_VAR_NAME "DM_VERITY_ERR_BLOCK_NR" + + #define DM_VERITY_DEFAULT_PREFETCH_SIZE 262144 diff --git a/queue-5.10/dm_early_create-fix-freeing-used-table-on-dm_resume-failure.patch b/queue-5.10/dm_early_create-fix-freeing-used-table-on-dm_resume-failure.patch new file mode 100644 index 0000000000..17a151662a --- /dev/null +++ b/queue-5.10/dm_early_create-fix-freeing-used-table-on-dm_resume-failure.patch @@ -0,0 +1,34 @@ +From 366665416f20527ff7cad548a32d1ddf23195740 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Thu, 9 Jul 2026 21:29:11 +0200 +Subject: dm_early_create: fix freeing used table on dm_resume failure + +From: Mikulas Patocka + +commit 366665416f20527ff7cad548a32d1ddf23195740 upstream. + +If dm_resume fails, the kernel attempts to free table with +dm_table_destroy, but the table was already instantiated with +dm_swap_table. This commit skips the call to dm_table_destroy in this +case. + +Signed-off-by: Mikulas Patocka +Assisted-by: Claude:claude-opus-4.6 +Fixes: 6bbc923dfcf5 ("dm: add support to directly boot to a mapped device") +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -2164,7 +2164,7 @@ int __init dm_early_create(struct dm_ioc + /* resume device */ + r = dm_resume(md); + if (r) +- goto err_destroy_table; ++ goto err_hash_remove; + + DMINFO("%s (%s) is ready", md->disk->disk_name, dmi->name); + dm_put(md); diff --git a/queue-5.10/i2c-mediatek-fix-wrrd-for-socs-without-auto_restart-option.patch b/queue-5.10/i2c-mediatek-fix-wrrd-for-socs-without-auto_restart-option.patch new file mode 100644 index 0000000000..1704de3dc2 --- /dev/null +++ b/queue-5.10/i2c-mediatek-fix-wrrd-for-socs-without-auto_restart-option.patch @@ -0,0 +1,37 @@ +From deb35336b5bfed5db9231b5348bc1514db930797 Mon Sep 17 00:00:00 2001 +From: Roman Vivchar +Date: Thu, 9 Jul 2026 16:31:29 +0300 +Subject: i2c: mediatek: fix WRRD for SoCs without auto_restart option + +From: Roman Vivchar + +commit deb35336b5bfed5db9231b5348bc1514db930797 upstream. + +MediaTek mt65xx family SoCs have no auto restart, however, they still +support the WRRD mode in the hardware. Because auto_restart is set to 0, +the WRRD mode will be never enabled, leading to read errors. + +Fix this by removing auto_restart check from the WRRD enable path. + +Fixes: b49218365280 ("i2c: mediatek: fix potential incorrect use of I2C_MASTER_WRRD") +Signed-off-by: Roman Vivchar +Cc: # v6.18+ +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260709-6572-6595-i2c-v2-1-b2fb8510d1d3@protonmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-mt65xx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-mt65xx.c ++++ b/drivers/i2c/busses/i2c-mt65xx.c +@@ -1075,7 +1075,7 @@ static int mtk_i2c_transfer(struct i2c_a + i2c->auto_restart = i2c->dev_comp->auto_restart; + + /* checking if we can skip restart and optimize using WRRD mode */ +- if (i2c->auto_restart && num == 2) { ++ if (num == 2) { + if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) && + msgs[0].addr == msgs[1].addr) { + i2c->auto_restart = 0; diff --git a/queue-5.10/i2c-mlxbf-fix-use-after-free-in-mlxbf_i2c_init_resource.patch b/queue-5.10/i2c-mlxbf-fix-use-after-free-in-mlxbf_i2c_init_resource.patch new file mode 100644 index 0000000000..24fd4c0e2b --- /dev/null +++ b/queue-5.10/i2c-mlxbf-fix-use-after-free-in-mlxbf_i2c_init_resource.patch @@ -0,0 +1,39 @@ +From 71356737a7a55c76fee847563e3d33f8e6dc6b6d Mon Sep 17 00:00:00 2001 +From: Xuanqiang Luo +Date: Tue, 14 Jul 2026 23:08:08 +0800 +Subject: i2c: mlxbf: Fix use-after-free in mlxbf_i2c_init_resource() + +From: Xuanqiang Luo + +commit 71356737a7a55c76fee847563e3d33f8e6dc6b6d upstream. + +If devm_platform_get_and_ioremap_resource() returns an error, +mlxbf_i2c_init_resource() frees tmp_res before reading tmp_res->io to +get the error code. This results in a use-after-free. + +Save the error code before freeing tmp_res. + +Fixes: b5b5b32081cd ("i2c: mlxbf: I2C SMBus driver for Mellanox BlueField SoC") +Signed-off-by: Xuanqiang Luo +Cc: # v5.10+ +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260714150808.85045-1-xuanqiang.luo@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-mlxbf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-mlxbf.c ++++ b/drivers/i2c/busses/i2c-mlxbf.c +@@ -1063,8 +1063,10 @@ static int mlxbf_i2c_init_resource(struc + + tmp_res->io = devm_ioremap_resource(dev, tmp_res->params); + if (IS_ERR(tmp_res->io)) { ++ int ret = PTR_ERR(tmp_res->io); ++ + devm_kfree(dev, tmp_res); +- return PTR_ERR(tmp_res->io); ++ return ret; + } + + tmp_res->type = type; diff --git a/queue-5.10/irqchip-crossbar-use-correct-index-in-crossbar_domain_free.patch b/queue-5.10/irqchip-crossbar-use-correct-index-in-crossbar_domain_free.patch new file mode 100644 index 0000000000..df8b4d5435 --- /dev/null +++ b/queue-5.10/irqchip-crossbar-use-correct-index-in-crossbar_domain_free.patch @@ -0,0 +1,52 @@ +From 043db005a8d6932dc7d217c86307e9af0bc10ddc Mon Sep 17 00:00:00 2001 +From: Bhargav Joshi +Date: Sat, 20 Jun 2026 17:39:16 +0530 +Subject: irqchip/crossbar: Use correct index in crossbar_domain_free() + +From: Bhargav Joshi + +commit 043db005a8d6932dc7d217c86307e9af0bc10ddc upstream. + +crossbar_domain_free() resets the domain data and then uses the nulled +out irq_data->hwirq member as index to reset the irq_map[] entry and to +write the relevant crossbar register with a safe entry. That means it +never frees the correct index and keeps the crossbar register connection +to the source interrupt active. + +If it would not reset the domain data, then this would be even worse as +irq_data->hwirq holds the source interrupt number, but both the map and +register index need the corresponding GIC SPI number and not the source +interrupt number. This might even result in an out of bounds access as +the source interrupt number can be higher than the maximal index space. + +Fix this by using the GIC SPI index from the parent domain's irq_data. + +Fixes: 783d31863fb82 ("irqchip: crossbar: Convert dra7 crossbar to stacked domains") +Signed-off-by: Bhargav Joshi +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260620-irq-crossbar-fix-v2-1-b8e8499f468a@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/irqchip/irq-crossbar.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/irqchip/irq-crossbar.c ++++ b/drivers/irqchip/irq-crossbar.c +@@ -158,9 +158,14 @@ static void crossbar_domain_free(struct + for (i = 0; i < nr_irqs; i++) { + struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); + ++ /* ++ * irq_map[] is indexed by GIC SPI number. The parent domain's ++ * hwirq contains the GIC interrupt number (GIC SPI + ++ * GIC_IRQ_START). ++ */ ++ cb->irq_map[d->parent_data->hwirq - GIC_IRQ_START] = IRQ_FREE; ++ cb->write(d->parent_data->hwirq - GIC_IRQ_START, cb->safe_map); + irq_domain_reset_irq_data(d); +- cb->irq_map[d->hwirq] = IRQ_FREE; +- cb->write(d->hwirq, cb->safe_map); + } + raw_spin_unlock(&cb->lock); + irq_domain_free_irqs_parent(domain, virq, nr_irqs); diff --git a/queue-5.10/mtd-maps-vmu-flash-fix-null-pointer-dereference-in-initialization.patch b/queue-5.10/mtd-maps-vmu-flash-fix-null-pointer-dereference-in-initialization.patch new file mode 100644 index 0000000000..6e9e78b24a --- /dev/null +++ b/queue-5.10/mtd-maps-vmu-flash-fix-null-pointer-dereference-in-initialization.patch @@ -0,0 +1,32 @@ +From 357e3b8e3a8769ba36eb8ec5e053e4825f1a9329 Mon Sep 17 00:00:00 2001 +From: Florian Fuchs +Date: Mon, 18 May 2026 13:45:21 +0200 +Subject: mtd: maps: vmu-flash: fix NULL pointer dereference in initialization + +From: Florian Fuchs + +commit 357e3b8e3a8769ba36eb8ec5e053e4825f1a9329 upstream. + +The mtd_info contains a struct device, which must be linked to its +parent. Without this, the initialization of the MTD fails with a NULL +pointer dereference. + +Fixes: 47a72688fae7 ("mtd: flash mapping support for Dreamcast VMU.") +Cc: stable@vger.kernel.org +Signed-off-by: Florian Fuchs +Signed-off-by: Miquel Raynal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/maps/vmu-flash.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/maps/vmu-flash.c ++++ b/drivers/mtd/maps/vmu-flash.c +@@ -547,6 +547,7 @@ static void vmu_queryblocks(struct maple + mpart->partition = card->partition; + mtd_cur->priv = mpart; + mtd_cur->owner = THIS_MODULE; ++ mtd_cur->dev.parent = &mdev->dev; + + pcache = kzalloc(sizeof(struct vmu_cache), GFP_KERNEL); + if (!pcache) diff --git a/queue-5.10/nvmet-rdma-handle-inline-data-with-a-nonzero-offset.patch b/queue-5.10/nvmet-rdma-handle-inline-data-with-a-nonzero-offset.patch new file mode 100644 index 0000000000..4302737da8 --- /dev/null +++ b/queue-5.10/nvmet-rdma-handle-inline-data-with-a-nonzero-offset.patch @@ -0,0 +1,89 @@ +From 48c0162f647bb47e6084ffbc71b8f213f5e2f4f8 Mon Sep 17 00:00:00 2001 +From: Bryam Vargas +Date: Thu, 4 Jun 2026 19:36:54 +0000 +Subject: nvmet-rdma: handle inline data with a nonzero offset + +From: Bryam Vargas + +commit 48c0162f647bb47e6084ffbc71b8f213f5e2f4f8 upstream. + +nvmet_rdma_use_inline_sg() maps the host-controlled inline data offset +into the per-command inline scatterlist. The bounds check admits any +offset with off + len <= inline_data_size, but the mapping still assumes +the data begins in the first inline page: + + sg->offset = off; + sg->length = min_t(int, len, PAGE_SIZE - off); + +When a port is configured with inline_data_size > PAGE_SIZE (settable up +to max(SZ_16K, PAGE_SIZE)), an offset in (PAGE_SIZE, inline_data_size] +makes "PAGE_SIZE - off" underflow, so sg->length is set to ~4 GiB and +the block backend reads far past the first inline page. num_pages(len) +also ignores the offset, so an in-bounds offset whose [off, off+len) +span crosses a page boundary under-counts the scatterlist. + +Map the offset properly: split it into a page index and an in-page +offset, start the scatterlist at that page, and size the page count from +page_off + len. Because the request scatterlist may now start at +inline_sg[page_idx] rather than inline_sg[0], generalize the inline-SGL +identity test in nvmet_rdma_release_rsp() to a range test; otherwise the +persistent inline scatterlist is mistaken for an allocated one and +nvmet_req_free_sgls() frees an inline page (and warns in +free_large_kmalloc()). + +Fixes: 0d5ee2b2ab4f ("nvmet-rdma: support max(16KB, PAGE_SIZE) inline data") +Cc: stable@vger.kernel.org +Suggested-by: Keith Busch +Reported-by: Bryam Vargas +Signed-off-by: Bryam Vargas +Signed-off-by: Keith Busch +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvme/target/rdma.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +--- a/drivers/nvme/target/rdma.c ++++ b/drivers/nvme/target/rdma.c +@@ -665,7 +665,8 @@ static void nvmet_rdma_release_rsp(struc + if (rsp->n_rdma) + nvmet_rdma_rw_ctx_destroy(rsp); + +- if (rsp->req.sg != rsp->cmd->inline_sg) ++ if (rsp->req.sg < rsp->cmd->inline_sg || ++ rsp->req.sg >= rsp->cmd->inline_sg + queue->dev->inline_page_count) + nvmet_req_free_sgls(&rsp->req); + + if (unlikely(!list_empty_careful(&queue->rsp_wr_wait_list))) +@@ -820,24 +821,25 @@ static void nvmet_rdma_write_data_done(s + static void nvmet_rdma_use_inline_sg(struct nvmet_rdma_rsp *rsp, u32 len, + u64 off) + { +- int sg_count = num_pages(len); ++ u64 page_off = off % PAGE_SIZE; ++ u64 page_idx = off / PAGE_SIZE; ++ int sg_count = num_pages(page_off + len); + struct scatterlist *sg; + int i; + +- sg = rsp->cmd->inline_sg; ++ sg = &rsp->cmd->inline_sg[page_idx]; + for (i = 0; i < sg_count; i++, sg++) { + if (i < sg_count - 1) + sg_unmark_end(sg); + else + sg_mark_end(sg); +- sg->offset = off; +- sg->length = min_t(int, len, PAGE_SIZE - off); ++ sg->offset = page_off; ++ sg->length = min_t(u64, len, PAGE_SIZE - page_off); + len -= sg->length; +- if (!i) +- off = 0; ++ page_off = 0; + } + +- rsp->req.sg = rsp->cmd->inline_sg; ++ rsp->req.sg = &rsp->cmd->inline_sg[page_idx]; + rsp->req.sg_cnt = sg_count; + } + diff --git a/queue-5.10/scsi-hpsa-fix-dma-mapping-leak-on-ioaccel2-reset-path.patch b/queue-5.10/scsi-hpsa-fix-dma-mapping-leak-on-ioaccel2-reset-path.patch new file mode 100644 index 0000000000..6a6fbf97b3 --- /dev/null +++ b/queue-5.10/scsi-hpsa-fix-dma-mapping-leak-on-ioaccel2-reset-path.patch @@ -0,0 +1,39 @@ +From e166bafc483e927150cb9b5f286c9191ea0df84e Mon Sep 17 00:00:00 2001 +From: Haoxiang Li +Date: Tue, 23 Jun 2026 00:00:28 +0800 +Subject: scsi: hpsa: Fix DMA mapping leak on IOACCEL2 reset path + +From: Haoxiang Li + +commit e166bafc483e927150cb9b5f286c9191ea0df84e upstream. + +If phys_disk->in_reset is set, the function returns directly without +undoing the resources acquired for the command. Add the missing error +cleanup by unmapping the IOACCEL2 SG chain block when needed, unmapping +the SCSI command, and dropping the outstanding IOACCEL command count +before returning. + +Fixes: c5dfd106414f ("scsi: hpsa: correct device resets") +Cc: stable@vger.kernel.org +Signed-off-by: Haoxiang Li +Acked-by: Don Brace +Link: https://patch.msgid.link/20260622160028.1240496-1-haoxiang_li2024@163.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/hpsa.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -5035,6 +5035,10 @@ static int hpsa_scsi_ioaccel2_queue_comm + + if (phys_disk->in_reset) { + cmd->result = DID_RESET << 16; ++ atomic_dec(&phys_disk->ioaccel_cmds_out); ++ scsi_dma_unmap(cmd); ++ if (use_sg > h->ioaccel_maxsg) ++ hpsa_unmap_ioaccel2_sg_chain_block(h, cp); + return -1; + } + diff --git a/queue-5.10/scsi-sg-report-request-table-problems-when-any-status-is-set.patch b/queue-5.10/scsi-sg-report-request-table-problems-when-any-status-is-set.patch new file mode 100644 index 0000000000..6ac6b2cdc5 --- /dev/null +++ b/queue-5.10/scsi-sg-report-request-table-problems-when-any-status-is-set.patch @@ -0,0 +1,49 @@ +From 1d3a742afeb761eaead774691bde1ced699e9a5d Mon Sep 17 00:00:00 2001 +From: Xu Rao +Date: Tue, 7 Jul 2026 11:08:45 +0800 +Subject: scsi: sg: Report request-table problems when any status is set + +From: Xu Rao + +commit 1d3a742afeb761eaead774691bde1ced699e9a5d upstream. + +SG_GET_REQUEST_TABLE reports per-request diagnostic state through +sg_req_info::problem. The field is meant to indicate whether there is an +error to report for a completed request. + +sg_fill_request_table() currently combines masked_status, host_status +and driver_status with bitwise AND. This only reports a problem when all +three status fields are non-zero at the same time. A normal target check +condition, for example, has masked_status set while host_status and +driver_status may both be zero, so the request is incorrectly reported +as clean. + +Use the same condition as sg_new_read(), which sets SG_INFO_CHECK when +any of the three status fields is non-zero. + +Cc: stable@vger.kernel.org +Signed-off-by: Xu Rao +Reviewed-by: Bart Van Assche +Link: https://patch.msgid.link/54B60C19F7DB8889+20260707030845.970018-1-raoxu@uniontech.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/sg.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -864,10 +864,9 @@ sg_fill_request_table(Sg_fd *sfp, sg_req + if (val >= SG_MAX_QUEUE) + break; + rinfo[val].req_state = srp->done + 1; +- rinfo[val].problem = +- srp->header.masked_status & +- srp->header.host_status & +- srp->header.driver_status; ++ rinfo[val].problem = srp->header.masked_status || ++ srp->header.host_status || ++ srp->header.driver_status; + if (srp->done) + rinfo[val].duration = + srp->header.duration; diff --git a/queue-5.10/scsi-target-core-fix-iscsi-isid-use-after-free-in-register-and-move.patch b/queue-5.10/scsi-target-core-fix-iscsi-isid-use-after-free-in-register-and-move.patch new file mode 100644 index 0000000000..b01a6ae6bb --- /dev/null +++ b/queue-5.10/scsi-target-core-fix-iscsi-isid-use-after-free-in-register-and-move.patch @@ -0,0 +1,69 @@ +From fda6a1f3c3d7047b5ce5654487649c2daa738bfc Mon Sep 17 00:00:00 2001 +From: Bryam Vargas +Date: Wed, 10 Jun 2026 04:22:48 +0000 +Subject: scsi: target: core: Fix iSCSI ISID use-after-free in REGISTER AND MOVE + +From: Bryam Vargas + +commit fda6a1f3c3d7047b5ce5654487649c2daa738bfc upstream. + +core_scsi3_emulate_pro_register_and_move() maps the PERSISTENT RESERVE OUT +parameter list with transport_kmap_data_sg() and parses the destination +TransportID with target_parse_pr_out_transport_id(). For an iSCSI +TransportID (FORMAT CODE 01b), iscsi_parse_pr_out_transport_id() returns +the ISID in iport_ptr as a raw pointer into that mapped buffer. + +The function then unmaps the buffer with transport_kunmap_data_sg() before +dereferencing iport_ptr in strcmp(), __core_scsi3_locate_pr_reg() and +core_scsi3_alloc_registration(). When the parameter list spans more than +one page (PARAMETER LIST LENGTH > 4096), transport_kmap_data_sg() uses +vmap() and transport_kunmap_data_sg() does vunmap(), so the kernel virtual +address backing iport_ptr is torn down and every subsequent dereference is +a use-after-free read of the unmapped region. + +Keep the parameter list mapped until iport_ptr is no longer needed: drop +the early transport_kunmap_data_sg() and unmap once on the success path, +right before returning. The error paths already unmap through the existing +"if (buf) transport_kunmap_data_sg(cmd)" at the out: label, which now runs +on every post-map error exit because buf is no longer cleared early. Only +reads of the mapping happen while spinlocks are held; the map and unmap +calls remain outside any lock. The sibling caller +core_scsi3_decode_spec_i_port() already uses the buffer before unmapping it +and is left unchanged. + +Fixes: 4949314c7283 ("target: Allow control CDBs with data > 1 page") +Cc: stable@vger.kernel.org +Signed-off-by: Bryam Vargas +Reviewed-by: John Garry +Reviewed-by: David Disseldorp +Link: https://patch.msgid.link/20260610042245.35473-1-hexlabsecurity@proton.me +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/target_core_pr.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -3293,9 +3293,6 @@ core_scsi3_emulate_pro_register_and_move + goto out; + } + +- transport_kunmap_data_sg(cmd); +- buf = NULL; +- + pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s" + " %s\n", dest_tf_ops->fabric_name, (iport_ptr != NULL) ? + "port" : "device", initiator_str, (iport_ptr != NULL) ? +@@ -3529,6 +3526,11 @@ after_iport_check: + core_scsi3_update_and_write_aptpl(cmd->se_dev, aptpl); + + core_scsi3_put_pr_reg(dest_pr_reg); ++ /* ++ * iport_ptr aliases the PR-OUT parameter list mapped above, so the ++ * buffer is unmapped only here on success (and at out: on error). ++ */ ++ transport_kunmap_data_sg(cmd); + return 0; + out: + if (buf) diff --git a/queue-5.10/sctp-validate-stale_cookie-cause-length-before-reading-staleness.patch b/queue-5.10/sctp-validate-stale_cookie-cause-length-before-reading-staleness.patch new file mode 100644 index 0000000000..5ca05ec4bf --- /dev/null +++ b/queue-5.10/sctp-validate-stale_cookie-cause-length-before-reading-staleness.patch @@ -0,0 +1,103 @@ +From 1cd23ca80784223fa2204e16203f754da4e821f8 Mon Sep 17 00:00:00 2001 +From: Weiming Shi +Date: Fri, 3 Jul 2026 20:35:46 -0700 +Subject: sctp: validate STALE_COOKIE cause length before reading staleness + +From: Weiming Shi + +commit 1cd23ca80784223fa2204e16203f754da4e821f8 upstream. + +When an ERROR chunk with a STALE_COOKIE cause is received in the +COOKIE_ECHOED state, sctp_sf_do_5_2_6_stale() reads the 4-byte Measure +of Staleness that follows the cause header: + + err = (struct sctp_errhdr *)(chunk->skb->data); + stale = ntohl(*(__be32 *)((u8 *)err + sizeof(*err))); + +err is the first cause in the chunk, not the STALE_COOKIE cause that +caused the dispatch, and nothing guarantees the staleness field is +present. sctp_walk_errors() only requires a cause to be as long as the +4-byte header, so for a STALE_COOKIE cause of length 4 the read runs +past the cause, and for a minimal ERROR chunk past skb->tail. The value +is echoed to the peer in the Cookie Preservative of the reply INIT, +leaking uninitialized memory. + +sctp_sf_cookie_echoed_err() already walks to the STALE_COOKIE cause, so +check its length there and pass it to sctp_sf_do_5_2_6_stale(), which +reads that cause instead of the first one. A STALE_COOKIE cause too +short to hold the staleness field is discarded. + +The read is reachable by any peer that can drive an association into +COOKIE_ECHOED, including an unprivileged process using a raw SCTP socket +in a user and network namespace. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Cc: stable@vger.kernel.org +Signed-off-by: Weiming Shi +Acked-by: Xin Long +Link: https://patch.msgid.link/20260704033545.2438373-2-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/sm_statefuns.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -73,7 +73,8 @@ static enum sctp_disposition sctp_sf_do_ + const struct sctp_association *asoc, + const union sctp_subtype type, + void *arg, +- struct sctp_cmd_seq *commands); ++ struct sctp_cmd_seq *commands, ++ struct sctp_errhdr *err); + static enum sctp_disposition sctp_sf_shut_8_4_5( + struct net *net, + const struct sctp_endpoint *ep, +@@ -2419,9 +2420,15 @@ enum sctp_disposition sctp_sf_cookie_ech + * errors. + */ + sctp_walk_errors(err, chunk->chunk_hdr) { +- if (SCTP_ERROR_STALE_COOKIE == err->cause) +- return sctp_sf_do_5_2_6_stale(net, ep, asoc, type, +- arg, commands); ++ if (err->cause != SCTP_ERROR_STALE_COOKIE) ++ continue; ++ /* The staleness is only meaningful if the cause is long ++ * enough to hold it; a shorter one is malformed. ++ */ ++ if (ntohs(err->length) < sizeof(*err) + sizeof(__be32)) ++ break; ++ return sctp_sf_do_5_2_6_stale(net, ep, asoc, type, ++ arg, commands, err); + } + + /* It is possible to have malformed error causes, and that +@@ -2463,13 +2470,13 @@ static enum sctp_disposition sctp_sf_do_ + const struct sctp_association *asoc, + const union sctp_subtype type, + void *arg, +- struct sctp_cmd_seq *commands) ++ struct sctp_cmd_seq *commands, ++ struct sctp_errhdr *err) + { + int attempts = asoc->init_err_counter + 1; +- struct sctp_chunk *chunk = arg, *reply; + struct sctp_cookie_preserve_param bht; + struct sctp_bind_addr *bp; +- struct sctp_errhdr *err; ++ struct sctp_chunk *reply; + u32 stale; + + if (attempts > asoc->max_init_attempts) { +@@ -2480,8 +2487,6 @@ static enum sctp_disposition sctp_sf_do_ + return SCTP_DISPOSITION_DELETE_TCB; + } + +- err = (struct sctp_errhdr *)(chunk->skb->data); +- + /* When calculating the time extension, an implementation + * SHOULD use the RTT information measured based on the + * previous COOKIE ECHO / ERROR exchange, and should add no diff --git a/queue-5.10/series b/queue-5.10/series index acc14b47dd..6a8dd88a52 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -488,3 +488,31 @@ ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch +mtd-maps-vmu-flash-fix-null-pointer-dereference-in-initialization.patch +irqchip-crossbar-use-correct-index-in-crossbar_domain_free.patch +i2c-mediatek-fix-wrrd-for-socs-without-auto_restart-option.patch +i2c-mlxbf-fix-use-after-free-in-mlxbf_i2c_init_resource.patch +xen-gntdev-fix-error-handling-in-ioctl.patch +xfrm-use-compat-translator-only-for-u64-alignment-mismatch.patch +xfrm-xfrm_interface-require-cap_net_admin-in-the-device-netns-for-changelink.patch +tpm-fix-event_size-output-in-tpm1_binary_bios_measurements_show.patch +tpm-make-the-tpm-character-devices-non-seekable.patch +time-fix-off-by-one-in-compat-settimeofday-usec-validation.patch +spi-uniphier-fix-completion-initialization-order-before-devm_request_irq.patch +sctp-validate-stale_cookie-cause-length-before-reading-staleness.patch +nvmet-rdma-handle-inline-data-with-a-nonzero-offset.patch +can-isotp-use-unconditional-synchronize_rcu-in-isotp_release.patch +can-bcm-fix-lockless-bound-ifindex-race-and-silent-rx_setup-failure.patch +can-bcm-add-missing-rcu-list-annotations-and-operations.patch +dm-thin-metadata-fix-superblock-refcount-leak-on-snapshot-shadow-failure.patch +dm-thin-metadata-fix-metadata-snapshot-consistency-on-commit-failure.patch +dm-era-fix-out-of-bounds-memory-access-for-non-zero-start-sector.patch +dm-bufio-fix-wrong-count-calculation-in-dm_bufio_issue_discard.patch +dm-log-fix-a-bitset_size-overflow-on-32bit-machines.patch +dm-stats-fix-dm_jiffies_to_msec64.patch +dm-stats-fix-merge-accounting.patch +dm_early_create-fix-freeing-used-table-on-dm_resume-failure.patch +dm-verity-increase-sprintf-buffer-size.patch +scsi-hpsa-fix-dma-mapping-leak-on-ioaccel2-reset-path.patch +scsi-sg-report-request-table-problems-when-any-status-is-set.patch +scsi-target-core-fix-iscsi-isid-use-after-free-in-register-and-move.patch diff --git a/queue-5.10/spi-uniphier-fix-completion-initialization-order-before-devm_request_irq.patch b/queue-5.10/spi-uniphier-fix-completion-initialization-order-before-devm_request_irq.patch new file mode 100644 index 0000000000..a496bc7054 --- /dev/null +++ b/queue-5.10/spi-uniphier-fix-completion-initialization-order-before-devm_request_irq.patch @@ -0,0 +1,52 @@ +From f3ad1c87d8201e54b66bd6072442f0b5d5a308ee Mon Sep 17 00:00:00 2001 +From: Kunihiko Hayashi +Date: Tue, 16 Jun 2026 10:12:23 +0900 +Subject: spi: uniphier: Fix completion initialization order before devm_request_irq() + +From: Kunihiko Hayashi + +commit f3ad1c87d8201e54b66bd6072442f0b5d5a308ee upstream. + +The driver calls devm_request_irq() before initializing the completion +used by the interrupt handler. Because the interrupt may occur immediately +after devm_request_irq(), the handler may execute before init_completion(). + +This may result in calling complete() on an uninitialized completion, +causing undefined behavior. This has been observed with KASAN. + +Fix this by initializing the completion before registering the IRQ. + +Reported-by: Sangyun Kim +Reported-by: Kyungwook Boo +Fixes: 5ba155a4d4cc ("spi: add SPI controller driver for UniPhier SoC") +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Signed-off-by: Kunihiko Hayashi +Reviewed-by: Masami Hiramatsu (Google) +Link: https://patch.msgid.link/20260616011223.201357-1-hayashi.kunihiko@socionext.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-uniphier.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/spi/spi-uniphier.c ++++ b/drivers/spi/spi-uniphier.c +@@ -659,6 +659,8 @@ static int uniphier_spi_probe(struct pla + priv->master = master; + priv->is_save_param = false; + ++ init_completion(&priv->xfer_done); ++ + priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->base)) { + ret = PTR_ERR(priv->base); +@@ -690,8 +692,6 @@ static int uniphier_spi_probe(struct pla + goto out_disable_clk; + } + +- init_completion(&priv->xfer_done); +- + clk_rate = clk_get_rate(priv->clk); + + master->max_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MIN_CLK_DIVIDER); diff --git a/queue-5.10/time-fix-off-by-one-in-compat-settimeofday-usec-validation.patch b/queue-5.10/time-fix-off-by-one-in-compat-settimeofday-usec-validation.patch new file mode 100644 index 0000000000..6042d7f59f --- /dev/null +++ b/queue-5.10/time-fix-off-by-one-in-compat-settimeofday-usec-validation.patch @@ -0,0 +1,44 @@ +From 269f2b43fae692d1f3988c9f888a6301aa537b82 Mon Sep 17 00:00:00 2001 +From: Wang Yan +Date: Mon, 22 Jun 2026 18:33:48 +0800 +Subject: time: Fix off-by-one in compat settimeofday() usec validation + +From: Wang Yan + +commit 269f2b43fae692d1f3988c9f888a6301aa537b82 upstream. + +The compat version of settimeofday() uses '>' instead of '>=' when +validating tv_usec against USEC_PER_SEC, allowing the value 1000000 to pass +the check. After the subsequent conversion to nanoseconds (tv_nsec *= +NSEC_PER_USEC), this results in tv_nsec == NSEC_PER_SEC, which violates the +timespec invariant that tv_nsec must be strictly less than NSEC_PER_SEC. + +The native settimeofday() was already fixed in commit ce4abda5e126 ("time: +Fix off-by-one in settimeofday() usec validation"), but the compat +counterpart was missed. + +Fix it by using '>=' to reject tv_usec values outside the valid range [0, +USEC_PER_SEC - 1]. + +Fixes: 5e0fb1b57bea ("y2038: time: avoid timespec usage in settimeofday()") +Signed-off-by: Wang Yan +Signed-off-by: Thomas Gleixner +Acked-by: Arnd Bergmann +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260622103348.120255-1-wangyan01@kylinos.cn +Signed-off-by: Greg Kroah-Hartman +--- + kernel/time/time.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/time/time.c ++++ b/kernel/time/time.c +@@ -251,7 +251,7 @@ COMPAT_SYSCALL_DEFINE2(settimeofday, str + get_user(new_ts.tv_nsec, &tv->tv_usec)) + return -EFAULT; + +- if (new_ts.tv_nsec > USEC_PER_SEC || new_ts.tv_nsec < 0) ++ if (new_ts.tv_nsec >= USEC_PER_SEC || new_ts.tv_nsec < 0) + return -EINVAL; + + new_ts.tv_nsec *= NSEC_PER_USEC; diff --git a/queue-5.10/tpm-fix-event_size-output-in-tpm1_binary_bios_measurements_show.patch b/queue-5.10/tpm-fix-event_size-output-in-tpm1_binary_bios_measurements_show.patch new file mode 100644 index 0000000000..a08dad57de --- /dev/null +++ b/queue-5.10/tpm-fix-event_size-output-in-tpm1_binary_bios_measurements_show.patch @@ -0,0 +1,51 @@ +From 1a58f6115bfb34eabcc7de8a3a9745b219179781 Mon Sep 17 00:00:00 2001 +From: Thorsten Blum +Date: Mon, 15 Jun 2026 15:02:05 +0300 +Subject: tpm: fix event_size output in tpm1_binary_bios_measurements_show + +From: Thorsten Blum + +commit 1a58f6115bfb34eabcc7de8a3a9745b219179781 upstream. + +Commit 186d124f07da ("tpm_eventlog.c: fix binary_bios_measurements") +split the output to write the endian-converted event header first and +then the variable-length event data. + +However, the split was at sizeof(struct tcpa_event) - 1, even though +event_data was a zero-length array, and later a flexible array member, +both of which already excluded the event data. + +Therefore, the current code writes the first three bytes of event_size +from the endian-converted header and then the last byte from the raw +header, which can emit a corrupted event_size on PPC64, where +do_endian_conversion() maps to be32_to_cpu(). + +Split one byte later to write the full endian-converted header first, +followed by the variable-length event->event_data. + +Fixes: 186d124f07da ("tpm_eventlog.c: fix binary_bios_measurements") +Cc: stable@vger.kernel.org # v5.10+ +Signed-off-by: Thorsten Blum +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/tpm/eventlog/tpm1.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/char/tpm/eventlog/tpm1.c ++++ b/drivers/char/tpm/eventlog/tpm1.c +@@ -235,12 +235,12 @@ static int tpm1_binary_bios_measurements + + temp_ptr = (char *) &temp_event; + +- for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++) ++ for (i = 0; i < sizeof(struct tcpa_event); i++) + seq_putc(m, temp_ptr[i]); + + temp_ptr = (char *) v; + +- for (i = (sizeof(struct tcpa_event) - 1); ++ for (i = sizeof(struct tcpa_event); + i < (sizeof(struct tcpa_event) + temp_event.event_size); i++) + seq_putc(m, temp_ptr[i]); + diff --git a/queue-5.10/tpm-make-the-tpm-character-devices-non-seekable.patch b/queue-5.10/tpm-make-the-tpm-character-devices-non-seekable.patch new file mode 100644 index 0000000000..c41e831d3c --- /dev/null +++ b/queue-5.10/tpm-make-the-tpm-character-devices-non-seekable.patch @@ -0,0 +1,75 @@ +From f20d61c22bcaf172d6790b6500e3838e532e71c8 Mon Sep 17 00:00:00 2001 +From: Jaewon Yang +Date: Mon, 13 Jul 2026 02:11:47 +0900 +Subject: tpm: Make the TPM character devices non-seekable + +From: Jaewon Yang + +commit f20d61c22bcaf172d6790b6500e3838e532e71c8 upstream. + +The TPM character devices expose a sequential command/response +interface, but their open handlers leave FMODE_PREAD and FMODE_PWRITE +enabled. + +After a command leaves a response pending, pread(fd, buf, 16, 0x1400) +passes 0x1400 as *off to tpm_common_read(). The transfer length is +bounded by response_length, but the offset is used unchecked when +forming data_buffer + *off. A sufficiently large offset therefore causes +an out-of-bounds heap read through copy_to_user() and, if the copy +succeeds, an out-of-bounds zero-write through the following memset(). + +Positional I/O does not provide coherent semantics for this interface. +An arbitrary pread offset cannot represent how much of a response has +been consumed sequentially. The write callback always stores a command +at the start of data_buffer, while pwrite() does not update file->f_pos +and can leave the sequential read cursor stale. + +Call nonseekable_open() from both open handlers. This removes +FMODE_PREAD and FMODE_PWRITE, causing positional reads and writes to +fail with -ESPIPE before reaching the TPM callbacks, and explicitly +marks the files non-seekable. Normal read() and write() continue to use +the existing sequential f_pos cursor, leaving the response state machine +unchanged. + +Tested on Linux 6.12 with KASAN and a swtpm TPM2 device: + + - sequential partial reads returned the complete response + - pread() and preadv() with offset 0x1400 returned -ESPIPE + - pwrite() and pwritev() with offset zero returned -ESPIPE + - the pending response remained intact after the rejected operations + - a subsequent normal command/response cycle completed normally + - no KASAN report was produced. + +Fixes: 9488585b21be ("tpm: add support for partial reads") +Link: https://lore.kernel.org/all/20260710090217.191289-1-yong010301@gmail.com/ +Cc: stable@vger.kernel.org +Signed-off-by: Jaewon Yang +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/tpm/tpm-dev.c | 2 +- + drivers/char/tpm/tpmrm-dev.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/char/tpm/tpm-dev.c ++++ b/drivers/char/tpm/tpm-dev.c +@@ -36,7 +36,7 @@ static int tpm_open(struct inode *inode, + + tpm_common_open(file, chip, priv, NULL); + +- return 0; ++ return nonseekable_open(inode, file); + + out: + clear_bit(0, &chip->is_open); +--- a/drivers/char/tpm/tpmrm-dev.c ++++ b/drivers/char/tpm/tpmrm-dev.c +@@ -29,7 +29,7 @@ static int tpmrm_open(struct inode *inod + + tpm_common_open(file, chip, &priv->priv, &priv->space); + +- return 0; ++ return nonseekable_open(inode, file); + } + + static int tpmrm_release(struct inode *inode, struct file *file) diff --git a/queue-5.10/xen-gntdev-fix-error-handling-in-ioctl.patch b/queue-5.10/xen-gntdev-fix-error-handling-in-ioctl.patch new file mode 100644 index 0000000000..0299c7396e --- /dev/null +++ b/queue-5.10/xen-gntdev-fix-error-handling-in-ioctl.patch @@ -0,0 +1,61 @@ +From 45ca1afe2fd14c04e37227e79d3f8455831d8408 Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Mon, 22 Jun 2026 19:25:41 +0800 +Subject: xen/gntdev: fix error handling in ioctl + +From: Wentao Liang + +commit 45ca1afe2fd14c04e37227e79d3f8455831d8408 upstream. + +When gntdev_ioctl_map_grant_ref() fails to copy the operation result +back to userspace after successfully adding the mapping to the list, +the error path returns -EFAULT without releasing the reference +acquired by gntdev_alloc_map(). The mapping remains in priv->maps +with a refcount of 1, causing a memory leak and a dangling list +entry. + +Additionally, gntdev_add_map() may modify map->index to avoid overlap +with existing mappings. Therefore, the index returned to userspace +must be obtained after gntdev_add_map() completes. + +Fix this by holding the mutex across gntdev_add_map(), retrieving +the correct index, and copy_to_user(). If copy_to_user() fails, +remove the mapping from the list and release the reference while +still holding the lock. + +Cc: stable@vger.kernel.org + +Fix these issues by properly handling all error cases. + +Fixes: 1401c00e59ea ("xen/gntdev: convert priv->lock to a mutex") +Fixes: 68b025c813c2 ("xen-gntdev: Add reference counting to maps") + +Signed-off-by: Wentao Liang +Reviewed-by: Juergen Gross +Signed-off-by: Juergen Gross +Message-ID: <20260622112541.38194-1-vulab@iscas.ac.cn> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/xen/gntdev.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -668,11 +668,15 @@ static long gntdev_ioctl_map_grant_ref(s + mutex_lock(&priv->lock); + gntdev_add_map(priv, map); + op.index = map->index << PAGE_SHIFT; +- mutex_unlock(&priv->lock); + +- if (copy_to_user(u, &op, sizeof(op)) != 0) ++ if (copy_to_user(u, &op, sizeof(op)) != 0) { ++ list_del(&map->next); ++ mutex_unlock(&priv->lock); ++ gntdev_put_map(priv, map); + return -EFAULT; ++ } + ++ mutex_unlock(&priv->lock); + return 0; + } + diff --git a/queue-5.10/xfrm-use-compat-translator-only-for-u64-alignment-mismatch.patch b/queue-5.10/xfrm-use-compat-translator-only-for-u64-alignment-mismatch.patch new file mode 100644 index 0000000000..f1e411c02b --- /dev/null +++ b/queue-5.10/xfrm-use-compat-translator-only-for-u64-alignment-mismatch.patch @@ -0,0 +1,88 @@ +From 355fbcbdc2539cca7890b0d0914d4ce0f985ad74 Mon Sep 17 00:00:00 2001 +From: Sanman Pradhan +Date: Sun, 7 Jun 2026 16:47:34 +0000 +Subject: xfrm: use compat translator only for u64 alignment mismatch + +From: Sanman Pradhan + +commit 355fbcbdc2539cca7890b0d0914d4ce0f985ad74 upstream. + +The XFRM compat layer (CONFIG_XFRM_USER_COMPAT) translates 32-bit xfrm +netlink and setsockopt messages into the native 64-bit layout. It is +only needed on architectures where the 32-bit and 64-bit ABIs disagree +on u64 alignment, which the kernel encodes as COMPAT_FOR_U64_ALIGNMENT. + +That symbol is defined only by arch/x86. XFRM_USER_COMPAT depends on it, +so the translator can never be built on any other architecture, +including arm64, which still provides a 32-bit compat ABI (CONFIG_COMPAT) +for AArch32 EL0 userspace. On arm64 the AArch32 EABI already aligns u64 +to 8 bytes, identical to the AArch64 ABI, so no translation is required +and the native code path is correct for 32-bit tasks. + +However, xfrm_user_rcv_msg() and xfrm_user_policy() gate on +in_compat_syscall() alone and then call xfrm_get_translator(), which +returns NULL when no translator is registered. On arm64 that is always +the case, so every xfrm netlink message and the XFRM_POLICY setsockopt +issued by a 32-bit task returns -EOPNOTSUPP. A 32-bit userspace process +on arm64 (and on any other arch with CONFIG_COMPAT but without +COMPAT_FOR_U64_ALIGNMENT) therefore cannot configure XFRM state or +policy through the XFRM_USER netlink API, and cannot use the XFRM_POLICY +setsockopt path, because both fail before reaching the native parser. + +The translator series replaced the blanket compat rejection with a +translator lookup. That made the path usable on x86 when the translator +is available, but left architectures that cannot build the translator +permanently rejected even when their compat layout already matches the +native layout. Let those architectures use the native parser instead. + +Gate the translator requirement on COMPAT_FOR_U64_ALIGNMENT instead of +on in_compat_syscall() alone. Gating on the ABI property rather than on +CONFIG_XFRM_USER_COMPAT is deliberate: on x86 with IA32_EMULATION=y but +XFRM_USER_COMPAT=n, a 32-bit task must still be rejected rather than +routed through the native parser, which would misread genuinely +4-byte-aligned x86-32 messages. COMPAT_FOR_U64_ALIGNMENT is the ABI +property that makes the XFRM translator mandatory. + +Only the receive/input direction needs the guard. The send, dump and +notification paths already call the translator as "if (xtr) { ... }" +with no error on NULL, so on arches without a translator they no-op and +the kernel emits native 64-bit-layout messages, which is what an AArch32 +task expects. + +Tested on Juniper SRX hardware: with the fix, 32-bit IPsec userspace +netlink and XFRM_POLICY setsockopt operations that previously failed +with -EOPNOTSUPP now succeed; x86 behaviour is unchanged by inspection. + +Fixes: 5106f4a8acff ("xfrm/compat: Add 32=>64-bit messages translator") +Fixes: 96392ee5a13b ("xfrm/compat: Translate 32-bit user_policy from sockptr") +Cc: stable@vger.kernel.org +Signed-off-by: Sanman Pradhan +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/xfrm_state.c | 2 +- + net/xfrm/xfrm_user.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2410,7 +2410,7 @@ int xfrm_user_policy(struct sock *sk, in + if (IS_ERR(data)) + return PTR_ERR(data); + +- if (in_compat_syscall()) { ++ if (IS_ENABLED(CONFIG_COMPAT_FOR_U64_ALIGNMENT) && in_compat_syscall()) { + struct xfrm_translator *xtr = xfrm_get_translator(); + + if (!xtr) { +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -2833,7 +2833,7 @@ static int xfrm_user_rcv_msg(struct sk_b + if (!netlink_net_capable(skb, CAP_NET_ADMIN)) + return -EPERM; + +- if (in_compat_syscall()) { ++ if (IS_ENABLED(CONFIG_COMPAT_FOR_U64_ALIGNMENT) && in_compat_syscall()) { + struct xfrm_translator *xtr = xfrm_get_translator(); + + if (!xtr) diff --git a/queue-5.10/xfrm-xfrm_interface-require-cap_net_admin-in-the-device-netns-for-changelink.patch b/queue-5.10/xfrm-xfrm_interface-require-cap_net_admin-in-the-device-netns-for-changelink.patch new file mode 100644 index 0000000000..5ea5bef79c --- /dev/null +++ b/queue-5.10/xfrm-xfrm_interface-require-cap_net_admin-in-the-device-netns-for-changelink.patch @@ -0,0 +1,44 @@ +From 095515d89b19b6cc19dfcdc846f97403ed1ebce3 Mon Sep 17 00:00:00 2001 +From: Maoyi Xie +Date: Fri, 12 Jun 2026 16:59:41 +0800 +Subject: xfrm: xfrm_interface: require CAP_NET_ADMIN in the device netns for changelink + +From: Maoyi Xie + +commit 095515d89b19b6cc19dfcdc846f97403ed1ebce3 upstream. + +xfrmi_changelink() operates on at most two netns, dev_net(dev) and the +interface link netns xi->net. They differ once the device is created in +or moved to a netns other than the one the request runs in. The rtnl +changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a +caller privileged there but not in xi->net can rewrite an interface that +lives in xi->net. + +Gate xfrmi_changelink() on rtnl_dev_link_net_capable() at its top, +before any attribute is parsed. + +Reported-by: Xiao Liang +Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/ +Fixes: f203b76d7809 ("xfrm: Add virtual xfrm interfaces") +Cc: stable@vger.kernel.org +Signed-off-by: Maoyi Xie +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260612085941.3158249-8-maoyixie.tju@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/xfrm_interface_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/xfrm/xfrm_interface_core.c ++++ b/net/xfrm/xfrm_interface_core.c +@@ -726,6 +726,9 @@ static int xfrmi_changelink(struct net_d + struct net *net = xi->net; + struct xfrm_if_parms p = {}; + ++ if (!rtnl_dev_link_net_capable(dev, net)) ++ return -EPERM; ++ + xfrmi_netlink_parms(data, &p); + if (!p.if_id) { + NL_SET_ERR_MSG(extack, "if_id must be non zero");