From: Greg Kroah-Hartman Date: Tue, 12 May 2026 13:53:46 +0000 (+0200) Subject: 7.0-stable patches X-Git-Tag: v6.12.88~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fdc05059d6fab3fc15998b88c5d0848392ba7b12;p=thirdparty%2Fkernel%2Fstable-queue.git 7.0-stable patches added patches: af_unix-reject-siocatmark-on-non-stream-sockets.patch arm64-fpsimd-ptrace-zero-target-s-fpsimd_state-not-the-tracer-s.patch block-add-pgmap-check-to-biovec_phys_mergeable.patch block-fix-zone-write-plug-removal.patch block-only-read-from-sqe-on-initial-invocation-of-blkdev_uring_cmd.patch cifs-abort-open_cached_dir-if-we-don-t-request-leases.patch cifs-change_conf-needs-to-be-called-for-session-setup.patch clk-imx-imx8-acm-fix-flags-for-acm-clocks.patch clk-microchip-mpfs-ccc-fix-out-of-bounds-access-during-output-registration.patch clk-rk808-fix-of-node-reference-imbalance.patch cpuidle-powerpc-avoid-double-clear-when-breaking-snooze.patch extcon-ptn5150-handle-pending-irq-events-during-system-resume.patch fbcon-avoid-oob-font-access-if-console-rotation-fails.patch gpio-of-clear-of_populated-on-hog-nodes-in-remove-path.patch hv-select-config_sysfb-only-for-config_hyperv_vmbus.patch hv_sock-fix-arm64-support.patch hv_sock-report-eof-instead-of-eio-for-fin.patch hv_sock-return-eio-for-malformed-short-packets.patch hwmon-corsair-psu-close-hid-device-on-probe-errors.patch hwmon-ltc2992-clamp-threshold-writes-to-hardware-range.patch hwmon-ltc2992-fix-u32-overflow-in-power-read-path.patch ibmveth-disable-gso-for-packets-with-small-mss.patch ice-fix-double-free-in-ice_sf_eth_activate-error-path.patch ip6_gre-use-cached-t-net-in-ip6erspan_changelink.patch net-libwx-fix-vf-illegal-register-access.patch net-libwx-use-request_irq-for-vf-misc-interrupt.patch net-rds-handle-zerocopy-send-cleanup-before-the-message-is-queued.patch net-wwan-t7xx-validate-port_count-against-message-length-in-t7xx_port_enum_msg_handler.patch netpoll-pass-buffer-size-to-egress_dev-to-avoid-mac-truncation.patch ovl-fix-verity-lazy-load-guard-broken-by-fsverity_active-semantic-change.patch parisc-fix-irq-leak-in-lasi-driver.patch platform-chrome-cros_ec_typec-init-mutex-in-thunderbolt-registration.patch pmdomain-mediatek-fix-use-after-free-in-scpsys_get_bus_protection_legacy.patch pseries-papr-hvpipe-fix-null-ptr-deref-in-papr_hvpipe_dev_create_handle.patch pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch pseries-papr-hvpipe-fix-simplify-error-handling-in-papr_hvpipe_init.patch pseries-papr-hvpipe-fix-the-usage-of-copy_to_user.patch pseries-papr-hvpipe-prevent-kernel-stack-memory-leak-to-userspace.patch sound-ua101-fix-division-by-zero-at-probe.patch spi-microchip-core-qspi-control-built-in-cs-manually.patch spi-microchip-core-qspi-don-t-attempt-to-transmit-during-emulated-read-only-dual-quad-operations.patch spi-microchip-core-qspi-fix-controller-deregistration.patch spi-microchip-core-spi-fix-controller-deregistration.patch spi-topcliff-pch-fix-controller-deregistration.patch spi-topcliff-pch-fix-use-after-free-on-unbind.patch thermal-core-free-thermal-zone-id-later-during-removal.patch thermal-drivers-sprd-fix-raw-temperature-clamping-in-sprd_thm_rawdata_to_temp.patch thermal-drivers-sprd-fix-temperature-clamping-in-sprd_thm_temp_to_rawdata.patch tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch tracing-fprobe-remove-fprobe-from-hash-in-failure-path.patch tracing-fprobe-unregister-fprobe-even-if-memory-allocation-fails.patch tracing-probes-limit-size-of-event-probe-to-3k.patch udf-reject-descriptors-with-oversized-crc-length.patch x86-boot-e820-re-enable-bios-fallback-if-e820-table-is-empty.patch x86-efi-fix-graceful-fault-handling-after-fpu-softirq-changes.patch --- diff --git a/queue-7.0/af_unix-reject-siocatmark-on-non-stream-sockets.patch b/queue-7.0/af_unix-reject-siocatmark-on-non-stream-sockets.patch new file mode 100644 index 0000000000..15846a18fc --- /dev/null +++ b/queue-7.0/af_unix-reject-siocatmark-on-non-stream-sockets.patch @@ -0,0 +1,48 @@ +From d119775f2bad827edc28071c061fdd4a91f889a5 Mon Sep 17 00:00:00 2001 +From: Jiexun Wang +Date: Wed, 6 May 2026 22:08:23 +0800 +Subject: af_unix: Reject SIOCATMARK on non-stream sockets + +From: Jiexun Wang + +commit d119775f2bad827edc28071c061fdd4a91f889a5 upstream. + +SIOCATMARK reports whether the receive queue is at the urgent mark for +MSG_OOB. + +In AF_UNIX, MSG_OOB is supported only for SOCK_STREAM sockets. +SOCK_DGRAM and SOCK_SEQPACKET reject MSG_OOB in sendmsg() and recvmsg(), +so they should not support SIOCATMARK either. + +Return -EOPNOTSUPP for non-stream sockets before checking the receive +queue. + +Fixes: 314001f0bf92 ("af_unix: Add OOB support") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Suggested-by: Kuniyuki Iwashima +Signed-off-by: Jiexun Wang +Signed-off-by: Ren Wei +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260506140825.2987635-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/unix/af_unix.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -3300,6 +3300,9 @@ static int unix_ioctl(struct socket *soc + struct sk_buff *skb; + int answ = 0; + ++ if (sk->sk_type != SOCK_STREAM) ++ return -EOPNOTSUPP; ++ + mutex_lock(&u->iolock); + + skb = skb_peek(&sk->sk_receive_queue); diff --git a/queue-7.0/arm64-fpsimd-ptrace-zero-target-s-fpsimd_state-not-the-tracer-s.patch b/queue-7.0/arm64-fpsimd-ptrace-zero-target-s-fpsimd_state-not-the-tracer-s.patch new file mode 100644 index 0000000000..dc31b0f7d4 --- /dev/null +++ b/queue-7.0/arm64-fpsimd-ptrace-zero-target-s-fpsimd_state-not-the-tracer-s.patch @@ -0,0 +1,58 @@ +From 5cbb61bf4168859d97c068d88d364f4f1f440325 Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Tue, 5 May 2026 09:02:13 -0700 +Subject: arm64/fpsimd: ptrace: zero target's fpsimd_state, not the tracer's + +From: Breno Leitao + +commit 5cbb61bf4168859d97c068d88d364f4f1f440325 upstream. + +sve_set_common() is the backend for PTRACE_SETREGSET(NT_ARM_SVE) and +PTRACE_SETREGSET(NT_ARM_SSVE). Every write in the function operates on +the tracee (target) - except a single memset that uses current instead, +zeroing the tracer's saved V0-V31 / FPSR / FPCR shadow on every ptrace +SETREGSET call. + +The memset is meant to give the tracee a defined zero register image +before the user-supplied payload is copied in (for partial writes, +header-only writes, and FPSIMD<->SVE format switches). Aiming it at +current both denies the tracee that clean slate and silently corrupts +the tracer. + +The corruption of the tracer's saved FPSIMD state is not always +observable. Where the tracer's state is live on a CPU, this may be +reused without loading the corrupted state from memory, and will +eventually be written back over the corrupted state. Where the tracer's +state is saved in SVE_PT_REGS_SVE format, only the FPSR and FPCR are +clobbered, and the effective copy of the vectors is in the task's +sve_state. + +Reproducible on an arm64 kernel with SVE: a single-threaded tracer that +loads a known pattern into V0-V31, issues PTRACE_SETREGSET(NT_ARM_SVE) +on a child, and reads V0-V31 back observes them all zeroed within tens +of thousands of iterations when a sibling thread keeps stealing the +FPSIMD CPU binding. + +Fixes: 316283f276eb ("arm64/fpsimd: ptrace: Consistently handle partial writes to NT_ARM_(S)SVE") +Cc: +Signed-off-by: Breno Leitao +Acked-by: Mark Rutland +Signed-off-by: Catalin Marinas +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kernel/ptrace.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -983,8 +983,8 @@ static int sve_set_common(struct task_st + } + + /* Always zero V regs, FPSR, and FPCR */ +- memset(¤t->thread.uw.fpsimd_state, 0, +- sizeof(current->thread.uw.fpsimd_state)); ++ memset(&target->thread.uw.fpsimd_state, 0, ++ sizeof(target->thread.uw.fpsimd_state)); + + /* Registers: FPSIMD-only case */ + diff --git a/queue-7.0/block-add-pgmap-check-to-biovec_phys_mergeable.patch b/queue-7.0/block-add-pgmap-check-to-biovec_phys_mergeable.patch new file mode 100644 index 0000000000..30c25546de --- /dev/null +++ b/queue-7.0/block-add-pgmap-check-to-biovec_phys_mergeable.patch @@ -0,0 +1,48 @@ +From 13920e4b7b784b40cf4519ff1f0f3e513476a499 Mon Sep 17 00:00:00 2001 +From: Naman Jain +Date: Fri, 10 Apr 2026 15:34:13 +0000 +Subject: block: add pgmap check to biovec_phys_mergeable + +From: Naman Jain + +commit 13920e4b7b784b40cf4519ff1f0f3e513476a499 upstream. + +biovec_phys_mergeable() is used by the request merge, DMA mapping, +and integrity merge paths to decide if two physically contiguous +bvec segments can be coalesced into one. It currently has no check +for whether the segments belong to different dev_pagemaps. + +When zone device memory is registered in multiple chunks, each chunk +gets its own dev_pagemap. A single bio can legitimately contain +bvecs from different pgmaps -- iov_iter_extract_bvecs() breaks at +pgmap boundaries but the outer loop in bio_iov_iter_get_pages() +continues filling the same bio. If such bvecs are physically +contiguous, biovec_phys_mergeable() will coalesce them, making it +impossible to recover the correct pgmap for the merged segment +via page_pgmap(). + +Add a zone_device_pages_have_same_pgmap() check to prevent merging +bvec segments that span different pgmaps. + +Fixes: 49580e690755 ("block: add check when merging zone device pages") +Cc: stable@vger.kernel.org +Reviewed-by: Christoph Hellwig +Signed-off-by: Naman Jain +Link: https://patch.msgid.link/20260410153414.4159050-2-namjain@linux.microsoft.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/blk.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/block/blk.h ++++ b/block/blk.h +@@ -132,6 +132,8 @@ static inline bool biovec_phys_mergeable + + if (addr1 + vec1->bv_len != addr2) + return false; ++ if (!zone_device_pages_have_same_pgmap(vec1->bv_page, vec2->bv_page)) ++ return false; + if (xen_domain() && !xen_biovec_phys_mergeable(vec1, vec2->bv_page)) + return false; + if ((addr1 | mask) != ((addr2 + vec2->bv_len - 1) | mask)) diff --git a/queue-7.0/block-fix-zone-write-plug-removal.patch b/queue-7.0/block-fix-zone-write-plug-removal.patch new file mode 100644 index 0000000000..30a5b430a9 --- /dev/null +++ b/queue-7.0/block-fix-zone-write-plug-removal.patch @@ -0,0 +1,295 @@ +From b7d4ffb510373cc6ecf16022dd0e510a023034fb Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Fri, 27 Feb 2026 22:19:44 +0900 +Subject: block: fix zone write plug removal + +From: Damien Le Moal + +commit b7d4ffb510373cc6ecf16022dd0e510a023034fb upstream. + +Commit 7b295187287e ("block: Do not remove zone write plugs still in +use") modified disk_should_remove_zone_wplug() to add a check on the +reference count of a zone write plug to prevent removing zone write +plugs from a disk hash table when the plugs are still being referenced +by BIOs or requests in-flight. However, this check does not take into +account that a BIO completion may happen right after its submission by +a zone write plug BIO work, and before the zone write plug BIO work +releases the zone write plug reference count. This situation leads to +disk_should_remove_zone_wplug() returning false as in this case the zone +write plug reference count is at least equal to 3. If the BIO that +completes in such manner transitioned the zone to the FULL condition, +the zone write plug for the FULL zone will remain in the disk hash +table. + +Furthermore, relying on a particular value of a zone write plug +reference count to set the BLK_ZONE_WPLUG_UNHASHED flag is fragile as +reading the atomic reference count and doing a comparison with some +value is not overall atomic at all. + +Address these issues by reworking the reference counting of zone write +plugs so that removing plugs from a disk hash table can be done +directly from disk_put_zone_wplug() when the last reference on a plug +is dropped. + +To do so, replace the function disk_remove_zone_wplug() with +disk_mark_zone_wplug_dead(). This new function sets the zone write plug +flag BLK_ZONE_WPLUG_DEAD (which replaces BLK_ZONE_WPLUG_UNHASHED) and +drops the initial reference on the zone write plug taken when the plug +was added to the disk hash table. This function is called either for +zones that are empty or full, or directly in the case of a forced plug +removal (e.g. when the disk hash table is being destroyed on disk +removal). With this change, disk_should_remove_zone_wplug() is also +removed. + +disk_put_zone_wplug() is modified to call the function +disk_free_zone_wplug() to remove a zone write plug from a disk hash +table and free the plug structure (with a call_rcu()), when the last +reference on a zone write plug is dropped. disk_free_zone_wplug() +always checks that the BLK_ZONE_WPLUG_DEAD flag is set. + +In order to avoid having multiple zone write plugs for the same zone in +the disk hash table, disk_get_and_lock_zone_wplug() checked for the +BLK_ZONE_WPLUG_UNHASHED flag. This check is removed and a check for +the new BLK_ZONE_WPLUG_DEAD flag is added to +blk_zone_wplug_handle_write(). With this change, we continue preventing +adding multiple zone write plugs for the same zone and at the same time +re-inforce checks on the user behavior by failing new incoming write +BIOs targeting a zone that is marked as dead. This case can happen only +if the user erroneously issues write BIOs to zones that are full, or to +zones that are currently being reset or finished. + +Fixes: 7b295187287e ("block: Do not remove zone write plugs still in use") +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-zoned.c | 151 ++++++++++++++++++++---------------------------------- + 1 file changed, 57 insertions(+), 94 deletions(-) + +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -99,17 +99,17 @@ static inline unsigned int disk_zone_wpl + * being executed or the zone write plug bio list is not empty. + * - BLK_ZONE_WPLUG_NEED_WP_UPDATE: Indicates that we lost track of a zone + * write pointer offset and need to update it. +- * - BLK_ZONE_WPLUG_UNHASHED: Indicates that the zone write plug was removed +- * from the disk hash table and that the initial reference to the zone +- * write plug set when the plug was first added to the hash table has been +- * dropped. This flag is set when a zone is reset, finished or become full, +- * to prevent new references to the zone write plug to be taken for +- * newly incoming BIOs. A zone write plug flagged with this flag will be +- * freed once all remaining references from BIOs or functions are dropped. ++ * - BLK_ZONE_WPLUG_DEAD: Indicates that the zone write plug will be ++ * removed from the disk hash table of zone write plugs when the last ++ * reference on the zone write plug is dropped. If set, this flag also ++ * indicates that the initial extra reference on the zone write plug was ++ * dropped, meaning that the reference count indicates the current number of ++ * active users (code context or BIOs and requests in flight). This flag is ++ * set when a zone is reset, finished or becomes full. + */ + #define BLK_ZONE_WPLUG_PLUGGED (1U << 0) + #define BLK_ZONE_WPLUG_NEED_WP_UPDATE (1U << 1) +-#define BLK_ZONE_WPLUG_UNHASHED (1U << 2) ++#define BLK_ZONE_WPLUG_DEAD (1U << 2) + + /** + * blk_zone_cond_str - Return a zone condition name string +@@ -587,64 +587,15 @@ static void disk_free_zone_wplug_rcu(str + mempool_free(zwplug, zwplug->disk->zone_wplugs_pool); + } + +-static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug) +-{ +- if (refcount_dec_and_test(&zwplug->ref)) { +- WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list)); +- WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED); +- WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED)); +- +- call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu); +- } +-} +- +-static inline bool disk_should_remove_zone_wplug(struct gendisk *disk, +- struct blk_zone_wplug *zwplug) +-{ +- lockdep_assert_held(&zwplug->lock); +- +- /* If the zone write plug was already removed, we are done. */ +- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) +- return false; +- +- /* If the zone write plug is still plugged, it cannot be removed. */ +- if (zwplug->flags & BLK_ZONE_WPLUG_PLUGGED) +- return false; +- +- /* +- * Completions of BIOs with blk_zone_write_plug_bio_endio() may +- * happen after handling a request completion with +- * blk_zone_write_plug_finish_request() (e.g. with split BIOs +- * that are chained). In such case, disk_zone_wplug_unplug_bio() +- * should not attempt to remove the zone write plug until all BIO +- * completions are seen. Check by looking at the zone write plug +- * reference count, which is 2 when the plug is unused (one reference +- * taken when the plug was allocated and another reference taken by the +- * caller context). +- */ +- if (refcount_read(&zwplug->ref) > 2) +- return false; +- +- /* We can remove zone write plugs for zones that are empty or full. */ +- return !zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug); +-} +- +-static void disk_remove_zone_wplug(struct gendisk *disk, +- struct blk_zone_wplug *zwplug) ++static void disk_free_zone_wplug(struct blk_zone_wplug *zwplug) + { ++ struct gendisk *disk = zwplug->disk; + unsigned long flags; + +- /* If the zone write plug was already removed, we have nothing to do. */ +- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) +- return; ++ WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)); ++ WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED); ++ WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list)); + +- /* +- * Mark the zone write plug as unhashed and drop the extra reference we +- * took when the plug was inserted in the hash table. Also update the +- * disk zone condition array with the current condition of the zone +- * write plug. +- */ +- zwplug->flags |= BLK_ZONE_WPLUG_UNHASHED; + spin_lock_irqsave(&disk->zone_wplugs_lock, flags); + blk_zone_set_cond(rcu_dereference_check(disk->zones_cond, + lockdep_is_held(&disk->zone_wplugs_lock)), +@@ -652,7 +603,29 @@ static void disk_remove_zone_wplug(struc + hlist_del_init_rcu(&zwplug->node); + atomic_dec(&disk->nr_zone_wplugs); + spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags); +- disk_put_zone_wplug(zwplug); ++ ++ call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu); ++} ++ ++static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug) ++{ ++ if (refcount_dec_and_test(&zwplug->ref)) ++ disk_free_zone_wplug(zwplug); ++} ++ ++/* ++ * Flag the zone write plug as dead and drop the initial reference we got when ++ * the zone write plug was added to the hash table. The zone write plug will be ++ * unhashed when its last reference is dropped. ++ */ ++static void disk_mark_zone_wplug_dead(struct blk_zone_wplug *zwplug) ++{ ++ lockdep_assert_held(&zwplug->lock); ++ ++ if (!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)) { ++ zwplug->flags |= BLK_ZONE_WPLUG_DEAD; ++ disk_put_zone_wplug(zwplug); ++ } + } + + static void blk_zone_wplug_bio_work(struct work_struct *work); +@@ -672,18 +645,7 @@ static struct blk_zone_wplug *disk_get_a + again: + zwplug = disk_get_zone_wplug(disk, sector); + if (zwplug) { +- /* +- * Check that a BIO completion or a zone reset or finish +- * operation has not already removed the zone write plug from +- * the hash table and dropped its reference count. In such case, +- * we need to get a new plug so start over from the beginning. +- */ + spin_lock_irqsave(&zwplug->lock, *flags); +- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) { +- spin_unlock_irqrestore(&zwplug->lock, *flags); +- disk_put_zone_wplug(zwplug); +- goto again; +- } + return zwplug; + } + +@@ -788,14 +750,8 @@ static void disk_zone_wplug_set_wp_offse + disk_zone_wplug_update_cond(disk, zwplug); + + disk_zone_wplug_abort(zwplug); +- +- /* +- * The zone write plug now has no BIO plugged: remove it from the +- * hash table so that it cannot be seen. The plug will be freed +- * when the last reference is dropped. +- */ +- if (disk_should_remove_zone_wplug(disk, zwplug)) +- disk_remove_zone_wplug(disk, zwplug); ++ if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug)) ++ disk_mark_zone_wplug_dead(zwplug); + } + + static unsigned int blk_zone_wp_offset(struct blk_zone *zone) +@@ -1451,6 +1407,19 @@ static bool blk_zone_wplug_handle_write( + return true; + } + ++ /* ++ * If we got a zone write plug marked as dead, then the user is issuing ++ * writes to a full zone, or without synchronizing with zone reset or ++ * zone finish operations. In such case, fail the BIO to signal this ++ * invalid usage. ++ */ ++ if (zwplug->flags & BLK_ZONE_WPLUG_DEAD) { ++ spin_unlock_irqrestore(&zwplug->lock, flags); ++ disk_put_zone_wplug(zwplug); ++ bio_io_error(bio); ++ return true; ++ } ++ + /* Indicate that this BIO is being handled using zone write plugging. */ + bio_set_flag(bio, BIO_ZONE_WRITE_PLUGGING); + +@@ -1531,7 +1500,7 @@ static void blk_zone_wplug_handle_native + disk->disk_name, zwplug->zone_no); + disk_zone_wplug_abort(zwplug); + } +- disk_remove_zone_wplug(disk, zwplug); ++ disk_mark_zone_wplug_dead(zwplug); + spin_unlock_irqrestore(&zwplug->lock, flags); + + disk_put_zone_wplug(zwplug); +@@ -1634,14 +1603,8 @@ static void disk_zone_wplug_unplug_bio(s + } + + zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED; +- +- /* +- * If the zone is full (it was fully written or finished, or empty +- * (it was reset), remove its zone write plug from the hash table. +- */ +- if (disk_should_remove_zone_wplug(disk, zwplug)) +- disk_remove_zone_wplug(disk, zwplug); +- ++ if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug)) ++ disk_mark_zone_wplug_dead(zwplug); + spin_unlock_irqrestore(&zwplug->lock, flags); + } + +@@ -1852,9 +1815,9 @@ static void disk_destroy_zone_wplugs_has + while (!hlist_empty(&disk->zone_wplugs_hash[i])) { + zwplug = hlist_entry(disk->zone_wplugs_hash[i].first, + struct blk_zone_wplug, node); +- refcount_inc(&zwplug->ref); +- disk_remove_zone_wplug(disk, zwplug); +- disk_put_zone_wplug(zwplug); ++ spin_lock_irq(&zwplug->lock); ++ disk_mark_zone_wplug_dead(zwplug); ++ spin_unlock_irq(&zwplug->lock); + } + } + diff --git a/queue-7.0/block-only-read-from-sqe-on-initial-invocation-of-blkdev_uring_cmd.patch b/queue-7.0/block-only-read-from-sqe-on-initial-invocation-of-blkdev_uring_cmd.patch new file mode 100644 index 0000000000..3e69bc1d97 --- /dev/null +++ b/queue-7.0/block-only-read-from-sqe-on-initial-invocation-of-blkdev_uring_cmd.patch @@ -0,0 +1,71 @@ +From 212ec34e4e726e8cd4af7bea4740db24de8a9dab Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 4 May 2026 08:34:32 -0600 +Subject: block: only read from sqe on initial invocation of blkdev_uring_cmd() + +From: Jens Axboe + +commit 212ec34e4e726e8cd4af7bea4740db24de8a9dab upstream. + +This passthrough helper currently only supports discards. Part of that +command is the start and length, which is read from the SQE. It does +so on every invocation, where it really should just make it stable +on the first invocation. This avoids needing to copy the SQE upfront, +as we only really need those two 8b values stored in our per-req +payload. + +Cc: stable@vger.kernel.org # 6.17+ +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/ioctl.c | 24 +++++++++++++++--------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -864,6 +864,8 @@ long compat_blkdev_ioctl(struct file *fi + #endif + + struct blk_iou_cmd { ++ u64 start; ++ u64 len; + int res; + bool nowait; + }; +@@ -953,23 +955,27 @@ int blkdev_uring_cmd(struct io_uring_cmd + { + struct block_device *bdev = I_BDEV(cmd->file->f_mapping->host); + struct blk_iou_cmd *bic = io_uring_cmd_to_pdu(cmd, struct blk_iou_cmd); +- const struct io_uring_sqe *sqe = cmd->sqe; + u32 cmd_op = cmd->cmd_op; +- uint64_t start, len; + +- if (unlikely(sqe->ioprio || sqe->__pad1 || sqe->len || +- sqe->rw_flags || sqe->file_index)) +- return -EINVAL; ++ /* Read what we need from the SQE on the first issue */ ++ if (!(issue_flags & IORING_URING_CMD_REISSUE)) { ++ const struct io_uring_sqe *sqe = cmd->sqe; ++ ++ if (unlikely(sqe->ioprio || sqe->__pad1 || sqe->len || ++ sqe->rw_flags || sqe->file_index)) ++ return -EINVAL; ++ ++ bic->start = READ_ONCE(sqe->addr); ++ bic->len = READ_ONCE(sqe->addr3); ++ } + + bic->res = 0; + bic->nowait = issue_flags & IO_URING_F_NONBLOCK; + +- start = READ_ONCE(sqe->addr); +- len = READ_ONCE(sqe->addr3); +- + switch (cmd_op) { + case BLOCK_URING_CMD_DISCARD: +- return blkdev_cmd_discard(cmd, bdev, start, len, bic->nowait); ++ return blkdev_cmd_discard(cmd, bdev, bic->start, bic->len, ++ bic->nowait); + } + return -EINVAL; + } diff --git a/queue-7.0/cifs-abort-open_cached_dir-if-we-don-t-request-leases.patch b/queue-7.0/cifs-abort-open_cached_dir-if-we-don-t-request-leases.patch new file mode 100644 index 0000000000..736c0b19a9 --- /dev/null +++ b/queue-7.0/cifs-abort-open_cached_dir-if-we-don-t-request-leases.patch @@ -0,0 +1,46 @@ +From d68ce834f8cf6cb2e77f3331df65166b35466b53 Mon Sep 17 00:00:00 2001 +From: Shyam Prasad N +Date: Tue, 28 Apr 2026 21:37:47 +0530 +Subject: cifs: abort open_cached_dir if we don't request leases + +From: Shyam Prasad N + +commit d68ce834f8cf6cb2e77f3331df65166b35466b53 upstream. + +It is possible that SMB2_open_init may not set lease context based +on the requested oplock level. This can happen when leases have been +temporarily or permanently disabled. When this happens, we will have +open_cached_dir making an open without lease context and the response +will anyway be rejected by open_cached_dir (thereby forcing a close to +discard this open). That's unnecessary two round-trips to the server. + +This change adds a check before making the open request to the server +to make sure that SMB2_open_init did add the expected lease context +to the open in open_cached_dir. + +Cc: +Reviewed-by: Bharath SM +Signed-off-by: Shyam Prasad N +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/cached_dir.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/smb/client/cached_dir.c ++++ b/fs/smb/client/cached_dir.c +@@ -286,6 +286,14 @@ replay_again: + &rqst[0], &oplock, &oparms, utf16_path); + if (rc) + goto oshr_free; ++ ++ if (oplock != SMB2_OPLOCK_LEVEL_II) { ++ rc = -EINVAL; ++ cifs_dbg(FYI, "%s: Oplock level %d not suitable for cached directory\n", ++ __func__, oplock); ++ goto oshr_free; ++ } ++ + smb2_set_next_command(tcon, &rqst[0]); + + memset(&qi_iov, 0, sizeof(qi_iov)); diff --git a/queue-7.0/cifs-change_conf-needs-to-be-called-for-session-setup.patch b/queue-7.0/cifs-change_conf-needs-to-be-called-for-session-setup.patch new file mode 100644 index 0000000000..356c3f1756 --- /dev/null +++ b/queue-7.0/cifs-change_conf-needs-to-be-called-for-session-setup.patch @@ -0,0 +1,54 @@ +From c208a2b95811d6e1ebae65d0d2fc13f73707f8e7 Mon Sep 17 00:00:00 2001 +From: Shyam Prasad N +Date: Mon, 30 Mar 2026 16:19:59 +0530 +Subject: cifs: change_conf needs to be called for session setup + +From: Shyam Prasad N + +commit c208a2b95811d6e1ebae65d0d2fc13f73707f8e7 upstream. + +Today we skip calling change_conf for negotiates and session setup +requests. This can be a problem for mchan as the immediate next call +after session setup could be due to an I/O that is made on the +mount point. For single channel, this is not a problem as +there will be several calls after setting up session. + +This change enforces calling change_conf when the total credits contain +enough for reservations for echoes and oplocks. We expect this to happen +during the last session setup response. This way, echoes and oplocks are +not disabled before the first request to the server. So if that first +request is an open, it does not need to disable requesting leases. + +Cc: +Reviewed-by: Bharath SM +Signed-off-by: Shyam Prasad N +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/smb2ops.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -111,10 +111,21 @@ smb2_add_credits(struct TCP_Server_Info + cifs_trace_rw_credits_zero_in_flight); + } + server->in_flight--; ++ ++ /* ++ * Rebalance credits when an op drains in_flight. For session setup, ++ * do this only when the total accumulated credits are high enough (>2) ++ * so that a newly established secondary channel can reserve credits for ++ * echoes and oplocks. We expect this to happen at the end of the final ++ * session setup response. ++ */ + if (server->in_flight == 0 && + ((optype & CIFS_OP_MASK) != CIFS_NEG_OP) && + ((optype & CIFS_OP_MASK) != CIFS_SESS_OP)) + rc = change_conf(server); ++ else if (server->in_flight == 0 && ++ ((optype & CIFS_OP_MASK) == CIFS_SESS_OP) && *val > 2) ++ rc = change_conf(server); + /* + * Sometimes server returns 0 credits on oplock break ack - we need to + * rebalance credits in this case. diff --git a/queue-7.0/clk-imx-imx8-acm-fix-flags-for-acm-clocks.patch b/queue-7.0/clk-imx-imx8-acm-fix-flags-for-acm-clocks.patch new file mode 100644 index 0000000000..0cbb799f52 --- /dev/null +++ b/queue-7.0/clk-imx-imx8-acm-fix-flags-for-acm-clocks.patch @@ -0,0 +1,45 @@ +From f2c2fc93b4a3efdfcf3805ab74741826d343ff2c Mon Sep 17 00:00:00 2001 +From: Stefan Eichenberger +Date: Thu, 12 Feb 2026 16:57:50 +0800 +Subject: clk: imx: imx8-acm: fix flags for acm clocks + +From: Stefan Eichenberger + +commit f2c2fc93b4a3efdfcf3805ab74741826d343ff2c upstream. + +Currently, the flags for the ACM clocks are set to 0. This configuration +causes the fsl-sai audio driver to fail when attempting to set the +sysclk, returning an EINVAL error. The following error messages +highlight the issue: +fsl-sai 59090000.sai: ASoC: error at snd_soc_dai_set_sysclk on 59090000.sai: -22 +imx-hdmi sound-hdmi: failed to set cpu sysclk: -22 + +By setting the flag CLK_SET_RATE_NO_REPARENT, we signal that the ACM +driver does not support reparenting and instead relies on the clock tree +as defined in the device tree. This change resolves the issue with the +fsl-sai audio driver. + +CC: stable@vger.kernel.org +Fixes: d3a0946d7ac9 ("clk: imx: imx8: add audio clock mux driver") +Signed-off-by: Stefan Eichenberger +Signed-off-by: Shengjiu Wang +Reviewed-by: Peng Fan +Link: https://patch.msgid.link/20260212085750.3253187-1-shengjiu.wang@nxp.com +Signed-off-by: Abel Vesa +Signed-off-by: Greg Kroah-Hartman +--- + drivers/clk/imx/clk-imx8-acm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/clk/imx/clk-imx8-acm.c ++++ b/drivers/clk/imx/clk-imx8-acm.c +@@ -371,7 +371,8 @@ static int imx8_acm_clk_probe(struct pla + for (i = 0; i < priv->soc_data->num_sels; i++) { + hws[sels[i].clkid] = devm_clk_hw_register_mux_parent_data_table(dev, + sels[i].name, sels[i].parents, +- sels[i].num_parents, 0, ++ sels[i].num_parents, ++ CLK_SET_RATE_NO_REPARENT, + base + sels[i].reg, + sels[i].shift, sels[i].width, + 0, NULL, NULL); diff --git a/queue-7.0/clk-microchip-mpfs-ccc-fix-out-of-bounds-access-during-output-registration.patch b/queue-7.0/clk-microchip-mpfs-ccc-fix-out-of-bounds-access-during-output-registration.patch new file mode 100644 index 0000000000..71b3902fc5 --- /dev/null +++ b/queue-7.0/clk-microchip-mpfs-ccc-fix-out-of-bounds-access-during-output-registration.patch @@ -0,0 +1,48 @@ +From 2f7ae8ab6aa73daaf080d5332110357c29df9c36 Mon Sep 17 00:00:00 2001 +From: Conor Dooley +Date: Tue, 24 Feb 2026 09:35:25 +0000 +Subject: clk: microchip: mpfs-ccc: fix out of bounds access during output registration + +From: Conor Dooley + +commit 2f7ae8ab6aa73daaf080d5332110357c29df9c36 upstream. + +UBSAN reported an out of bounds access during registration of the last +two outputs. This out of bounds access occurs because space is only +allocated in the hws array for two PLLs and the four output dividers +that each has, but the defined IDs contain two DLLS and their two +outputs each, which are not supported by the driver. The ID order is +PLLs -> DLLs -> PLL outputs -> DLL outputs. Decrement the PLL output IDs +by two while adding them to the array to avoid the problem. + +Fixes: d39fb172760e ("clk: microchip: add PolarFire SoC fabric clock support") +CC: stable@vger.kernel.org +Reviewed-by: Brian Masney +Signed-off-by: Conor Dooley +Signed-off-by: Greg Kroah-Hartman +--- + drivers/clk/microchip/clk-mpfs-ccc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/clk/microchip/clk-mpfs-ccc.c ++++ b/drivers/clk/microchip/clk-mpfs-ccc.c +@@ -178,7 +178,7 @@ static int mpfs_ccc_register_outputs(str + return dev_err_probe(dev, ret, "failed to register clock id: %d\n", + out_hw->id); + +- data->hw_data.hws[out_hw->id] = &out_hw->divider.hw; ++ data->hw_data.hws[out_hw->id - 2] = &out_hw->divider.hw; + } + + return 0; +@@ -234,6 +234,10 @@ static int mpfs_ccc_probe(struct platfor + unsigned int num_clks; + int ret; + ++ /* ++ * If DLLs get added here, mpfs_ccc_register_outputs() currently packs ++ * sparse clock IDs in the hws array ++ */ + num_clks = ARRAY_SIZE(mpfs_ccc_pll_clks) + ARRAY_SIZE(mpfs_ccc_pll0out_clks) + + ARRAY_SIZE(mpfs_ccc_pll1out_clks); + diff --git a/queue-7.0/clk-rk808-fix-of-node-reference-imbalance.patch b/queue-7.0/clk-rk808-fix-of-node-reference-imbalance.patch new file mode 100644 index 0000000000..f56371592d --- /dev/null +++ b/queue-7.0/clk-rk808-fix-of-node-reference-imbalance.patch @@ -0,0 +1,40 @@ +From de019f203b0d472c98ead4081ad4f05d92c9b826 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 7 Apr 2026 11:50:27 +0200 +Subject: clk: rk808: fix OF node reference imbalance + +From: Johan Hovold + +commit de019f203b0d472c98ead4081ad4f05d92c9b826 upstream. + +The driver reuses the OF node of the parent multi-function device but +fails to take another reference to balance the one dropped by the +platform bus code when unbinding the MFD and deregistering the child +devices. + +Fix this by using the intended helper for reusing OF nodes. + +Fixes: 2dc51ca822e4 ("clk: RK808: Reduce 'struct rk808' usage") +Cc: stable@vger.kernel.org # 6.5 +Cc: Sebastian Reichel +Signed-off-by: Johan Hovold +Reviewed-by: Sebastian Reichel +Reviewed-by: Brian Masney +Reviewed-by: Heiko Stuebner +Signed-off-by: Stephen Boyd +Signed-off-by: Greg Kroah-Hartman +--- + drivers/clk/clk-rk808.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/clk-rk808.c ++++ b/drivers/clk/clk-rk808.c +@@ -153,7 +153,7 @@ static int rk808_clkout_probe(struct pla + struct rk808_clkout *rk808_clkout; + int ret; + +- dev->of_node = pdev->dev.parent->of_node; ++ device_set_of_node_from_dev(dev, dev->parent); + + rk808_clkout = devm_kzalloc(dev, + sizeof(*rk808_clkout), GFP_KERNEL); diff --git a/queue-7.0/cpuidle-powerpc-avoid-double-clear-when-breaking-snooze.patch b/queue-7.0/cpuidle-powerpc-avoid-double-clear-when-breaking-snooze.patch new file mode 100644 index 0000000000..f31abb8d91 --- /dev/null +++ b/queue-7.0/cpuidle-powerpc-avoid-double-clear-when-breaking-snooze.patch @@ -0,0 +1,59 @@ +From 64ed1e3e728afb57ba9acb59e69de930ead847d9 Mon Sep 17 00:00:00 2001 +From: Shrikanth Hegde +Date: Wed, 11 Mar 2026 11:47:09 +0530 +Subject: cpuidle: powerpc: avoid double clear when breaking snooze + +From: Shrikanth Hegde + +commit 64ed1e3e728afb57ba9acb59e69de930ead847d9 upstream. + +snooze_loop is done often in any system which has fair bit of +idle time. So it qualifies for even micro-optimizations. + +When breaking the snooze due to timeout, TIF_POLLING_NRFLAG is cleared +twice. Clearing the bit invokes atomics. Avoid double clear and thereby +avoid one atomic write. + +dev->poll_time_limit indicates whether the loop was broken due to +timeout. Use that instead of defining a new variable. + +Fixes: 7ded429152e8 ("cpuidle: powerpc: no memory barrier after break from idle") +Cc: stable@vger.kernel.org +Reviewed-by: Mukesh Kumar Chaurasiya (IBM) +Signed-off-by: Shrikanth Hegde +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260311061709.1230440-1-sshegde@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/cpuidle/cpuidle-powernv.c | 5 ++++- + drivers/cpuidle/cpuidle-pseries.c | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/cpuidle/cpuidle-powernv.c ++++ b/drivers/cpuidle/cpuidle-powernv.c +@@ -95,7 +95,10 @@ static int snooze_loop(struct cpuidle_de + + HMT_medium(); + ppc64_runlatch_on(); +- clear_thread_flag(TIF_POLLING_NRFLAG); ++ ++ /* Avoid double clear when breaking */ ++ if (!dev->poll_time_limit) ++ clear_thread_flag(TIF_POLLING_NRFLAG); + + local_irq_disable(); + +--- a/drivers/cpuidle/cpuidle-pseries.c ++++ b/drivers/cpuidle/cpuidle-pseries.c +@@ -64,7 +64,10 @@ int snooze_loop(struct cpuidle_device *d + } + + HMT_medium(); +- clear_thread_flag(TIF_POLLING_NRFLAG); ++ ++ /* Avoid double clear when breaking */ ++ if (!dev->poll_time_limit) ++ clear_thread_flag(TIF_POLLING_NRFLAG); + + raw_local_irq_disable(); + diff --git a/queue-7.0/extcon-ptn5150-handle-pending-irq-events-during-system-resume.patch b/queue-7.0/extcon-ptn5150-handle-pending-irq-events-during-system-resume.patch new file mode 100644 index 0000000000..fc9a972c4f --- /dev/null +++ b/queue-7.0/extcon-ptn5150-handle-pending-irq-events-during-system-resume.patch @@ -0,0 +1,58 @@ +From 4652fefcda3c604c83d1ae28ede94544e2142f06 Mon Sep 17 00:00:00 2001 +From: Xu Yang +Date: Sat, 15 Nov 2025 10:59:05 +0800 +Subject: extcon: ptn5150: handle pending IRQ events during system resume + +From: Xu Yang + +commit 4652fefcda3c604c83d1ae28ede94544e2142f06 upstream. + +When the system is suspended and ptn5150 wakeup interrupt is disabled, +any changes on ptn5150 will only be record in interrupt status +registers and won't fire an IRQ since its trigger type is falling +edge. So the HW interrupt line will keep at low state and any further +changes won't trigger IRQ anymore. To fix it, this will schedule a +work to check whether any IRQ are pending and handle it accordingly. + +Fixes: 4ed754de2d66 ("extcon: Add support for ptn5150 extcon driver") +Cc: stable@vger.kernel.org +Reviewed-by: Krzysztof Kozlowski +Acked-by: MyungJoo Ham +Signed-off-by: Xu Yang +Signed-off-by: Chanwoo Choi +Link: https://lore.kernel.org/lkml/20251115025905.1395347-1-xu.yang_2@nxp.com/ +Signed-off-by: Greg Kroah-Hartman +--- + drivers/extcon/extcon-ptn5150.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/extcon/extcon-ptn5150.c ++++ b/drivers/extcon/extcon-ptn5150.c +@@ -331,6 +331,19 @@ static int ptn5150_i2c_probe(struct i2c_ + return 0; + } + ++static int ptn5150_resume(struct device *dev) ++{ ++ struct i2c_client *i2c = to_i2c_client(dev); ++ struct ptn5150_info *info = i2c_get_clientdata(i2c); ++ ++ /* Need to check possible pending interrupt events */ ++ schedule_work(&info->irq_work); ++ ++ return 0; ++} ++ ++static DEFINE_SIMPLE_DEV_PM_OPS(ptn5150_pm_ops, NULL, ptn5150_resume); ++ + static const struct of_device_id ptn5150_dt_match[] = { + { .compatible = "nxp,ptn5150" }, + { }, +@@ -346,6 +359,7 @@ MODULE_DEVICE_TABLE(i2c, ptn5150_i2c_id) + static struct i2c_driver ptn5150_i2c_driver = { + .driver = { + .name = "ptn5150", ++ .pm = pm_sleep_ptr(&ptn5150_pm_ops), + .of_match_table = ptn5150_dt_match, + }, + .probe = ptn5150_i2c_probe, diff --git a/queue-7.0/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch b/queue-7.0/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch new file mode 100644 index 0000000000..282a2cca43 --- /dev/null +++ b/queue-7.0/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch @@ -0,0 +1,51 @@ +From e4ef723d8975a2694cc90733a6b888a5e2841842 Mon Sep 17 00:00:00 2001 +From: Thomas Zimmermann +Date: Tue, 7 Apr 2026 11:23:12 +0200 +Subject: fbcon: Avoid OOB font access if console rotation fails + +From: Thomas Zimmermann + +commit e4ef723d8975a2694cc90733a6b888a5e2841842 upstream. + +Clear the font buffer if the reallocation during console rotation fails +in fbcon_rotate_font(). The putcs implementations for the rotated buffer +will return early in this case. See [1] for an example. + +Currently, fbcon_rotate_font() keeps the old buffer, which is too small +for the rotated font. Printing to the rotated console with a high-enough +character code will overflow the font buffer. + +v2: +- fix typos in commit message + +Signed-off-by: Thomas Zimmermann +Fixes: 6cc50e1c5b57 ("[PATCH] fbcon: Console Rotation - Add support to rotate font bitmap") +Cc: stable@vger.kernel.org # v2.6.15+ +Link: https://elixir.bootlin.com/linux/v6.19/source/drivers/video/fbdev/core/fbcon_ccw.c#L144 # [1] +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/core/fbcon_rotate.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/video/fbdev/core/fbcon_rotate.c ++++ b/drivers/video/fbdev/core/fbcon_rotate.c +@@ -46,6 +46,10 @@ int fbcon_rotate_font(struct fb_info *in + info->fbops->fb_sync(info); + + if (par->fd_size < d_cellsize * len) { ++ kfree(par->fontbuffer); ++ par->fontbuffer = NULL; ++ par->fd_size = 0; ++ + dst = kmalloc_array(len, d_cellsize, GFP_KERNEL); + + if (dst == NULL) { +@@ -54,7 +58,6 @@ int fbcon_rotate_font(struct fb_info *in + } + + par->fd_size = d_cellsize * len; +- kfree(par->fontbuffer); + par->fontbuffer = dst; + } + diff --git a/queue-7.0/gpio-of-clear-of_populated-on-hog-nodes-in-remove-path.patch b/queue-7.0/gpio-of-clear-of_populated-on-hog-nodes-in-remove-path.patch new file mode 100644 index 0000000000..52e9b6f26a --- /dev/null +++ b/queue-7.0/gpio-of-clear-of_populated-on-hog-nodes-in-remove-path.patch @@ -0,0 +1,41 @@ +From bbee90e750262bfb406d66dc65c46d616d2b6673 Mon Sep 17 00:00:00 2001 +From: Bartosz Golaszewski +Date: Mon, 9 Mar 2026 13:42:37 +0100 +Subject: gpio: of: clear OF_POPULATED on hog nodes in remove path + +From: Bartosz Golaszewski + +commit bbee90e750262bfb406d66dc65c46d616d2b6673 upstream. + +The previously set OF_POPULATED flag should be cleared on the hog nodes +when removing the chip. + +Cc: stable@vger.kernel.org +Fixes: 63636d956c455 ("gpio: of: Add DT overlay support for GPIO hogs") +Acked-by: Linus Walleij +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260309-gpio-hog-fwnode-v2-1-4e61f3dbf06a@oss.qualcomm.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpio/gpiolib-of.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -1210,7 +1210,14 @@ int of_gpiochip_add(struct gpio_chip *ch + + void of_gpiochip_remove(struct gpio_chip *chip) + { +- of_node_put(dev_of_node(&chip->gpiodev->dev)); ++ struct device_node *np = dev_of_node(&chip->gpiodev->dev); ++ ++ for_each_child_of_node_scoped(np, child) { ++ if (of_property_present(child, "gpio-hog")) ++ of_node_clear_flag(child, OF_POPULATED); ++ } ++ ++ of_node_put(np); + } + + bool of_gpiochip_instance_match(struct gpio_chip *gc, unsigned int index) diff --git a/queue-7.0/hv-select-config_sysfb-only-for-config_hyperv_vmbus.patch b/queue-7.0/hv-select-config_sysfb-only-for-config_hyperv_vmbus.patch new file mode 100644 index 0000000000..49a7c80590 --- /dev/null +++ b/queue-7.0/hv-select-config_sysfb-only-for-config_hyperv_vmbus.patch @@ -0,0 +1,49 @@ +From d33db956c9618e7cb08c2520ce708437914214ec Mon Sep 17 00:00:00 2001 +From: Thomas Zimmermann +Date: Thu, 2 Apr 2026 11:09:15 +0200 +Subject: hv: Select CONFIG_SYSFB only for CONFIG_HYPERV_VMBUS + +From: Thomas Zimmermann + +commit d33db956c9618e7cb08c2520ce708437914214ec upstream. + +Hyperv's sysfb access only exists in the VMBUS support. Therefore +only select CONFIG_SYSFB for CONFIG_HYPERV_VMBUS. Avoids sysfb code +on systems that don't need it. + +Signed-off-by: Thomas Zimmermann +Fixes: 96959283a58d ("Drivers: hv: Always select CONFIG_SYSFB for Hyper-V guests") +Cc: Michael Kelley +Cc: Saurabh Sengar +Cc: Wei Liu +Cc: "K. Y. Srinivasan" +Cc: Haiyang Zhang +Cc: Dexuan Cui +Cc: Long Li +Cc: linux-hyperv@vger.kernel.org +Cc: # v6.16+ +Reviewed-by: Saurabh Sengar +Link: https://patch.msgid.link/20260402092305.208728-2-tzimmermann@suse.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hv/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hv/Kconfig ++++ b/drivers/hv/Kconfig +@@ -9,7 +9,6 @@ config HYPERV + select PARAVIRT + select X86_HV_CALLBACK_VECTOR if X86 + select OF_EARLY_FLATTREE if OF +- select SYSFB if EFI && !HYPERV_VTL_MODE + select IRQ_MSI_LIB if X86 + help + Select this option to run Linux as a Hyper-V client operating +@@ -62,6 +61,7 @@ config HYPERV_VMBUS + tristate "Microsoft Hyper-V VMBus driver" + depends on HYPERV + default HYPERV ++ select SYSFB if EFI && !HYPERV_VTL_MODE + help + Select this option to enable Hyper-V Vmbus driver. + diff --git a/queue-7.0/hv_sock-fix-arm64-support.patch b/queue-7.0/hv_sock-fix-arm64-support.patch new file mode 100644 index 0000000000..360d3575d2 --- /dev/null +++ b/queue-7.0/hv_sock-fix-arm64-support.patch @@ -0,0 +1,42 @@ +From b31681206e3f527970a7c7ed807fbf6a028fc25b Mon Sep 17 00:00:00 2001 +From: Hamza Mahfooz +Date: Tue, 28 Apr 2026 08:53:39 -0400 +Subject: hv_sock: fix ARM64 support + +From: Hamza Mahfooz + +commit b31681206e3f527970a7c7ed807fbf6a028fc25b upstream. + +VMBUS ring buffers must be page aligned. Therefore, the current value of +24K presents a challenge on ARM64 kernels (with 64K pages). So, use +VMBUS_RING_SIZE() to ensure they are always aligned and large enough to +hold all of the relevant data. + +Cc: stable@vger.kernel.org +Fixes: 77ffe33363c0 ("hv_sock: use HV_HYP_PAGE_SIZE for Hyper-V communication") +Tested-by: Dexuan Cui +Reviewed-by: Dexuan Cui +Signed-off-by: Hamza Mahfooz +Acked-by: Stefano Garzarella +Link: https://patch.msgid.link/20260428125339.13963-1-hamzamahfooz@linux.microsoft.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/vmw_vsock/hyperv_transport.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/vmw_vsock/hyperv_transport.c ++++ b/net/vmw_vsock/hyperv_transport.c +@@ -375,10 +375,10 @@ static void hvs_open_connection(struct v + } else { + sndbuf = max_t(int, sk->sk_sndbuf, RINGBUFFER_HVS_SND_SIZE); + sndbuf = min_t(int, sndbuf, RINGBUFFER_HVS_MAX_SIZE); +- sndbuf = ALIGN(sndbuf, HV_HYP_PAGE_SIZE); ++ sndbuf = VMBUS_RING_SIZE(sndbuf); + rcvbuf = max_t(int, sk->sk_rcvbuf, RINGBUFFER_HVS_RCV_SIZE); + rcvbuf = min_t(int, rcvbuf, RINGBUFFER_HVS_MAX_SIZE); +- rcvbuf = ALIGN(rcvbuf, HV_HYP_PAGE_SIZE); ++ rcvbuf = VMBUS_RING_SIZE(rcvbuf); + } + + chan->max_pkt_size = HVS_MAX_PKT_SIZE; diff --git a/queue-7.0/hv_sock-report-eof-instead-of-eio-for-fin.patch b/queue-7.0/hv_sock-report-eof-instead-of-eio-for-fin.patch new file mode 100644 index 0000000000..7d5f54d806 --- /dev/null +++ b/queue-7.0/hv_sock-report-eof-instead-of-eio-for-fin.patch @@ -0,0 +1,68 @@ +From f6315295899415f1ddcf39f7c9cb46d25e2c6c6a Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Thu, 16 Apr 2026 12:14:33 -0700 +Subject: hv_sock: Report EOF instead of -EIO for FIN + +From: Dexuan Cui + +commit f6315295899415f1ddcf39f7c9cb46d25e2c6c6a upstream. + +Commit f0c5827d07cb unluckily causes a regression for the FIN packet, +and the final read syscall gets an error rather than 0. + +Ideally, we would want to fix hvs_channel_readable_payload() so that it +could return 0 in the FIN scenario, but it's not good for the hv_sock +driver to use the VMBus ringbuffer's cached priv_read_index, which is +internal data in the VMBus driver. + +Fix the regression in hv_sock by returning 0 rather than -EIO. + +Fixes: f0c5827d07cb ("hv_sock: Return the readable bytes in hvs_stream_has_data()") +Cc: stable@vger.kernel.org +Reported-by: Ben Hillis +Reported-by: Mitchell Levy +Signed-off-by: Dexuan Cui +Acked-by: Stefano Garzarella +Link: https://patch.msgid.link/20260416191433.840637-1-decui@microsoft.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/vmw_vsock/hyperv_transport.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +--- a/net/vmw_vsock/hyperv_transport.c ++++ b/net/vmw_vsock/hyperv_transport.c +@@ -694,7 +694,6 @@ out: + static s64 hvs_stream_has_data(struct vsock_sock *vsk) + { + struct hvsock *hvs = vsk->trans; +- bool need_refill; + s64 ret; + + if (hvs->recv_data_len > 0) +@@ -702,9 +701,22 @@ static s64 hvs_stream_has_data(struct vs + + switch (hvs_channel_readable_payload(hvs->chan)) { + case 1: +- need_refill = !hvs->recv_desc; +- if (!need_refill) +- return -EIO; ++ if (hvs->recv_desc) { ++ /* Here hvs->recv_data_len is 0, so hvs->recv_desc must ++ * be NULL unless it points to the 0-byte-payload FIN ++ * packet: see hvs_update_recv_data(). ++ * ++ * Here all the payload has been dequeued, but ++ * hvs_channel_readable_payload() still returns 1, ++ * because the VMBus ringbuffer's read_index is not ++ * updated for the FIN packet: hvs_stream_dequeue() -> ++ * hv_pkt_iter_next() updates the cached priv_read_index ++ * but has no opportunity to update the read_index in ++ * hv_pkt_iter_close() as hvs_stream_has_data() returns ++ * 0 for the FIN packet, so it won't get dequeued. ++ */ ++ return 0; ++ } + + hvs->recv_desc = hv_pkt_iter_first(hvs->chan); + if (!hvs->recv_desc) diff --git a/queue-7.0/hv_sock-return-eio-for-malformed-short-packets.patch b/queue-7.0/hv_sock-return-eio-for-malformed-short-packets.patch new file mode 100644 index 0000000000..3c75a32252 --- /dev/null +++ b/queue-7.0/hv_sock-return-eio-for-malformed-short-packets.patch @@ -0,0 +1,67 @@ +From 3d1f20727a635811f6b77801a7b57b8995268abd Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Wed, 22 Apr 2026 23:48:11 -0700 +Subject: hv_sock: Return -EIO for malformed/short packets + +From: Dexuan Cui + +commit 3d1f20727a635811f6b77801a7b57b8995268abd upstream. + +Commit f63152958994 fixes a regression, however it fails to report an +error for malformed/short packets -- normally we should never see such +packets, but let's report an error for them just in case. + +Fixes: f63152958994 ("hv_sock: Report EOF instead of -EIO for FIN") +Cc: stable@vger.kernel.org +Signed-off-by: Dexuan Cui +Acked-by: Stefano Garzarella +Link: https://patch.msgid.link/20260423064811.1371749-1-decui@microsoft.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/vmw_vsock/hyperv_transport.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + +diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c +index 76e78c83fdbc..f862988c1e86 100644 +--- a/net/vmw_vsock/hyperv_transport.c ++++ b/net/vmw_vsock/hyperv_transport.c +@@ -704,17 +704,26 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk) + if (hvs->recv_desc) { + /* Here hvs->recv_data_len is 0, so hvs->recv_desc must + * be NULL unless it points to the 0-byte-payload FIN +- * packet: see hvs_update_recv_data(). ++ * packet or a malformed/short packet: see ++ * hvs_update_recv_data(). + * +- * Here all the payload has been dequeued, but +- * hvs_channel_readable_payload() still returns 1, +- * because the VMBus ringbuffer's read_index is not +- * updated for the FIN packet: hvs_stream_dequeue() -> +- * hv_pkt_iter_next() updates the cached priv_read_index +- * but has no opportunity to update the read_index in +- * hv_pkt_iter_close() as hvs_stream_has_data() returns +- * 0 for the FIN packet, so it won't get dequeued. ++ * If hvs->recv_desc points to the FIN packet, here all ++ * the payload has been dequeued and the peer_shutdown ++ * flag is set, but hvs_channel_readable_payload() still ++ * returns 1, because the VMBus ringbuffer's read_index ++ * is not updated for the FIN packet: ++ * hvs_stream_dequeue() -> hv_pkt_iter_next() updates ++ * the cached priv_read_index but has no opportunity to ++ * update the read_index in hv_pkt_iter_close() as ++ * hvs_stream_has_data() returns 0 for the FIN packet, ++ * so it won't get dequeued. ++ * ++ * In case hvs->recv_desc points to a malformed/short ++ * packet, return -EIO. + */ ++ if (!(vsk->peer_shutdown & SEND_SHUTDOWN)) ++ return -EIO; ++ + return 0; + } + +-- +2.54.0 + diff --git a/queue-7.0/hwmon-corsair-psu-close-hid-device-on-probe-errors.patch b/queue-7.0/hwmon-corsair-psu-close-hid-device-on-probe-errors.patch new file mode 100644 index 0000000000..76446828fb --- /dev/null +++ b/queue-7.0/hwmon-corsair-psu-close-hid-device-on-probe-errors.patch @@ -0,0 +1,45 @@ +From 174606451fbb17db506ebaacdd5e203e57773d5f Mon Sep 17 00:00:00 2001 +From: Myeonghun Pak +Date: Fri, 24 Apr 2026 22:50:51 +0900 +Subject: hwmon: (corsair-psu) Close HID device on probe errors + +From: Myeonghun Pak + +commit 174606451fbb17db506ebaacdd5e203e57773d5f upstream. + +corsairpsu_probe() opens the HID device before sending the device init +and firmware-info commands. If either command fails, the error path jumps +directly to fail_and_stop and skips hid_hw_close(). + +Use the existing fail_and_close label for those post-open failures so the +open count and low-level close callback are balanced before hid_hw_stop(). + +Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver") +Cc: stable@vger.kernel.org +Signed-off-by: Myeonghun Pak +Reviewed-by: Wilken Gottwalt +Link: https://lore.kernel.org/r/20260424135107.13720-1-mhun512@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/corsair-psu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -796,13 +796,13 @@ static int corsairpsu_probe(struct hid_d + ret = corsairpsu_init(priv); + if (ret < 0) { + dev_err(&hdev->dev, "unable to initialize device (%d)\n", ret); +- goto fail_and_stop; ++ goto fail_and_close; + } + + ret = corsairpsu_fwinfo(priv); + if (ret < 0) { + dev_err(&hdev->dev, "unable to query firmware (%d)\n", ret); +- goto fail_and_stop; ++ goto fail_and_close; + } + + corsairpsu_get_criticals(priv); diff --git a/queue-7.0/hwmon-ltc2992-clamp-threshold-writes-to-hardware-range.patch b/queue-7.0/hwmon-ltc2992-clamp-threshold-writes-to-hardware-range.patch new file mode 100644 index 0000000000..b8a588a3d8 --- /dev/null +++ b/queue-7.0/hwmon-ltc2992-clamp-threshold-writes-to-hardware-range.patch @@ -0,0 +1,115 @@ +From d6cc7c99bf1f73eda7d565d224d791d16239bb41 Mon Sep 17 00:00:00 2001 +From: Sanman Pradhan +Date: Thu, 16 Apr 2026 21:59:30 +0000 +Subject: hwmon: (ltc2992) Clamp threshold writes to hardware range + +From: Sanman Pradhan + +commit d6cc7c99bf1f73eda7d565d224d791d16239bb41 upstream. + +ltc2992_set_voltage(), ltc2992_set_current(), and ltc2992_set_power() +do not validate the user-supplied value before converting it to a +register value. This can result in: + +1. Negative input values wrapping to large positive register values. + For power, the negative long is implicitly cast to u64 in + mul_u64_u32_div(), producing an incorrect value. For voltage and + current, the negative converted value wraps when passed to + ltc2992_write_reg() as a u32. + +2. Intermediate arithmetic exceeding the range representable in u64 on + 64-bit platforms. In ltc2992_set_voltage(), (u64)val * 1000 can + exceed U64_MAX when val is a large positive long. In + ltc2992_set_current(), (u64)val * r_sense_uohm can overflow + similarly. In ltc2992_set_power(), the computed value may not fit + in u64. + +3. Register values exceeding the hardware field width. Voltage and + current threshold registers are 12-bit (stored left-justified in + 16 bits), and power threshold registers are 24-bit. Without + clamping, bits above the field width are truncated in + ltc2992_write_reg(). + +Fix by clamping negative values to zero, clamping positive values to +the rounded hardware-representable maximum (the value returned by the +read path for a full-scale register) to prevent intermediate overflow, +and clamping the converted register value to the hardware field width +before writing. The existing conversion formula and rounding behavior +are preserved. + +In the power write path, cancel the factor of 1000 from both the +numerator (r_sense_uohm * 1000) and the denominator +(VADC_UV_LSB * IADC_NANOV_LSB) to also eliminate a u32 overflow of +r_sense_uohm * 1000 when r_sense_uohm exceeds about 4.29 ohms. + +Fixes: b0bd407e94b03 ("hwmon: (ltc2992) Add support") +Cc: stable@vger.kernel.org +Signed-off-by: Sanman Pradhan +Link: https://lore.kernel.org/r/20260416215904.101969-2-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/ltc2992.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +--- a/drivers/hwmon/ltc2992.c ++++ b/drivers/hwmon/ltc2992.c +@@ -431,10 +431,16 @@ static int ltc2992_get_voltage(struct lt + + static int ltc2992_set_voltage(struct ltc2992_state *st, u32 reg, u32 scale, long val) + { +- val = DIV_ROUND_CLOSEST(val * 1000, scale); +- val = val << 4; ++ u32 reg_val; ++ long vmax; ++ ++ vmax = DIV_ROUND_CLOSEST_ULL(0xFFFULL * scale, 1000); ++ val = max(val, 0L); ++ val = min(val, vmax); ++ reg_val = min(DIV_ROUND_CLOSEST_ULL((u64)val * 1000, scale), ++ 0xFFFULL) << 4; + +- return ltc2992_write_reg(st, reg, 2, val); ++ return ltc2992_write_reg(st, reg, 2, reg_val); + } + + static int ltc2992_read_gpio_alarm(struct ltc2992_state *st, int nr_gpio, u32 attr, long *val) +@@ -559,9 +565,15 @@ static int ltc2992_get_current(struct lt + static int ltc2992_set_current(struct ltc2992_state *st, u32 reg, u32 channel, long val) + { + u32 reg_val; ++ long cmax; + +- reg_val = DIV_ROUND_CLOSEST(val * st->r_sense_uohm[channel], LTC2992_IADC_NANOV_LSB); +- reg_val = reg_val << 4; ++ cmax = DIV_ROUND_CLOSEST_ULL(0xFFFULL * LTC2992_IADC_NANOV_LSB, ++ st->r_sense_uohm[channel]); ++ val = max(val, 0L); ++ val = min(val, cmax); ++ reg_val = min(DIV_ROUND_CLOSEST_ULL((u64)val * st->r_sense_uohm[channel], ++ LTC2992_IADC_NANOV_LSB), ++ 0xFFFULL) << 4; + + return ltc2992_write_reg(st, reg, 2, reg_val); + } +@@ -634,9 +646,18 @@ static int ltc2992_get_power(struct ltc2 + static int ltc2992_set_power(struct ltc2992_state *st, u32 reg, u32 channel, long val) + { + u32 reg_val; ++ u64 pmax, uval; + +- reg_val = mul_u64_u32_div(val, st->r_sense_uohm[channel] * 1000, +- LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB); ++ uval = max(val, 0L); ++ pmax = mul_u64_u32_div(0xFFFFFFULL, ++ LTC2992_VADC_UV_LSB / 1000 * ++ LTC2992_IADC_NANOV_LSB, ++ st->r_sense_uohm[channel]); ++ uval = min(uval, pmax); ++ reg_val = min(mul_u64_u32_div(uval, st->r_sense_uohm[channel], ++ LTC2992_VADC_UV_LSB / 1000 * ++ LTC2992_IADC_NANOV_LSB), ++ 0xFFFFFFULL); + + return ltc2992_write_reg(st, reg, 3, reg_val); + } diff --git a/queue-7.0/hwmon-ltc2992-fix-u32-overflow-in-power-read-path.patch b/queue-7.0/hwmon-ltc2992-fix-u32-overflow-in-power-read-path.patch new file mode 100644 index 0000000000..93a9ec6741 --- /dev/null +++ b/queue-7.0/hwmon-ltc2992-fix-u32-overflow-in-power-read-path.patch @@ -0,0 +1,49 @@ +From 2da0c1fd01dbd6b22844e8676585153dfc660cbe Mon Sep 17 00:00:00 2001 +From: Sanman Pradhan +Date: Thu, 16 Apr 2026 21:59:40 +0000 +Subject: hwmon: (ltc2992) Fix u32 overflow in power read path + +From: Sanman Pradhan + +commit 2da0c1fd01dbd6b22844e8676585153dfc660cbe upstream. + +ltc2992_get_power() computes the divisor for mul_u64_u32_div() as +r_sense_uohm * 1000. This multiplication overflows u32 when +r_sense_uohm exceeds about 4.29 ohms (4294967 micro-ohms), producing +a truncated divisor and an incorrect power reading. + +Cancel the factor of 1000 from both the numerator +(VADC_UV_LSB * IADC_NANOV_LSB = 312500000) and the divisor +(r_sense_uohm * 1000), giving (VADC_UV_LSB / 1000) * IADC_NANOV_LSB += 312500 as the numerator and plain r_sense_uohm as the divisor. +The cancellation is exact because LTC2992_VADC_UV_LSB (25000) is +divisible by 1000. + +This is the read-path counterpart of the write-path fix applied in +the preceding patch. + +Fixes: b0bd407e94b03 ("hwmon: (ltc2992) Add support") +Cc: stable@vger.kernel.org +Signed-off-by: Sanman Pradhan +Link: https://lore.kernel.org/r/20260416215904.101969-3-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/ltc2992.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/ltc2992.c ++++ b/drivers/hwmon/ltc2992.c +@@ -637,8 +637,10 @@ static int ltc2992_get_power(struct ltc2 + if (reg_val < 0) + return reg_val; + +- *val = mul_u64_u32_div(reg_val, LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB, +- st->r_sense_uohm[channel] * 1000); ++ *val = mul_u64_u32_div(reg_val, ++ LTC2992_VADC_UV_LSB / 1000 * ++ LTC2992_IADC_NANOV_LSB, ++ st->r_sense_uohm[channel]); + + return 0; + } diff --git a/queue-7.0/ibmveth-disable-gso-for-packets-with-small-mss.patch b/queue-7.0/ibmveth-disable-gso-for-packets-with-small-mss.patch new file mode 100644 index 0000000000..8ce52d3e99 --- /dev/null +++ b/queue-7.0/ibmveth-disable-gso-for-packets-with-small-mss.patch @@ -0,0 +1,99 @@ +From cc427d24ac6442ffdeafd157a63c7c5b73ed4de4 Mon Sep 17 00:00:00 2001 +From: Mingming Cao +Date: Fri, 24 Apr 2026 09:29:17 -0700 +Subject: ibmveth: Disable GSO for packets with small MSS + +From: Mingming Cao + +commit cc427d24ac6442ffdeafd157a63c7c5b73ed4de4 upstream. + +Some physical adapters on Power systems do not support segmentation +offload when the MSS is less than 224 bytes. Attempting to send such +packets causes the adapter to freeze, stopping all traffic until +manually reset. + +Implement ndo_features_check to disable GSO for packets with small MSS +values. The network stack will perform software segmentation instead. + +The 224-byte minimum matches ibmvnic +commit ("ibmvnic: Enforce stronger sanity checks +on GSO packets") +which uses the same physical adapters in SEA configurations. + +The issue occurs specifically when the hardware attempts to perform +segmentation (gso_segs > 1) with a small MSS. Single-segment GSO packets +(gso_segs == 1) do not trigger the problematic LSO code path and are +transmitted normally without segmentation. + +Add an ndo_features_check callback to disable GSO when MSS < 224 bytes. +Also call vlan_features_check() to ensure proper handling of VLAN packets, +particularly QinQ (802.1ad) configurations where the hardware parser may +not support certain offload features. + +Validated using iptables to force small MSS values. Without the fix, +the adapter freezes. With the fix, packets are segmented in software +and transmission succeeds. Comprehensive regression testing completedd +(MSS tests, performance, stability). + +Fixes: 8641dd85799f ("ibmveth: Add support for TSO") +Cc: stable@vger.kernel.org +Reviewed-by: Brian King +Tested-by: Shaik Abdulla +Tested-by: Naveed Ahmed +Signed-off-by: Mingming Cao +Link: https://patch.msgid.link/20260424162917.65725-1-mmc@linux.ibm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/ibm/ibmveth.c | 22 ++++++++++++++++++++++ + drivers/net/ethernet/ibm/ibmveth.h | 1 + + 2 files changed, 23 insertions(+) + +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -1756,6 +1756,27 @@ static int ibmveth_set_mac_addr(struct n + return 0; + } + ++static netdev_features_t ibmveth_features_check(struct sk_buff *skb, ++ struct net_device *dev, ++ netdev_features_t features) ++{ ++ /* Some physical adapters do not support segmentation offload with ++ * MSS < 224. Disable GSO for such packets to avoid adapter freeze. ++ * Note: Single-segment packets (gso_segs == 1) don't need this check ++ * as they bypass the LSO path and are transmitted without segmentation. ++ */ ++ if (skb_is_gso(skb)) { ++ if (skb_shinfo(skb)->gso_size < IBMVETH_MIN_LSO_MSS) { ++ netdev_warn_once(dev, ++ "MSS %u too small for LSO, disabling GSO\n", ++ skb_shinfo(skb)->gso_size); ++ features &= ~NETIF_F_GSO_MASK; ++ } ++ } ++ ++ return vlan_features_check(skb, features); ++} ++ + static const struct net_device_ops ibmveth_netdev_ops = { + .ndo_open = ibmveth_open, + .ndo_stop = ibmveth_close, +@@ -1767,6 +1788,7 @@ static const struct net_device_ops ibmve + .ndo_set_features = ibmveth_set_features, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = ibmveth_set_mac_addr, ++ .ndo_features_check = ibmveth_features_check, + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ibmveth_poll_controller, + #endif +--- a/drivers/net/ethernet/ibm/ibmveth.h ++++ b/drivers/net/ethernet/ibm/ibmveth.h +@@ -37,6 +37,7 @@ + #define IBMVETH_ILLAN_IPV4_TCP_CSUM 0x0000000000000002UL + #define IBMVETH_ILLAN_ACTIVE_TRUNK 0x0000000000000001UL + ++#define IBMVETH_MIN_LSO_MSS 224 /* Minimum MSS for LSO */ + /* hcall macros */ + #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ + plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac) diff --git a/queue-7.0/ice-fix-double-free-in-ice_sf_eth_activate-error-path.patch b/queue-7.0/ice-fix-double-free-in-ice_sf_eth_activate-error-path.patch new file mode 100644 index 0000000000..0cb724b97c --- /dev/null +++ b/queue-7.0/ice-fix-double-free-in-ice_sf_eth_activate-error-path.patch @@ -0,0 +1,43 @@ +From 9aab1c3d7299285e2569cbc0ed5892d631a241b2 Mon Sep 17 00:00:00 2001 +From: Guangshuo Li +Date: Thu, 16 Apr 2026 17:53:27 -0700 +Subject: ice: fix double free in ice_sf_eth_activate() error path + +From: Guangshuo Li + +commit 9aab1c3d7299285e2569cbc0ed5892d631a241b2 upstream. + +When auxiliary_device_add() fails, ice_sf_eth_activate() jumps to +aux_dev_uninit and calls auxiliary_device_uninit(&sf_dev->adev). + +The device release callback ice_sf_dev_release() frees sf_dev, but +the current error path falls through to sf_dev_free and calls +kfree(sf_dev) again, causing a double free. + +Keep kfree(sf_dev) for the auxiliary_device_init() failure path, but +avoid falling through to sf_dev_free after auxiliary_device_uninit(). + +Fixes: 13acc5c4cdbe ("ice: subfunction activation and base devlink ops") +Cc: stable@vger.kernel.org +Reviewed-by: Aleksandr Loktionov +Signed-off-by: Guangshuo Li +Reviewed-by: Simon Horman +Signed-off-by: Jacob Keller +Link: https://patch.msgid.link/20260416-iwl-net-submission-2026-04-14-v2-3-686c33c9828d@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_sf_eth.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c ++++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c +@@ -305,6 +305,8 @@ ice_sf_eth_activate(struct ice_dynamic_p + + aux_dev_uninit: + auxiliary_device_uninit(&sf_dev->adev); ++ return err; ++ + sf_dev_free: + kfree(sf_dev); + xa_erase: diff --git a/queue-7.0/ip6_gre-use-cached-t-net-in-ip6erspan_changelink.patch b/queue-7.0/ip6_gre-use-cached-t-net-in-ip6erspan_changelink.patch new file mode 100644 index 0000000000..4eaf0dc46e --- /dev/null +++ b/queue-7.0/ip6_gre-use-cached-t-net-in-ip6erspan_changelink.patch @@ -0,0 +1,55 @@ +From 1d324c2f43f70c965f25c58cc3611c779adbe47e Mon Sep 17 00:00:00 2001 +From: Maoyi Xie +Date: Thu, 30 Apr 2026 18:33:18 +0800 +Subject: ip6_gre: Use cached t->net in ip6erspan_changelink(). + +From: Maoyi Xie + +commit 1d324c2f43f70c965f25c58cc3611c779adbe47e upstream. + +After commit 5e72ce3e3980 ("net: ipv6: Use link netns in newlink() of +rtnl_link_ops"), ip6erspan_newlink() correctly resolves the per-netns +ip6gre hash via link_net. ip6erspan_changelink() was not converted in +that series and still uses dev_net(dev), which diverges from the +device's creation netns after IFLA_NET_NS_FD migration. + +This re-inserts the tunnel into the wrong per-netns hash. The +original netns keeps a stale entry. When that netns is later +destroyed, ip6gre_exit_rtnl_net() walks the stale entry, producing a +slab-use-after-free reported by KASAN, followed by a kernel BUG at +net/core/dev.c (LIST_POISON1) in unregister_netdevice_many_notify(). + +Reachable from an unprivileged user namespace (unshare --user +--map-root-user --net). + +ip6gre_changelink() earlier in the same file already uses the cached +t->net; only ip6erspan_changelink() has the wrong shape. + +Fixes: 2d665034f239 ("net: ip6_gre: Fix ip6erspan hlen calculation") +Cc: stable@vger.kernel.org # v5.15+ +Signed-off-by: Maoyi Xie +Reviewed-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260430103318.3206018-1-maoyi.xie@ntu.edu.sg +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_gre.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -2261,10 +2261,11 @@ static int ip6erspan_changelink(struct n + struct nlattr *data[], + struct netlink_ext_ack *extack) + { +- struct ip6gre_net *ign = net_generic(dev_net(dev), ip6gre_net_id); ++ struct ip6_tnl *t = netdev_priv(dev); + struct __ip6_tnl_parm p; +- struct ip6_tnl *t; ++ struct ip6gre_net *ign; + ++ ign = net_generic(t->net, ip6gre_net_id); + t = ip6gre_changelink_common(dev, tb, data, &p, extack); + if (IS_ERR(t)) + return PTR_ERR(t); diff --git a/queue-7.0/net-libwx-fix-vf-illegal-register-access.patch b/queue-7.0/net-libwx-fix-vf-illegal-register-access.patch new file mode 100644 index 0000000000..9d0c85ac27 --- /dev/null +++ b/queue-7.0/net-libwx-fix-vf-illegal-register-access.patch @@ -0,0 +1,42 @@ +From 694de316f607fe2473d52ca0707e3918e72c1562 Mon Sep 17 00:00:00 2001 +From: Jiawen Wu +Date: Wed, 29 Apr 2026 16:37:42 +0800 +Subject: net: libwx: fix VF illegal register access + +From: Jiawen Wu + +commit 694de316f607fe2473d52ca0707e3918e72c1562 upstream. + +Register WX_CFG_PORT_ST is a PF restricted register. When a VF is +initialized, attempting to read this register triggers an illegal +register access, which lead to a system hang. + +When the device is VF, the bus function ID can be obtained directly from +the PCI_FUNC(pdev->devfn). + +Fixes: a04ea57aae37 ("net: libwx: fix device bus LAN ID") +Cc: stable@vger.kernel.org +Signed-off-by: Jiawen Wu +Link: https://patch.msgid.link/4D1F4452D21DE107+20260429083743.88961-1-jiawenwu@trustnetic.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/wangxun/libwx/wx_hw.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c ++++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c +@@ -2480,8 +2480,11 @@ int wx_sw_init(struct wx *wx) + wx->oem_svid = pdev->subsystem_vendor; + wx->oem_ssid = pdev->subsystem_device; + wx->bus.device = PCI_SLOT(pdev->devfn); +- wx->bus.func = FIELD_GET(WX_CFG_PORT_ST_LANID, +- rd32(wx, WX_CFG_PORT_ST)); ++ if (pdev->is_virtfn) ++ wx->bus.func = PCI_FUNC(pdev->devfn); ++ else ++ wx->bus.func = FIELD_GET(WX_CFG_PORT_ST_LANID, ++ rd32(wx, WX_CFG_PORT_ST)); + + if (wx->oem_svid == PCI_VENDOR_ID_WANGXUN || + pdev->is_virtfn) { diff --git a/queue-7.0/net-libwx-use-request_irq-for-vf-misc-interrupt.patch b/queue-7.0/net-libwx-use-request_irq-for-vf-misc-interrupt.patch new file mode 100644 index 0000000000..9063de6ff0 --- /dev/null +++ b/queue-7.0/net-libwx-use-request_irq-for-vf-misc-interrupt.patch @@ -0,0 +1,43 @@ +From 7a33345153eeeda195c55f15be27074e4c3b5109 Mon Sep 17 00:00:00 2001 +From: Jiawen Wu +Date: Wed, 29 Apr 2026 16:37:43 +0800 +Subject: net: libwx: use request_irq for VF misc interrupt + +From: Jiawen Wu + +commit 7a33345153eeeda195c55f15be27074e4c3b5109 upstream. + +Currently, request_threaded_irq() is used with a primary handler but a +NULL threaded handler, while also setting the IRQF_ONESHOT flag. This +specific combination triggers a WARNING since the commit aef30c8d569c +("genirq: Warn about using IRQF_ONESHOT without a threaded handler"). + +WARNING: kernel/irq/manage.c:1502 at __setup_irq+0x4fa/0x760 + +Fix the issue by switching to request_irq(), which is the appropriate +interface or a non-threaded interrupt handler, and removing the +unnecessary IRQF_ONESHOT flag. + +Fixes: eb4898fde1de ("net: libwx: add wangxun vf common api") +Cc: stable@vger.kernel.org +Signed-off-by: Jiawen Wu +Link: https://patch.msgid.link/786DDC7D5CCA6D0A+20260429083743.88961-2-jiawenwu@trustnetic.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/wangxun/libwx/wx_vf_common.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c ++++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c +@@ -98,8 +98,8 @@ int wx_request_msix_irqs_vf(struct wx *w + } + } + +- err = request_threaded_irq(wx->msix_entry->vector, wx_msix_misc_vf, +- NULL, IRQF_ONESHOT, netdev->name, wx); ++ err = request_irq(wx->msix_entry->vector, wx_msix_misc_vf, ++ 0, netdev->name, wx); + if (err) { + wx_err(wx, "request_irq for msix_other failed: %d\n", err); + goto free_queue_irqs; diff --git a/queue-7.0/net-rds-handle-zerocopy-send-cleanup-before-the-message-is-queued.patch b/queue-7.0/net-rds-handle-zerocopy-send-cleanup-before-the-message-is-queued.patch new file mode 100644 index 0000000000..7029a33009 --- /dev/null +++ b/queue-7.0/net-rds-handle-zerocopy-send-cleanup-before-the-message-is-queued.patch @@ -0,0 +1,87 @@ +From 44b550d88b267320459d518c0743a241ab2108fa Mon Sep 17 00:00:00 2001 +From: Nan Li +Date: Fri, 1 May 2026 09:08:44 +0800 +Subject: net/rds: handle zerocopy send cleanup before the message is queued + +From: Nan Li + +commit 44b550d88b267320459d518c0743a241ab2108fa upstream. + +A zerocopy send can fail after user pages have been pinned but before +the message is attached to the sending socket. + +The purge path currently infers zerocopy state from rm->m_rs, so an +unqueued message can be cleaned up as if it owned normal payload pages. +However, zerocopy ownership is really determined by the presence of +op_mmp_znotifier, regardless of whether the message has reached the +socket queue. + +Capture op_mmp_znotifier up front in rds_message_purge() and use it as +the cleanup discriminator. If the message is already associated with a +socket, keep the existing completion path. Otherwise, drop the pinned +page accounting directly and release the notifier before putting the +payload pages. + +This keeps early send failure cleanup consistent with the zerocopy +lifetime rules without changing the normal queued completion path. + +Fixes: 0cebaccef3ac ("rds: zerocopy Tx support.") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Co-developed-by: Xiao Liu +Signed-off-by: Xiao Liu +Signed-off-by: Nan Li +Signed-off-by: Ren Wei +Reviewed-by: Allison Henderson +Link: https://patch.msgid.link/d2ea98a6313d5467bac00f7c9fef8c7acddb9258.1777550074.git.tonanli66@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + net/rds/message.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/net/rds/message.c ++++ b/net/rds/message.c +@@ -131,24 +131,34 @@ static void rds_rm_zerocopy_callback(str + */ + static void rds_message_purge(struct rds_message *rm) + { ++ struct rds_znotifier *znotifier; + unsigned long i, flags; +- bool zcopy = false; ++ bool zcopy; + + if (unlikely(test_bit(RDS_MSG_PAGEVEC, &rm->m_flags))) + return; + + spin_lock_irqsave(&rm->m_rs_lock, flags); ++ znotifier = rm->data.op_mmp_znotifier; ++ rm->data.op_mmp_znotifier = NULL; ++ zcopy = !!znotifier; ++ + if (rm->m_rs) { + struct rds_sock *rs = rm->m_rs; + +- if (rm->data.op_mmp_znotifier) { +- zcopy = true; +- rds_rm_zerocopy_callback(rs, rm->data.op_mmp_znotifier); ++ if (znotifier) { ++ rds_rm_zerocopy_callback(rs, znotifier); + rds_wake_sk_sleep(rs); +- rm->data.op_mmp_znotifier = NULL; + } + sock_put(rds_rs_to_sk(rs)); + rm->m_rs = NULL; ++ } else if (znotifier) { ++ /* ++ * Zerocopy can fail before the message is queued on the ++ * socket, so there is no rs to carry the notification. ++ */ ++ mm_unaccount_pinned_pages(&znotifier->z_mmp); ++ kfree(rds_info_from_znotifier(znotifier)); + } + spin_unlock_irqrestore(&rm->m_rs_lock, flags); + diff --git a/queue-7.0/net-wwan-t7xx-validate-port_count-against-message-length-in-t7xx_port_enum_msg_handler.patch b/queue-7.0/net-wwan-t7xx-validate-port_count-against-message-length-in-t7xx_port_enum_msg_handler.patch new file mode 100644 index 0000000000..1797e38a9a --- /dev/null +++ b/queue-7.0/net-wwan-t7xx-validate-port_count-against-message-length-in-t7xx_port_enum_msg_handler.patch @@ -0,0 +1,140 @@ +From 0e7c074cfcd9bd93765505f9eb8b42f03ed2a744 Mon Sep 17 00:00:00 2001 +From: Pavitra Jha +Date: Fri, 1 May 2026 07:07:12 -0400 +Subject: net: wwan: t7xx: validate port_count against message length in t7xx_port_enum_msg_handler + +From: Pavitra Jha + +commit 0e7c074cfcd9bd93765505f9eb8b42f03ed2a744 upstream. + +t7xx_port_enum_msg_handler() uses the modem-supplied port_count field as +a loop bound over port_msg->data[] without checking that the message buffer +contains sufficient data. A modem sending port_count=65535 in a 12-byte +buffer triggers a slab-out-of-bounds read of up to 262140 bytes. + +Add a sizeof(*port_msg) check before accessing the port message header +fields to guard against undersized messages. + +Add a struct_size() check after extracting port_count and before the loop. + +In t7xx_parse_host_rt_data(), guard the rt_feature header read with a +remaining-buffer check before accessing data_len, validate feat_data_len +against the actual remaining buffer to prevent OOB reads and signed +integer overflow on offset. + +Pass msg_len from both call sites: skb->len at the DPMAIF path after +skb_pull(), and the validated feat_data_len at the handshake path. + +Fixes: da45d2566a1d ("net: wwan: t7xx: Add control port") +Cc: stable@vger.kernel.org +Signed-off-by: Pavitra Jha +Link: https://patch.msgid.link/20260501110713.145563-1-jhapavitra98@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wwan/t7xx/t7xx_modem_ops.c | 20 +++++++++++++++++--- + drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c | 18 ++++++++++++++++-- + drivers/net/wwan/t7xx/t7xx_port_proxy.h | 2 +- + 3 files changed, 34 insertions(+), 6 deletions(-) + +--- a/drivers/net/wwan/t7xx/t7xx_modem_ops.c ++++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.c +@@ -457,8 +457,20 @@ static int t7xx_parse_host_rt_data(struc + + offset = sizeof(struct feature_query); + for (i = 0; i < FEATURE_COUNT && offset < data_length; i++) { ++ size_t remaining = data_length - offset; ++ size_t feat_data_len, feat_total; ++ ++ if (remaining < sizeof(*rt_feature)) ++ break; ++ + rt_feature = data + offset; +- offset += sizeof(*rt_feature) + le32_to_cpu(rt_feature->data_len); ++ feat_data_len = le32_to_cpu(rt_feature->data_len); ++ ++ if (feat_data_len > remaining - sizeof(*rt_feature)) ++ break; ++ ++ feat_total = sizeof(*rt_feature) + feat_data_len; ++ offset += feat_total; + + ft_spt_cfg = FIELD_GET(FEATURE_MSK, core->feature_set[i]); + if (ft_spt_cfg != MTK_FEATURE_MUST_BE_SUPPORTED) +@@ -468,8 +480,10 @@ static int t7xx_parse_host_rt_data(struc + if (ft_spt_st != MTK_FEATURE_MUST_BE_SUPPORTED) + return -EINVAL; + +- if (i == RT_ID_MD_PORT_ENUM || i == RT_ID_AP_PORT_ENUM) +- t7xx_port_enum_msg_handler(ctl->md, rt_feature->data); ++ if (i == RT_ID_MD_PORT_ENUM || i == RT_ID_AP_PORT_ENUM) { ++ t7xx_port_enum_msg_handler(ctl->md, rt_feature->data, ++ feat_data_len); ++ } + } + + return 0; +--- a/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c ++++ b/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c +@@ -117,6 +117,7 @@ static int fsm_ee_message_handler(struct + * t7xx_port_enum_msg_handler() - Parse the port enumeration message to create/remove nodes. + * @md: Modem context. + * @msg: Message. ++ * @msg_len: Length of @msg in bytes. + * + * Used to control create/remove device node. + * +@@ -124,12 +125,18 @@ static int fsm_ee_message_handler(struct + * * 0 - Success. + * * -EFAULT - Message check failure. + */ +-int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg) ++int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg, size_t msg_len) + { + struct device *dev = &md->t7xx_dev->pdev->dev; + unsigned int version, port_count, i; + struct port_msg *port_msg = msg; + ++ if (msg_len < sizeof(*port_msg)) { ++ dev_err(dev, "Port enum msg too short for header: need %zu, have %zu\n", ++ sizeof(*port_msg), msg_len); ++ return -EINVAL; ++ } ++ + version = FIELD_GET(PORT_MSG_VERSION, le32_to_cpu(port_msg->info)); + if (version != PORT_ENUM_VER || + le32_to_cpu(port_msg->head_pattern) != PORT_ENUM_HEAD_PATTERN || +@@ -141,6 +148,13 @@ int t7xx_port_enum_msg_handler(struct t7 + } + + port_count = FIELD_GET(PORT_MSG_PRT_CNT, le32_to_cpu(port_msg->info)); ++ ++ if (msg_len < struct_size(port_msg, data, port_count)) { ++ dev_err(dev, "Port enum msg too short: need %zu, have %zu\n", ++ struct_size(port_msg, data, port_count), msg_len); ++ return -EINVAL; ++ } ++ + for (i = 0; i < port_count; i++) { + u32 port_info = le32_to_cpu(port_msg->data[i]); + unsigned int ch_id; +@@ -191,7 +205,7 @@ static int control_msg_handler(struct t7 + + case CTL_ID_PORT_ENUM: + skb_pull(skb, sizeof(*ctrl_msg_h)); +- ret = t7xx_port_enum_msg_handler(ctl->md, (struct port_msg *)skb->data); ++ ret = t7xx_port_enum_msg_handler(ctl->md, (struct port_msg *)skb->data, skb->len); + if (!ret) + ret = port_ctl_send_msg_to_md(port, CTL_ID_PORT_ENUM, 0); + else +--- a/drivers/net/wwan/t7xx/t7xx_port_proxy.h ++++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.h +@@ -103,7 +103,7 @@ void t7xx_port_proxy_reset(struct port_p + void t7xx_port_proxy_uninit(struct port_proxy *port_prox); + int t7xx_port_proxy_init(struct t7xx_modem *md); + void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned int state); +-int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg); ++int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg, size_t msg_len); + int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned int ch_id, + bool en_flag); + void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id); diff --git a/queue-7.0/netpoll-pass-buffer-size-to-egress_dev-to-avoid-mac-truncation.patch b/queue-7.0/netpoll-pass-buffer-size-to-egress_dev-to-avoid-mac-truncation.patch new file mode 100644 index 0000000000..b7cf7c1528 --- /dev/null +++ b/queue-7.0/netpoll-pass-buffer-size-to-egress_dev-to-avoid-mac-truncation.patch @@ -0,0 +1,129 @@ +From 76b93a8107574006b25495664304ea9237494d70 Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Fri, 1 May 2026 02:58:41 -0700 +Subject: netpoll: pass buffer size to egress_dev() to avoid MAC truncation + +From: Breno Leitao + +commit 76b93a8107574006b25495664304ea9237494d70 upstream. + +egress_dev() formats np->dev_mac via snprintf() but receives buf as +a bare char *, so it cannot derive the buffer size from the pointer. The +size argument was hardcoded to MAC_ADDR_STR_LEN (3 * ETH_ALEN - 1 = 17), +which is silly wrong in two ways: + + 1) misleading kernel log output on the MAC-selected target path + (np->dev_name[0] == '\0'); for example "aa:bb:cc:dd:ee:ff doesn't + exist, aborting" was logged as "aa:bb:cc:dd:ee:f doesn't exist, + aborting". + + 2) the second argument of snprintf is the size of the buffer, not the + size of what you want to write. + +Add a bufsz parameter to egress_dev() and pass sizeof(buf) from each +caller, matching the standard snprintf() idiom and removing the +hardcoded size from the helper. + +Every caller already declares "char buf[MAC_ADDR_STR_LEN + 1]" so the +formatted MAC continues to fit. + +Tested by booting with + netconsole=6665@/aa:bb:cc:dd:ee:ff,6666@10.0.0.1/00:11:22:33:44:55 +on a kernel without a matching device. Pre-fix dmesg shows +"aa:bb:cc:dd:ee:f doesn't exist, aborting"; post-fix shows the full +"aa:bb:cc:dd:ee:ff doesn't exist, aborting". + +Fixes: f8a10bed32f5 ("netconsole: allow selection of egress interface via MAC address") +Cc: stable@vger.kernel.org +Signed-off-by: Breno Leitao +Link: https://patch.msgid.link/20260501-netpoll_snprintf_fix-v1-1-84b0566e6597@debian.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/core/netpoll.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -608,14 +608,16 @@ EXPORT_SYMBOL_GPL(__netpoll_setup); + /* + * Returns a pointer to a string representation of the identifier used + * to select the egress interface for the given netpoll instance. buf +- * must be a buffer of length at least MAC_ADDR_STR_LEN + 1. ++ * is used to format np->dev_mac when np->dev_name is empty; bufsz must ++ * be at least MAC_ADDR_STR_LEN + 1 to fit the formatted MAC address ++ * and its NUL terminator. + */ +-static char *egress_dev(struct netpoll *np, char *buf) ++static char *egress_dev(struct netpoll *np, char *buf, size_t bufsz) + { + if (np->dev_name[0]) + return np->dev_name; + +- snprintf(buf, MAC_ADDR_STR_LEN, "%pM", np->dev_mac); ++ snprintf(buf, bufsz, "%pM", np->dev_mac); + return buf; + } + +@@ -645,7 +647,7 @@ static int netpoll_take_ipv6(struct netp + + if (!IS_ENABLED(CONFIG_IPV6)) { + np_err(np, "IPv6 is not supported %s, aborting\n", +- egress_dev(np, buf)); ++ egress_dev(np, buf, sizeof(buf))); + return -EINVAL; + } + +@@ -667,7 +669,7 @@ static int netpoll_take_ipv6(struct netp + } + if (err) { + np_err(np, "no IPv6 address for %s, aborting\n", +- egress_dev(np, buf)); ++ egress_dev(np, buf, sizeof(buf))); + return err; + } + +@@ -687,14 +689,14 @@ static int netpoll_take_ipv4(struct netp + in_dev = __in_dev_get_rtnl(ndev); + if (!in_dev) { + np_err(np, "no IP address for %s, aborting\n", +- egress_dev(np, buf)); ++ egress_dev(np, buf, sizeof(buf))); + return -EDESTADDRREQ; + } + + ifa = rtnl_dereference(in_dev->ifa_list); + if (!ifa) { + np_err(np, "no IP address for %s, aborting\n", +- egress_dev(np, buf)); ++ egress_dev(np, buf, sizeof(buf))); + return -EDESTADDRREQ; + } + +@@ -719,7 +721,8 @@ int netpoll_setup(struct netpoll *np) + ndev = dev_getbyhwaddr(net, ARPHRD_ETHER, np->dev_mac); + + if (!ndev) { +- np_err(np, "%s doesn't exist, aborting\n", egress_dev(np, buf)); ++ np_err(np, "%s doesn't exist, aborting\n", ++ egress_dev(np, buf, sizeof(buf))); + err = -ENODEV; + goto unlock; + } +@@ -727,14 +730,14 @@ int netpoll_setup(struct netpoll *np) + + if (netdev_master_upper_dev_get(ndev)) { + np_err(np, "%s is a slave device, aborting\n", +- egress_dev(np, buf)); ++ egress_dev(np, buf, sizeof(buf))); + err = -EBUSY; + goto put; + } + + if (!netif_running(ndev)) { + np_info(np, "device %s not up yet, forcing it\n", +- egress_dev(np, buf)); ++ egress_dev(np, buf, sizeof(buf))); + + err = dev_open(ndev, NULL); + if (err) { diff --git a/queue-7.0/ovl-fix-verity-lazy-load-guard-broken-by-fsverity_active-semantic-change.patch b/queue-7.0/ovl-fix-verity-lazy-load-guard-broken-by-fsverity_active-semantic-change.patch new file mode 100644 index 0000000000..a563b493cc --- /dev/null +++ b/queue-7.0/ovl-fix-verity-lazy-load-guard-broken-by-fsverity_active-semantic-change.patch @@ -0,0 +1,44 @@ +From 0c8c88b8eb82a2a41bec5f17c076d6312dc40316 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Tue, 5 May 2026 15:42:57 -0700 +Subject: ovl: fix verity lazy-load guard broken by fsverity_active() semantic change + +From: Colin Walters + +commit 0c8c88b8eb82a2a41bec5f17c076d6312dc40316 upstream. + +Commit f77f281b6118 ("fsverity: use a hashtable to find the +fsverity_info") made fsverity_active() check whether the inode has the +verity flag, rather than whether the inode's fsverity_info is loaded. +This broke ovl_ensure_verity_loaded(), which wants to load the +fsverity_info for any verity inodes that haven't had it loaded yet. + +Therefore, to check that the fsverity_info hasn't yet been loaded, use +fsverity_get_info(inode) == NULL instead of !fsverity_active(inode). + +Also, since fsverity_get_info() now involves a hash table lookup, put +the more lightweight IS_VERITY() flag check first. + +Fixes: f77f281b6118 ("fsverity: use a hashtable to find the fsverity_info") +Cc: stable@vger.kernel.org +Link: https://github.com/bootc-dev/bootc/issues/2174 +Signed-off-by: Colin Walters +Acked-by: Amir Goldstein +Link: https://patch.msgid.link/20260505224257.23213-1-ebiggers@kernel.org +Signed-off-by: Eric Biggers +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -1379,7 +1379,7 @@ int ovl_ensure_verity_loaded(const struc + struct inode *inode = d_inode(datapath->dentry); + struct file *filp; + +- if (!fsverity_active(inode) && IS_VERITY(inode)) { ++ if (IS_VERITY(inode) && fsverity_get_info(inode) == NULL) { + /* + * If this inode was not yet opened, the verity info hasn't been + * loaded yet, so we need to do that here to force it into memory. diff --git a/queue-7.0/parisc-fix-irq-leak-in-lasi-driver.patch b/queue-7.0/parisc-fix-irq-leak-in-lasi-driver.patch new file mode 100644 index 0000000000..5478898a6f --- /dev/null +++ b/queue-7.0/parisc-fix-irq-leak-in-lasi-driver.patch @@ -0,0 +1,63 @@ +From 37b0dc5e279f35036fb638d1e187197b6c05a76d Mon Sep 17 00:00:00 2001 +From: Hongling Zeng +Date: Sun, 3 May 2026 12:17:44 +0800 +Subject: parisc: Fix IRQ leak in LASI driver + +From: Hongling Zeng + +commit 37b0dc5e279f35036fb638d1e187197b6c05a76d upstream. + +When request_irq() succeeds but gsc_common_setup() fails later, +the IRQ is never released. Fix this by adding proper error handling +with goto labels to ensure resources are released in LIFO order. + +Detected by Smatch: + drivers/parisc/lasi.c:216 lasi_init_chip() warn: 'lasi->gsc_irq.irq' +from request_irq() not released on lines: 207. + +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202604180957.4QdAIxP6-lkp@intel.com/ +Signed-off-by: Hongling Zeng +Cc: stable@vger.kernel.org +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/parisc/lasi.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/parisc/lasi.c ++++ b/drivers/parisc/lasi.c +@@ -193,8 +193,7 @@ static int __init lasi_init_chip(struct + + ret = request_irq(lasi->gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi); + if (ret < 0) { +- kfree(lasi); +- return ret; ++ goto err_free; + } + + /* enable IRQ's for devices below LASI */ +@@ -203,8 +202,7 @@ static int __init lasi_init_chip(struct + /* Done init'ing, register this driver */ + ret = gsc_common_setup(dev, lasi); + if (ret) { +- kfree(lasi); +- return ret; ++ goto err_irq; + } + + gsc_fixup_irqs(dev, lasi, lasi_choose_irq); +@@ -214,6 +212,12 @@ static int __init lasi_init_chip(struct + SYS_OFF_PRIO_DEFAULT, lasi_power_off, lasi); + + return ret; ++ ++err_irq: ++ free_irq(lasi->gsc_irq.irq, lasi); ++err_free: ++ kfree(lasi); ++ return ret; + } + + static struct parisc_device_id lasi_tbl[] __initdata = { diff --git a/queue-7.0/platform-chrome-cros_ec_typec-init-mutex-in-thunderbolt-registration.patch b/queue-7.0/platform-chrome-cros_ec_typec-init-mutex-in-thunderbolt-registration.patch new file mode 100644 index 0000000000..2261f11c9b --- /dev/null +++ b/queue-7.0/platform-chrome-cros_ec_typec-init-mutex-in-thunderbolt-registration.patch @@ -0,0 +1,37 @@ +From 525cb7ba6661074c1c5cc3772bccc6afab6791ef Mon Sep 17 00:00:00 2001 +From: Tzung-Bi Shih +Date: Tue, 5 May 2026 05:34:03 +0000 +Subject: platform/chrome: cros_ec_typec: Init mutex in Thunderbolt registration + +From: Tzung-Bi Shih + +commit 525cb7ba6661074c1c5cc3772bccc6afab6791ef upstream. + +cros_typec_register_thunderbolt() missed initializing the `adata->lock` +mutex. This leads to a NULL dereference when the mutex is later +acquired (e.g. in cros_typec_altmode_work()). + +Initialize the mutex in cros_typec_register_thunderbolt() to fix the +issue. + +Cc: stable@vger.kernel.org +Fixes: 3b00be26b16a ("platform/chrome: cros_ec_typec: Thunderbolt support") +Reviewed-by: Benson Leung +Reviewed-by: Abhishek Pandit-Subedi +Link: https://lore.kernel.org/r/20260505053403.3335740-1-tzungbi@kernel.org +Signed-off-by: Tzung-Bi Shih +Signed-off-by: Greg Kroah-Hartman +--- + drivers/platform/chrome/cros_typec_altmode.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/chrome/cros_typec_altmode.c ++++ b/drivers/platform/chrome/cros_typec_altmode.c +@@ -359,6 +359,7 @@ cros_typec_register_thunderbolt(struct c + } + + INIT_WORK(&adata->work, cros_typec_altmode_work); ++ mutex_init(&adata->lock); + adata->alt = alt; + adata->port = port; + adata->ap_mode_entry = true; diff --git a/queue-7.0/pmdomain-mediatek-fix-use-after-free-in-scpsys_get_bus_protection_legacy.patch b/queue-7.0/pmdomain-mediatek-fix-use-after-free-in-scpsys_get_bus_protection_legacy.patch new file mode 100644 index 0000000000..86d957f1b8 --- /dev/null +++ b/queue-7.0/pmdomain-mediatek-fix-use-after-free-in-scpsys_get_bus_protection_legacy.patch @@ -0,0 +1,57 @@ +From ec1fcddb3117d9452210e838fd37389ee61e10e8 Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Wed, 8 Apr 2026 14:11:21 +0000 +Subject: pmdomain: mediatek: fix use-after-free in scpsys_get_bus_protection_legacy() + +From: Wentao Liang + +commit ec1fcddb3117d9452210e838fd37389ee61e10e8 upstream. + +In scpsys_get_bus_protection_legacy(), of_find_node_with_property() +returns a device node with its reference count incremented. The function +then calls of_node_put(node) before checking whether +syscon_regmap_lookup_by_phandle() returns an error. If an error occurs, +dev_err_probe() dereferences the node pointer to print diagnostic +information, but the node memory may have already been freed due to the +earlier of_node_put(), leading to a use-after-free vulnerability. + +Fix this by moving the of_node_put() call after the error check, ensuring +the node is still valid when accessed in the error path. + +Fixes: c29345fa5f66 ("pmdomain: mediatek: Refactor bus protection regmaps retrieval") +Cc: stable@vger.kernel.org +Signed-off-by: Wentao Liang +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pmdomain/mediatek/mtk-pm-domains.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c ++++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c +@@ -993,6 +993,7 @@ static int scpsys_get_bus_protection_leg + struct device_node *node, *smi_np; + int num_regmaps = 0, i, j; + struct regmap *regmap[3]; ++ int ret = 0; + + /* + * Legacy code retrieves a maximum of three bus protection handles: +@@ -1043,11 +1044,14 @@ static int scpsys_get_bus_protection_leg + if (node) { + regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao"); + num_regmaps++; +- of_node_put(node); +- if (IS_ERR(regmap[2])) +- return dev_err_probe(dev, PTR_ERR(regmap[2]), ++ if (IS_ERR(regmap[2])) { ++ ret = dev_err_probe(dev, PTR_ERR(regmap[2]), + "%pOF: failed to get infracfg regmap\n", + node); ++ of_node_put(node); ++ return ret; ++ } ++ of_node_put(node); + } else { + regmap[2] = NULL; + } diff --git a/queue-7.0/pseries-papr-hvpipe-fix-null-ptr-deref-in-papr_hvpipe_dev_create_handle.patch b/queue-7.0/pseries-papr-hvpipe-fix-null-ptr-deref-in-papr_hvpipe_dev_create_handle.patch new file mode 100644 index 0000000000..c120ca3702 --- /dev/null +++ b/queue-7.0/pseries-papr-hvpipe-fix-null-ptr-deref-in-papr_hvpipe_dev_create_handle.patch @@ -0,0 +1,136 @@ +From 1b9f7aafa44f5ce852c00509104d10fd9eb0f402 Mon Sep 17 00:00:00 2001 +From: "Ritesh Harjani (IBM)" +Date: Fri, 1 May 2026 09:41:42 +0530 +Subject: pseries/papr-hvpipe: Fix null ptr deref in papr_hvpipe_dev_create_handle() + +From: Ritesh Harjani (IBM) + +commit 1b9f7aafa44f5ce852c00509104d10fd9eb0f402 upstream. + +commit 6d3789d347a7 ("papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()"), +changed the create handle to FD_PREPARE(), but it caused kernel +null-ptr-deref because after call to retain_and_null_ptr(src_info), +src_info is re-used for adding it to the global list. + +Getting the following kernel panic in papr_hvpipe_dev_create_handle() +when trying to add src_info to the list. + Kernel attempted to write user page (0) - exploit attempt? (uid: 0) + BUG: Kernel NULL pointer dereference on write at 0x00000000 + Faulting instruction address: 0xc0000000001b44a0 + Oops: Kernel access of bad area, sig: 11 [#1] + ... + Call Trace: + papr_hvpipe_dev_ioctl+0x1f4/0x48c (unreliable) + sys_ioctl+0x528/0x1064 + system_call_exception+0x128/0x360 + system_call_vectored_common+0x15c/0x2ec + +Now, the error handling with FD_PREPARE's file cleanup and __free(kfree) auto +cleanup is getting too convoluted. This is mainly because we need to +ensure only 1 user get the srcID handle. To simplify this, we allocate +prepare the src_info in the beginning and add it to the global list +under a spinlock after checking that no duplicates exist. + +This simplify the error handling where if the FD_ADD fails, we can +simply remove the src_info from the list and consume any pending msg in +hvpipe to be cleared, after src_info became visible in the global list. + +Cc: stable@vger.kernel.org +Fixes: 6d3789d347a7 ("papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()") +Reported-by: Haren Myneni +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/31ad94bc89d44156ee700c5bd006cb47a748e3cb.1777606826.git.ritesh.list@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/papr-hvpipe.c | 57 ++++++++++---------- + 1 file changed, 30 insertions(+), 27 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c +index 3392874ebdf6..402781299497 100644 +--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c ++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c +@@ -480,23 +480,10 @@ static const struct file_operations papr_hvpipe_handle_ops = { + + static int papr_hvpipe_dev_create_handle(u32 srcID) + { +- struct hvpipe_source_info *src_info __free(kfree) = NULL; ++ struct hvpipe_source_info *src_info; ++ int fd; + unsigned long flags; + +- spin_lock_irqsave(&hvpipe_src_list_lock, flags); +- /* +- * Do not allow more than one process communicates with +- * each source. +- */ +- src_info = hvpipe_find_source(srcID); +- if (src_info) { +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); +- pr_err("pid(%d) is already using the source(%d)\n", +- src_info->tsk->pid, srcID); +- return -EALREADY; +- } +- spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); +- + src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT); + if (!src_info) + return -ENOMEM; +@@ -505,26 +492,42 @@ static int papr_hvpipe_dev_create_handle(u32 srcID) + src_info->tsk = current; + init_waitqueue_head(&src_info->recv_wqh); + +- FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC, +- anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops, +- (void *)src_info, O_RDWR)); +- if (fdf.err) +- return fdf.err; +- +- retain_and_null_ptr(src_info); +- spin_lock_irqsave(&hvpipe_src_list_lock, flags); + /* +- * If two processes are executing ioctl() for the same +- * source ID concurrently, prevent the second process to +- * acquire FD. ++ * Do not allow more than one process communicates with ++ * each source. + */ ++ spin_lock_irqsave(&hvpipe_src_list_lock, flags); + if (hvpipe_find_source(srcID)) { + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ pr_err("pid(%d) could not get the source(%d)\n", ++ src_info->tsk->pid, srcID); ++ kfree(src_info); + return -EALREADY; + } + list_add(&src_info->list, &hvpipe_src_list); + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); +- return fd_publish(fdf); ++ ++ fd = FD_ADD(O_RDONLY | O_CLOEXEC, ++ anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops, ++ (void *)src_info, O_RDWR)); ++ if (fd < 0) { ++ spin_lock_irqsave(&hvpipe_src_list_lock, flags); ++ list_del(&src_info->list); ++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); ++ /* ++ * if we fail to add FD, that means no userspace program is ++ * polling. In that case if there is a msg pending because the ++ * interrupt was fired after the src_info was added to the ++ * global list, then let's consume it here, to unblock the ++ * hvpipe ++ */ ++ if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) ++ hvpipe_rtas_recv_msg(NULL, 0); ++ kfree(src_info); ++ return fd; ++ } ++ ++ return fd; + } + + /* +-- +2.54.0 + diff --git a/queue-7.0/pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch b/queue-7.0/pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch new file mode 100644 index 0000000000..11e6bf1e32 --- /dev/null +++ b/queue-7.0/pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch @@ -0,0 +1,103 @@ +From 7a4f0846ee6cc8cf44ae0046ed42e3259d1dd45b Mon Sep 17 00:00:00 2001 +From: "Ritesh Harjani (IBM)" +Date: Fri, 1 May 2026 09:41:40 +0530 +Subject: pseries/papr-hvpipe: Fix race with interrupt handler + +From: Ritesh Harjani (IBM) + +commit 7a4f0846ee6cc8cf44ae0046ed42e3259d1dd45b upstream. + +While executing ->ioctl handler or ->release handler, if an interrupt +fires on the same cpu, then we can enter into a deadlock. + +This patch fixes both these handlers to take spin_lock_irq{save|restore} +versions of the lock to prevent this deadlock. + +Cc: stable@vger.kernel.org +Fixes: 814ef095f12c9 ("powerpc/pseries: Add papr-hvpipe char driver for HVPIPE interfaces") +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/e4ed435c44fc191f2eb23c7907ba6f72f193e6aa.1777606826.git.ritesh.list@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/papr-hvpipe.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c ++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c +@@ -444,13 +444,14 @@ static int papr_hvpipe_handle_release(st + struct file *file) + { + struct hvpipe_source_info *src_info; ++ unsigned long flags; + + /* + * Hold the lock, remove source from src_list, reset the + * hvpipe status and release the lock to prevent any race + * with message event IRQ. + */ +- spin_lock(&hvpipe_src_list_lock); ++ spin_lock_irqsave(&hvpipe_src_list_lock, flags); + src_info = file->private_data; + list_del(&src_info->list); + file->private_data = NULL; +@@ -461,10 +462,10 @@ static int papr_hvpipe_handle_release(st + */ + if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) { + src_info->hvpipe_status = 0; +- spin_unlock(&hvpipe_src_list_lock); ++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + hvpipe_rtas_recv_msg(NULL, 0); + } else +- spin_unlock(&hvpipe_src_list_lock); ++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + + kfree(src_info); + return 0; +@@ -480,20 +481,21 @@ static const struct file_operations papr + static int papr_hvpipe_dev_create_handle(u32 srcID) + { + struct hvpipe_source_info *src_info __free(kfree) = NULL; ++ unsigned long flags; + +- spin_lock(&hvpipe_src_list_lock); ++ spin_lock_irqsave(&hvpipe_src_list_lock, flags); + /* + * Do not allow more than one process communicates with + * each source. + */ + src_info = hvpipe_find_source(srcID); + if (src_info) { +- spin_unlock(&hvpipe_src_list_lock); ++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + pr_err("pid(%d) is already using the source(%d)\n", + src_info->tsk->pid, srcID); + return -EALREADY; + } +- spin_unlock(&hvpipe_src_list_lock); ++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + + src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT); + if (!src_info) +@@ -510,18 +512,18 @@ static int papr_hvpipe_dev_create_handle + return fdf.err; + + retain_and_null_ptr(src_info); +- spin_lock(&hvpipe_src_list_lock); ++ spin_lock_irqsave(&hvpipe_src_list_lock, flags); + /* + * If two processes are executing ioctl() for the same + * source ID concurrently, prevent the second process to + * acquire FD. + */ + if (hvpipe_find_source(srcID)) { +- spin_unlock(&hvpipe_src_list_lock); ++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + return -EALREADY; + } + list_add(&src_info->list, &hvpipe_src_list); +- spin_unlock(&hvpipe_src_list_lock); ++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + return fd_publish(fdf); + } + diff --git a/queue-7.0/pseries-papr-hvpipe-fix-simplify-error-handling-in-papr_hvpipe_init.patch b/queue-7.0/pseries-papr-hvpipe-fix-simplify-error-handling-in-papr_hvpipe_init.patch new file mode 100644 index 0000000000..995ff4d084 --- /dev/null +++ b/queue-7.0/pseries-papr-hvpipe-fix-simplify-error-handling-in-papr_hvpipe_init.patch @@ -0,0 +1,84 @@ +From 713e468cdbc2277db6ce949c32c1acbd83501733 Mon Sep 17 00:00:00 2001 +From: "Ritesh Harjani (IBM)" +Date: Fri, 1 May 2026 09:41:43 +0530 +Subject: pseries/papr-hvpipe: Fix & simplify error handling in papr_hvpipe_init() + +From: Ritesh Harjani (IBM) + +commit 713e468cdbc2277db6ce949c32c1acbd83501733 upstream. + +Remove such 3 levels of nesting patterns to check success return values +from function calls. + +ret = enable_hvpipe_IRQ() + if (!ret) + ret = set_hvpipe_sys_param(1) + if (!ret) + ret = misc_register() + +Instead just bail out to "out*:" labels, in case of any error. This +simplifies the init flow. + +While at it let's also fix the following error handling logic: +We have already enabled interrupt sources and enabled hvpipe to received +interrupts, if misc_register() fails, we will destroy the workqueue, but +the HMC might send us a msg via hvpipe which will call, queue work on +the workqueue which might be destroyed. + +So instead, let's reverse the order of enabling set_hvpipe_sys_param(1) +and in case of an error let's remove the misc dev by calling +misc_deregister(). + +Cc: stable@vger.kernel.org +Fixes: 39a08a4f94980 ("powerpc/pseries: Enable hvpipe with ibm,set-system-parameter RTAS") +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/f2141eafb80e7780395e03aa9a22e8a37be80513.1777606826.git.ritesh.list@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/papr-hvpipe.c | 28 ++++++++++++++++----------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c ++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c +@@ -780,23 +780,29 @@ static int __init papr_hvpipe_init(void) + } + + ret = enable_hvpipe_IRQ(); +- if (!ret) { +- ret = set_hvpipe_sys_param(1); +- if (!ret) +- ret = misc_register(&papr_hvpipe_dev); +- } ++ if (ret) ++ goto out_wq; + +- if (!ret) { +- pr_info("hvpipe feature is enabled\n"); +- hvpipe_feature = true; +- return 0; +- } ++ ret = misc_register(&papr_hvpipe_dev); ++ if (ret) ++ goto out_wq; + +- pr_err("hvpipe feature is not enabled %d\n", ret); ++ ret = set_hvpipe_sys_param(1); ++ if (ret) ++ goto out_misc; ++ ++ pr_info("hvpipe feature is enabled\n"); ++ hvpipe_feature = true; ++ return 0; ++ ++out_misc: ++ misc_deregister(&papr_hvpipe_dev); ++out_wq: + destroy_workqueue(papr_hvpipe_wq); + out: + kfree(papr_hvpipe_work); + papr_hvpipe_work = NULL; ++ pr_err("hvpipe feature is not enabled %d\n", ret); + return ret; + } + machine_device_initcall(pseries, papr_hvpipe_init); diff --git a/queue-7.0/pseries-papr-hvpipe-fix-the-usage-of-copy_to_user.patch b/queue-7.0/pseries-papr-hvpipe-fix-the-usage-of-copy_to_user.patch new file mode 100644 index 0000000000..687881e79e --- /dev/null +++ b/queue-7.0/pseries-papr-hvpipe-fix-the-usage-of-copy_to_user.patch @@ -0,0 +1,97 @@ +From d48654bd8b1a75f662e224d257db54de475120dc Mon Sep 17 00:00:00 2001 +From: "Ritesh Harjani (IBM)" +Date: Fri, 1 May 2026 09:41:44 +0530 +Subject: pseries/papr-hvpipe: Fix the usage of copy_to_user() + +From: Ritesh Harjani (IBM) + +commit d48654bd8b1a75f662e224d257db54de475120dc upstream. + +copy_to_user() return bytes_not_copied to the user buffer. If there was +an error writing bytes into the user buffer, i.e. if copy_to_user +returns a non-zero value, then we should simply return -EFAULT from the +->read() call. + +Otherwise, in the non-patched version, we may end up mixing +"bytes_not_copied + bytes_copied (HVPIPE_HDR_LEN)" as the return value +to the user in ->read() call + +Also let's make sure we clear the hvpipe_status flag, if we have +consumed the hvpipe msg by making the rtas call. ret = -EFAULT means +copy_to_user has failed but that still means that the msg was read from +the hvpipe, hence for both cases, success & -EFAULT, we should clear the +HVPIPE_MSG_AVAILABLE flag in hvpipe_status. + +Cc: stable@vger.kernel.org +Fixes: cebdb522fd3edd1 ("powerpc/pseries: Receive payload with ibm,receive-hvpipe-msg RTAS") +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/8fda3212a1ad48879c174e92f67472d9b9f1c3b7.1777606826.git.ritesh.list@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/papr-hvpipe.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c ++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c +@@ -206,10 +206,11 @@ static int hvpipe_rtas_recv_msg(char __u + bytes_written, size); + bytes_written = size; + } +- ret = copy_to_user(buf, ++ if (copy_to_user(buf, + rtas_work_area_raw_buf(work_area), +- bytes_written); +- if (!ret) ++ bytes_written)) ++ ret = -EFAULT; ++ else + ret = bytes_written; + } + } else { +@@ -328,7 +329,7 @@ static ssize_t papr_hvpipe_handle_read(s + + struct hvpipe_source_info *src_info = file->private_data; + struct papr_hvpipe_hdr hdr = {}; +- long ret; ++ ssize_t ret = 0; + + /* + * Return -ENXIO during migration +@@ -376,7 +377,7 @@ static ssize_t papr_hvpipe_handle_read(s + + ret = copy_to_user(buf, &hdr, HVPIPE_HDR_LEN); + if (ret) +- return ret; ++ return -EFAULT; + + /* + * Message event has payload, so get the payload with +@@ -385,19 +386,23 @@ static ssize_t papr_hvpipe_handle_read(s + if (hdr.flags & HVPIPE_MSG_AVAILABLE) { + ret = hvpipe_rtas_recv_msg(buf + HVPIPE_HDR_LEN, + size - HVPIPE_HDR_LEN); +- if (ret > 0) { ++ /* ++ * Always clear MSG_AVAILABLE once the RTAS call has drained ++ * the message, regardless of whether copy_to_user succeeded. ++ */ ++ if (ret >= 0 || ret == -EFAULT) + src_info->hvpipe_status &= ~HVPIPE_MSG_AVAILABLE; +- ret += HVPIPE_HDR_LEN; +- } + } else if (hdr.flags & HVPIPE_LOST_CONNECTION) { + /* + * Hypervisor is closing the pipe for the specific + * source. So notify user space. + */ + src_info->hvpipe_status &= ~HVPIPE_LOST_CONNECTION; +- ret = HVPIPE_HDR_LEN; + } + ++ if (ret >= 0) ++ ret += HVPIPE_HDR_LEN; ++ + return ret; + } + diff --git a/queue-7.0/pseries-papr-hvpipe-prevent-kernel-stack-memory-leak-to-userspace.patch b/queue-7.0/pseries-papr-hvpipe-prevent-kernel-stack-memory-leak-to-userspace.patch new file mode 100644 index 0000000000..f3ccfc9a1c --- /dev/null +++ b/queue-7.0/pseries-papr-hvpipe-prevent-kernel-stack-memory-leak-to-userspace.patch @@ -0,0 +1,37 @@ +From cefeed44296261173a806bef988b26bc565da4be Mon Sep 17 00:00:00 2001 +From: "Ritesh Harjani (IBM)" +Date: Fri, 1 May 2026 09:41:41 +0530 +Subject: pseries/papr-hvpipe: Prevent kernel stack memory leak to userspace + +From: Ritesh Harjani (IBM) + +commit cefeed44296261173a806bef988b26bc565da4be upstream. + +The hdr variable is allocated on the stack and only hdr.version and +hdr.flags are initialized explicitly. Because the struct papr_hvpipe_hdr +contains reserved padding bytes (reserved[3] and reserved2[40]), these +could leak the uninitialized bytes to userspace after copy_to_user(). + +This patch fixes that by initializing the whole struct to 0. + +Cc: stable@vger.kernel.org +Fixes: cebdb522fd3ed ("powerpc/pseries: Receive payload with ibm,receive-hvpipe-msg RTAS") +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/7bfe03b65a282c856ed8182d1871bb973c0b78f2.1777606826.git.ritesh.list@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/papr-hvpipe.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c ++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c +@@ -327,7 +327,7 @@ static ssize_t papr_hvpipe_handle_read(s + { + + struct hvpipe_source_info *src_info = file->private_data; +- struct papr_hvpipe_hdr hdr; ++ struct papr_hvpipe_hdr hdr = {}; + long ret; + + /* diff --git a/queue-7.0/series b/queue-7.0/series index 7046576531..578ff0ff07 100644 --- a/queue-7.0/series +++ b/queue-7.0/series @@ -108,3 +108,60 @@ selftests-rseq-skip-tests-if-time-slice-extensions-are-not-available.patch selftests-rseq-validate-legacy-behavior.patch selftests-rseq-expand-for-optimized-rseq-abi-v2.patch accel-ivpu-disallow-re-exporting-imported-gem-objects.patch +sound-ua101-fix-division-by-zero-at-probe.patch +pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch +pseries-papr-hvpipe-prevent-kernel-stack-memory-leak-to-userspace.patch +pseries-papr-hvpipe-fix-null-ptr-deref-in-papr_hvpipe_dev_create_handle.patch +pseries-papr-hvpipe-fix-simplify-error-handling-in-papr_hvpipe_init.patch +pseries-papr-hvpipe-fix-the-usage-of-copy_to_user.patch +net-libwx-fix-vf-illegal-register-access.patch +ip6_gre-use-cached-t-net-in-ip6erspan_changelink.patch +net-libwx-use-request_irq-for-vf-misc-interrupt.patch +netpoll-pass-buffer-size-to-egress_dev-to-avoid-mac-truncation.patch +net-rds-handle-zerocopy-send-cleanup-before-the-message-is-queued.patch +net-wwan-t7xx-validate-port_count-against-message-length-in-t7xx_port_enum_msg_handler.patch +ovl-fix-verity-lazy-load-guard-broken-by-fsverity_active-semantic-change.patch +platform-chrome-cros_ec_typec-init-mutex-in-thunderbolt-registration.patch +parisc-fix-irq-leak-in-lasi-driver.patch +x86-efi-fix-graceful-fault-handling-after-fpu-softirq-changes.patch +hwmon-ltc2992-clamp-threshold-writes-to-hardware-range.patch +hwmon-ltc2992-fix-u32-overflow-in-power-read-path.patch +clk-rk808-fix-of-node-reference-imbalance.patch +hwmon-corsair-psu-close-hid-device-on-probe-errors.patch +af_unix-reject-siocatmark-on-non-stream-sockets.patch +arm64-fpsimd-ptrace-zero-target-s-fpsimd_state-not-the-tracer-s.patch +pmdomain-mediatek-fix-use-after-free-in-scpsys_get_bus_protection_legacy.patch +block-add-pgmap-check-to-biovec_phys_mergeable.patch +block-fix-zone-write-plug-removal.patch +block-only-read-from-sqe-on-initial-invocation-of-blkdev_uring_cmd.patch +cifs-abort-open_cached_dir-if-we-don-t-request-leases.patch +cifs-change_conf-needs-to-be-called-for-session-setup.patch +extcon-ptn5150-handle-pending-irq-events-during-system-resume.patch +fbcon-avoid-oob-font-access-if-console-rotation-fails.patch +gpio-of-clear-of_populated-on-hog-nodes-in-remove-path.patch +hv-select-config_sysfb-only-for-config_hyperv_vmbus.patch +hv_sock-fix-arm64-support.patch +hv_sock-report-eof-instead-of-eio-for-fin.patch +hv_sock-return-eio-for-malformed-short-packets.patch +ibmveth-disable-gso-for-packets-with-small-mss.patch +ice-fix-double-free-in-ice_sf_eth_activate-error-path.patch +spi-microchip-core-qspi-fix-controller-deregistration.patch +spi-microchip-core-spi-fix-controller-deregistration.patch +spi-microchip-core-qspi-don-t-attempt-to-transmit-during-emulated-read-only-dual-quad-operations.patch +spi-microchip-core-qspi-control-built-in-cs-manually.patch +tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch +udf-reject-descriptors-with-oversized-crc-length.patch +x86-boot-e820-re-enable-bios-fallback-if-e820-table-is-empty.patch +thermal-core-free-thermal-zone-id-later-during-removal.patch +thermal-drivers-sprd-fix-temperature-clamping-in-sprd_thm_temp_to_rawdata.patch +thermal-drivers-sprd-fix-raw-temperature-clamping-in-sprd_thm_rawdata_to_temp.patch +spi-topcliff-pch-fix-controller-deregistration.patch +spi-topcliff-pch-fix-use-after-free-on-unbind.patch +tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch +tracing-fprobe-remove-fprobe-from-hash-in-failure-path.patch +tracing-fprobe-unregister-fprobe-even-if-memory-allocation-fails.patch +tracing-probes-limit-size-of-event-probe-to-3k.patch +tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch +clk-imx-imx8-acm-fix-flags-for-acm-clocks.patch +clk-microchip-mpfs-ccc-fix-out-of-bounds-access-during-output-registration.patch +cpuidle-powerpc-avoid-double-clear-when-breaking-snooze.patch diff --git a/queue-7.0/sound-ua101-fix-division-by-zero-at-probe.patch b/queue-7.0/sound-ua101-fix-division-by-zero-at-probe.patch new file mode 100644 index 0000000000..73298cd46d --- /dev/null +++ b/queue-7.0/sound-ua101-fix-division-by-zero-at-probe.patch @@ -0,0 +1,45 @@ +From d1f73f169c1014463b5060e3f60813e13ddc7b87 Mon Sep 17 00:00:00 2001 +From: SeungJu Cheon +Date: Sun, 26 Apr 2026 20:12:39 +0900 +Subject: sound: ua101: fix division by zero at probe + +From: SeungJu Cheon + +commit d1f73f169c1014463b5060e3f60813e13ddc7b87 upstream. + +Add a missing sanity check for bNrChannels in detect_usb_format() +to prevent a division by zero in playback_urb_complete() and +capture_urb_complete(). + +USB core does not validate class-specific descriptor fields such +as bNrChannels, so drivers must verify them before use. If a +device provides bNrChannels = 0, frame_bytes becomes zero and is +later used as a divisor in the URB completion handlers, leading +to a kernel crash. + +Fixes: 63978ab3e3e9 ("sound: add Edirol UA-101 support") +Cc: stable@vger.kernel.org +Signed-off-by: SeungJu Cheon +Link: https://patch.msgid.link/20260426111239.103296-1-suunj1331@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/usb/misc/ua101.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/sound/usb/misc/ua101.c ++++ b/sound/usb/misc/ua101.c +@@ -974,6 +974,13 @@ static int detect_usb_format(struct ua10 + + ua->capture.channels = fmt_capture->bNrChannels; + ua->playback.channels = fmt_playback->bNrChannels; ++ if (!ua->capture.channels || !ua->playback.channels) { ++ dev_err(&ua->dev->dev, ++ "invalid channel count: capture %u, playback %u\n", ++ ua->capture.channels, ua->playback.channels); ++ return -EINVAL; ++ } ++ + ua->capture.frame_bytes = + fmt_capture->bSubframeSize * ua->capture.channels; + ua->playback.frame_bytes = diff --git a/queue-7.0/spi-microchip-core-qspi-control-built-in-cs-manually.patch b/queue-7.0/spi-microchip-core-qspi-control-built-in-cs-manually.patch new file mode 100644 index 0000000000..10dd9f0061 --- /dev/null +++ b/queue-7.0/spi-microchip-core-qspi-control-built-in-cs-manually.patch @@ -0,0 +1,193 @@ +From 7672749e1496215e8683ce57cf323119033954cf Mon Sep 17 00:00:00 2001 +From: Conor Dooley +Date: Thu, 30 Apr 2026 11:10:18 +0100 +Subject: spi: microchip-core-qspi: control built-in cs manually + +From: Conor Dooley + +commit 7672749e1496215e8683ce57cf323119033954cf upstream. + +The coreQSPI IP supports only a single chip select, which is +automagically operated by the hardware - set low when the transmit +buffer first gets written to and set high when the number of bytes +written to the TOTALBYTES field of the FRAMES register have been sent on +the bus. Additional devices must use GPIOs for their chip selects. +It was reported to me that if there are two devices attached to this +QSPI controller that the in-built chip select is set low while linux +tries to access the device attached to the GPIO. + +This went undetected as the boards that connected multiple devices to +the SPI controller all exclusively used GPIOs for chip selects, not +relying on the built-in chip select at all. It turns out that this was +because the built-in chip select, when controlled automagically, is set +low when active and high when inactive, thereby ruling out its use for +active-high devices or devices that need to transmit with the chip +select disabled. + +Modify the driver so that it controls chip select directly, retaining +the behaviour for mem_ops of setting the chip select active for the +entire duration of the transfer in the exec_op callback. For regular +transfers, implement the set_cs callback for the core to use. + +As part of this, the existing setup callback, mchp_coreqspi_setup_op(), +is removed. Modifying the CLKIDLE field is not safe to do during +operation when there are multiple devices, so this code is removed +entirely. Setting the MASTER and ENABLE fields is something that can be +done once at probe, it doesn't need to be re-run for each device. +Instead the new setup callback sets the built-in chip select to its +inactive state for active-low devices, as the reset value of the chip +select in software controlled mode is low. + +Fixes: 8f9cf02c88528 ("spi: microchip-core-qspi: Add regular transfers") +Fixes: 8596124c4c1bc ("spi: microchip-core-qspi: Add support for microchip fpga qspi controllers") +CC: stable@vger.kernel.org +Signed-off-by: Conor Dooley +Link: https://patch.msgid.link/20260430-hamstring-busload-f941d0347b5e@spud +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-microchip-core-qspi.c | 79 +++++++++++++++++++++++++++------- + 1 file changed, 64 insertions(+), 15 deletions(-) + +--- a/drivers/spi/spi-microchip-core-qspi.c ++++ b/drivers/spi/spi-microchip-core-qspi.c +@@ -74,6 +74,13 @@ + #define STATUS_FLAGSX4 BIT(8) + #define STATUS_MASK GENMASK(8, 0) + ++/* ++ * QSPI Direct Access register defines ++ */ ++#define DIRECT_ACCESS_EN_SSEL BIT(0) ++#define DIRECT_ACCESS_OP_SSEL BIT(1) ++#define DIRECT_ACCESS_OP_SSEL_SHIFT 1 ++ + #define BYTESUPPER_MASK GENMASK(31, 16) + #define BYTESLOWER_MASK GENMASK(15, 0) + +@@ -158,6 +165,38 @@ static int mchp_coreqspi_set_mode(struct + return 0; + } + ++static void mchp_coreqspi_set_cs(struct spi_device *spi, bool enable) ++{ ++ struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller); ++ u32 val; ++ ++ val = readl(qspi->regs + REG_DIRECT_ACCESS); ++ ++ val &= ~DIRECT_ACCESS_OP_SSEL; ++ val |= !enable << DIRECT_ACCESS_OP_SSEL_SHIFT; ++ ++ writel(val, qspi->regs + REG_DIRECT_ACCESS); ++} ++ ++static int mchp_coreqspi_setup(struct spi_device *spi) ++{ ++ struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller); ++ u32 val; ++ ++ /* ++ * Active low devices need to be specifically set to their inactive ++ * states during probe. ++ */ ++ if (spi->mode & SPI_CS_HIGH) ++ return 0; ++ ++ val = readl(qspi->regs + REG_DIRECT_ACCESS); ++ val |= DIRECT_ACCESS_OP_SSEL; ++ writel(val, qspi->regs + REG_DIRECT_ACCESS); ++ ++ return 0; ++} ++ + static inline void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi) + { + u32 control, data; +@@ -380,19 +419,6 @@ static int mchp_coreqspi_setup_clock(str + return 0; + } + +-static int mchp_coreqspi_setup_op(struct spi_device *spi_dev) +-{ +- struct spi_controller *ctlr = spi_dev->controller; +- struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr); +- u32 control = readl_relaxed(qspi->regs + REG_CONTROL); +- +- control |= (CONTROL_MASTER | CONTROL_ENABLE); +- control &= ~CONTROL_CLKIDLE; +- writel_relaxed(control, qspi->regs + REG_CONTROL); +- +- return 0; +-} +- + static inline void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const struct spi_mem_op *op) + { + u32 idle_cycles = 0; +@@ -483,6 +509,7 @@ static int mchp_coreqspi_exec_op(struct + + reinit_completion(&qspi->data_completion); + mchp_coreqspi_config_op(qspi, op); ++ mchp_coreqspi_set_cs(mem->spi, true); + if (op->cmd.opcode) { + qspi->txbuf = &opcode; + qspi->rxbuf = NULL; +@@ -523,6 +550,7 @@ static int mchp_coreqspi_exec_op(struct + err = -ETIMEDOUT; + + error: ++ mchp_coreqspi_set_cs(mem->spi, false); + mutex_unlock(&qspi->op_lock); + mchp_coreqspi_disable_ints(qspi); + +@@ -696,6 +724,7 @@ static int mchp_coreqspi_probe(struct pl + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; ++ u32 num_cs, val; + + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*qspi)); + if (!ctlr) +@@ -728,10 +757,18 @@ static int mchp_coreqspi_probe(struct pl + return ret; + } + ++ /* ++ * The IP core only has a single CS, any more have to be provided via ++ * gpios ++ */ ++ if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs)) ++ num_cs = 1; ++ ++ ctlr->num_chipselect = num_cs; ++ + ctlr->bits_per_word_mask = SPI_BPW_MASK(8); + ctlr->mem_ops = &mchp_coreqspi_mem_ops; + ctlr->mem_caps = &mchp_coreqspi_mem_caps; +- ctlr->setup = mchp_coreqspi_setup_op; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD | + SPI_TX_DUAL | SPI_TX_QUAD; + ctlr->dev.of_node = np; +@@ -739,9 +776,21 @@ static int mchp_coreqspi_probe(struct pl + ctlr->prepare_message = mchp_coreqspi_prepare_message; + ctlr->unprepare_message = mchp_coreqspi_unprepare_message; + ctlr->transfer_one = mchp_coreqspi_transfer_one; +- ctlr->num_chipselect = 2; ++ ctlr->setup = mchp_coreqspi_setup; ++ ctlr->set_cs = mchp_coreqspi_set_cs; + ctlr->use_gpio_descriptors = true; + ++ val = readl_relaxed(qspi->regs + REG_CONTROL); ++ val |= (CONTROL_MASTER | CONTROL_ENABLE); ++ writel_relaxed(val, qspi->regs + REG_CONTROL); ++ ++ /* ++ * Put cs into software controlled mode ++ */ ++ val = readl_relaxed(qspi->regs + REG_DIRECT_ACCESS); ++ val |= DIRECT_ACCESS_EN_SSEL; ++ writel(val, qspi->regs + REG_DIRECT_ACCESS); ++ + ret = spi_register_controller(ctlr); + if (ret) + return dev_err_probe(&pdev->dev, ret, diff --git a/queue-7.0/spi-microchip-core-qspi-don-t-attempt-to-transmit-during-emulated-read-only-dual-quad-operations.patch b/queue-7.0/spi-microchip-core-qspi-don-t-attempt-to-transmit-during-emulated-read-only-dual-quad-operations.patch new file mode 100644 index 0000000000..42ecf7e7a4 --- /dev/null +++ b/queue-7.0/spi-microchip-core-qspi-don-t-attempt-to-transmit-during-emulated-read-only-dual-quad-operations.patch @@ -0,0 +1,59 @@ +From eb56deaabf127e8985fc91fa6c97bf8a3b062844 Mon Sep 17 00:00:00 2001 +From: Conor Dooley +Date: Thu, 30 Apr 2026 11:10:19 +0100 +Subject: spi: microchip-core-qspi: don't attempt to transmit during emulated read-only dual/quad operations + +From: Conor Dooley + +commit eb56deaabf127e8985fc91fa6c97bf8a3b062844 upstream. + +The core will deal with reads by creating clock cycles itself, there's +no need to generate clock cycles by transmitting garbage data at the +driver level. Further, transmitting garbage data just bricks the transfer +since QSPI doesn't have a dedicated master-out line like MOSI in regular +SPI. I'm not entirely sure if the transfer is bricked because of the +garbage data being transmitted on the bus or because the core loses +track of whether it is supposed to be sending or receiving data. + +Fixes: 8f9cf02c88528 ("spi: microchip-core-qspi: Add regular transfers") +CC: stable@vger.kernel.org +Signed-off-by: Conor Dooley +Link: https://patch.msgid.link/20260430-freezing-saloon-95b1f3d9dad0@spud +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-microchip-core-qspi.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-microchip-core-qspi.c ++++ b/drivers/spi/spi-microchip-core-qspi.c +@@ -662,18 +662,28 @@ static int mchp_coreqspi_transfer_one(st + struct spi_transfer *t) + { + struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr); ++ bool dual_quad = false; + + qspi->tx_len = t->len; + ++ if (t->tx_nbits == SPI_NBITS_QUAD || t->rx_nbits == SPI_NBITS_QUAD || ++ t->tx_nbits == SPI_NBITS_DUAL || ++ t->rx_nbits == SPI_NBITS_DUAL) ++ dual_quad = true; ++ + if (t->tx_buf) + qspi->txbuf = (u8 *)t->tx_buf; + + if (!t->rx_buf) { + mchp_coreqspi_write_op(qspi); +- } else { ++ } else if (!dual_quad) { + qspi->rxbuf = (u8 *)t->rx_buf; + qspi->rx_len = t->len; + mchp_coreqspi_write_read_op(qspi); ++ } else { ++ qspi->rxbuf = (u8 *)t->rx_buf; ++ qspi->rx_len = t->len; ++ mchp_coreqspi_read_op(qspi); + } + + return 0; diff --git a/queue-7.0/spi-microchip-core-qspi-fix-controller-deregistration.patch b/queue-7.0/spi-microchip-core-qspi-fix-controller-deregistration.patch new file mode 100644 index 0000000000..37f53cb10f --- /dev/null +++ b/queue-7.0/spi-microchip-core-qspi-fix-controller-deregistration.patch @@ -0,0 +1,60 @@ +From e6464140d439f2d42f072eb422a5b1fec470c5a6 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 9 Apr 2026 14:04:17 +0200 +Subject: spi: microchip-core-qspi: fix controller deregistration + +From: Johan Hovold + +commit e6464140d439f2d42f072eb422a5b1fec470c5a6 upstream. + +Make sure to deregister the controller before disabling underlying +resources like interrupts during driver unbind. + +Fixes: 8596124c4c1b ("spi: microchip-core-qspi: Add support for microchip fpga qspi controllers") +Cc: stable@vger.kernel.org # 6.1 +Cc: Naga Sureshkumar Relli +Signed-off-by: Johan Hovold +Acked-by: Conor Dooley +Link: https://patch.msgid.link/20260409120419.388546-19-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-microchip-core-qspi.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/spi/spi-microchip-core-qspi.c ++++ b/drivers/spi/spi-microchip-core-qspi.c +@@ -692,7 +692,7 @@ static int mchp_coreqspi_probe(struct pl + return -ENOMEM; + + qspi = spi_controller_get_devdata(ctlr); +- platform_set_drvdata(pdev, qspi); ++ platform_set_drvdata(pdev, ctlr); + + qspi->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(qspi->regs)) +@@ -732,7 +732,7 @@ static int mchp_coreqspi_probe(struct pl + ctlr->num_chipselect = 2; + ctlr->use_gpio_descriptors = true; + +- ret = devm_spi_register_controller(&pdev->dev, ctlr); ++ ret = spi_register_controller(ctlr); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "spi_register_controller failed\n"); +@@ -742,9 +742,13 @@ static int mchp_coreqspi_probe(struct pl + + static void mchp_coreqspi_remove(struct platform_device *pdev) + { +- struct mchp_coreqspi *qspi = platform_get_drvdata(pdev); +- u32 control = readl_relaxed(qspi->regs + REG_CONTROL); ++ struct spi_controller *ctlr = platform_get_drvdata(pdev); ++ struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr); ++ u32 control; + ++ spi_unregister_controller(ctlr); ++ ++ control = readl_relaxed(qspi->regs + REG_CONTROL); + mchp_coreqspi_disable_ints(qspi); + control &= ~CONTROL_ENABLE; + writel_relaxed(control, qspi->regs + REG_CONTROL); diff --git a/queue-7.0/spi-microchip-core-spi-fix-controller-deregistration.patch b/queue-7.0/spi-microchip-core-spi-fix-controller-deregistration.patch new file mode 100644 index 0000000000..e7ab9aff6d --- /dev/null +++ b/queue-7.0/spi-microchip-core-spi-fix-controller-deregistration.patch @@ -0,0 +1,49 @@ +From d00d722ebad46cf7a9886684f26a26337b5ee3f4 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 9 Apr 2026 14:04:18 +0200 +Subject: spi: microchip-core-spi: fix controller deregistration + +From: Johan Hovold + +commit d00d722ebad46cf7a9886684f26a26337b5ee3f4 upstream. + +Make sure to deregister the controller before disabling underlying +resources like interrupts during driver unbind. + +Fixes: 059f545832be ("spi: add support for microchip "soft" spi controller") +Cc: stable@vger.kernel.org # 6.19 +Cc: Prajna Rajendra Kumar +Signed-off-by: Johan Hovold +Acked-by: Conor Dooley +Link: https://patch.msgid.link/20260409120419.388546-20-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-microchip-core-spi.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-microchip-core-spi.c b/drivers/spi/spi-microchip-core-spi.c +index a4c128ae391b..be01c178e2b0 100644 +--- a/drivers/spi/spi-microchip-core-spi.c ++++ b/drivers/spi/spi-microchip-core-spi.c +@@ -384,7 +384,7 @@ static int mchp_corespi_probe(struct platform_device *pdev) + + mchp_corespi_init(host, spi); + +- ret = devm_spi_register_controller(dev, host); ++ ret = spi_register_controller(host); + if (ret) { + mchp_corespi_disable_ints(spi); + mchp_corespi_disable(spi); +@@ -399,6 +399,8 @@ static void mchp_corespi_remove(struct platform_device *pdev) + struct spi_controller *host = platform_get_drvdata(pdev); + struct mchp_corespi *spi = spi_controller_get_devdata(host); + ++ spi_unregister_controller(host); ++ + mchp_corespi_disable_ints(spi); + mchp_corespi_disable(spi); + } +-- +2.54.0 + diff --git a/queue-7.0/spi-topcliff-pch-fix-controller-deregistration.patch b/queue-7.0/spi-topcliff-pch-fix-controller-deregistration.patch new file mode 100644 index 0000000000..b79e0f4bc6 --- /dev/null +++ b/queue-7.0/spi-topcliff-pch-fix-controller-deregistration.patch @@ -0,0 +1,46 @@ +From 5d6f477d6fc0767c57c5e1e6f55a1662820eef87 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 14 Apr 2026 15:43:18 +0200 +Subject: spi: topcliff-pch: fix controller deregistration + +From: Johan Hovold + +commit 5d6f477d6fc0767c57c5e1e6f55a1662820eef87 upstream. + +Make sure to deregister the controller before disabling and releasing +underlying resources like interrupts and DMA during driver unbind. + +Fixes: e8b17b5b3f30 ("spi/topcliff: Add topcliff platform controller hub (PCH) spi bus driver") +Cc: stable@vger.kernel.org # 2.6.37 +Cc: Masayuki Ohtake +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260414134319.978196-8-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-topcliff-pch.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-topcliff-pch.c ++++ b/drivers/spi/spi-topcliff-pch.c +@@ -1406,6 +1406,10 @@ static void pch_spi_pd_remove(struct pla + dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", + __func__, plat_dev->id, board_dat->pdev->irq); + ++ spi_controller_get(data->host); ++ ++ spi_unregister_controller(data->host); ++ + if (use_dma) + pch_free_dma_buf(board_dat, data); + +@@ -1433,7 +1437,8 @@ static void pch_spi_pd_remove(struct pla + } + + pci_iounmap(board_dat->pdev, data->io_remap_addr); +- spi_unregister_controller(data->host); ++ ++ spi_controller_put(data->host); + } + #ifdef CONFIG_PM + static int pch_spi_pd_suspend(struct platform_device *pd_dev, diff --git a/queue-7.0/spi-topcliff-pch-fix-use-after-free-on-unbind.patch b/queue-7.0/spi-topcliff-pch-fix-use-after-free-on-unbind.patch new file mode 100644 index 0000000000..8c07a94a8c --- /dev/null +++ b/queue-7.0/spi-topcliff-pch-fix-use-after-free-on-unbind.patch @@ -0,0 +1,45 @@ +From 9d72732fe70c11424bc90ed466c7ccfa58b42a9a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 14 Apr 2026 15:43:19 +0200 +Subject: spi: topcliff-pch: fix use-after-free on unbind + +From: Johan Hovold + +commit 9d72732fe70c11424bc90ed466c7ccfa58b42a9a upstream. + +Give the driver a chance to flush its queue before releasing the DMA +buffers on driver unbind + +Fixes: c37f3c2749b5 ("spi/topcliff_pch: DMA support") +Cc: stable@vger.kernel.org # 3.1 +Cc: Tomoya MORINAGA +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260414134319.978196-9-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-topcliff-pch.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/spi/spi-topcliff-pch.c ++++ b/drivers/spi/spi-topcliff-pch.c +@@ -1410,9 +1410,6 @@ static void pch_spi_pd_remove(struct pla + + spi_unregister_controller(data->host); + +- if (use_dma) +- pch_free_dma_buf(board_dat, data); +- + /* check for any pending messages; no action is taken if the queue + * is still full; but at least we tried. Unload anyway */ + count = 500; +@@ -1436,6 +1433,9 @@ static void pch_spi_pd_remove(struct pla + free_irq(board_dat->pdev->irq, data); + } + ++ if (use_dma) ++ pch_free_dma_buf(board_dat, data); ++ + pci_iounmap(board_dat->pdev, data->io_remap_addr); + + spi_controller_put(data->host); diff --git a/queue-7.0/thermal-core-free-thermal-zone-id-later-during-removal.patch b/queue-7.0/thermal-core-free-thermal-zone-id-later-during-removal.patch new file mode 100644 index 0000000000..2964149db1 --- /dev/null +++ b/queue-7.0/thermal-core-free-thermal-zone-id-later-during-removal.patch @@ -0,0 +1,60 @@ +From daae9c18feec74566e023fc88cfb0ce26e39d868 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Tue, 7 Apr 2026 15:58:34 +0200 +Subject: thermal: core: Free thermal zone ID later during removal + +From: Rafael J. Wysocki + +commit daae9c18feec74566e023fc88cfb0ce26e39d868 upstream. + +The thermal zone removal ordering is different from the thermal zone +registration rollback path ordering and the former is arguably +problematic because freeing a thermal zone ID prematurely may cause +it to be used during the registration of another thermal zone which +may fail as a result. + +Prevent that from occurring by changing the thermal zone removal +ordering to reflect the thermal zone registration rollback path +ordering. + +Also more the ida_destroy() call from thermal_zone_device_unregister() +to thermal_release() for consistency. + +Fixes: b31ef8285b19 ("thermal core: convert ID allocation to IDA") +Cc: All applicable +Signed-off-by: Rafael J. Wysocki +Link: https://patch.msgid.link/5063934.GXAFRqVoOG@rafael.j.wysocki +Signed-off-by: Greg Kroah-Hartman +--- + drivers/thermal/thermal_core.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -965,6 +965,7 @@ static void thermal_release(struct devic + tz = to_thermal_zone(dev); + thermal_zone_destroy_device_groups(tz); + thermal_set_governor(tz, NULL); ++ ida_destroy(&tz->ida); + mutex_destroy(&tz->lock); + complete(&tz->removal); + } else if (!strncmp(dev_name(dev), "cooling_device", +@@ -1730,8 +1731,6 @@ void thermal_zone_device_unregister(stru + + thermal_thresholds_exit(tz); + thermal_remove_hwmon_sysfs(tz); +- ida_free(&thermal_tz_ida, tz->id); +- ida_destroy(&tz->ida); + + device_del(&tz->device); + put_device(&tz->device); +@@ -1739,6 +1738,9 @@ void thermal_zone_device_unregister(stru + thermal_notify_tz_delete(tz); + + wait_for_completion(&tz->removal); ++ ++ ida_free(&thermal_tz_ida, tz->id); ++ + kfree(tz->tzp); + kfree(tz); + } diff --git a/queue-7.0/thermal-drivers-sprd-fix-raw-temperature-clamping-in-sprd_thm_rawdata_to_temp.patch b/queue-7.0/thermal-drivers-sprd-fix-raw-temperature-clamping-in-sprd_thm_rawdata_to_temp.patch new file mode 100644 index 0000000000..84710b7a48 --- /dev/null +++ b/queue-7.0/thermal-drivers-sprd-fix-raw-temperature-clamping-in-sprd_thm_rawdata_to_temp.patch @@ -0,0 +1,38 @@ +From b3414148bbc1f9cd56217e58a558c6ac4fd1b4a6 Mon Sep 17 00:00:00 2001 +From: Thorsten Blum +Date: Sat, 7 Mar 2026 11:24:21 +0100 +Subject: thermal/drivers/sprd: Fix raw temperature clamping in sprd_thm_rawdata_to_temp + +From: Thorsten Blum + +commit b3414148bbc1f9cd56217e58a558c6ac4fd1b4a6 upstream. + +The raw temperature data was never clamped to SPRD_THM_RAW_DATA_LOW or +SPRD_THM_RAW_DATA_HIGH because the return value of clamp() was not used. +Fix this by assigning the clamped value to 'rawdata'. + +Casting SPRD_THM_RAW_DATA_LOW and SPRD_THM_RAW_DATA_HIGH to u32 is also +redundant and can be removed. + +Fixes: 554fdbaf19b1 ("thermal: sprd: Add Spreadtrum thermal driver support") +Signed-off-by: Thorsten Blum +Signed-off-by: Daniel Lezcano +Reviewed-by: Baolin Wang +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260307102422.306055-2-thorsten.blum@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + drivers/thermal/sprd_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/sprd_thermal.c ++++ b/drivers/thermal/sprd_thermal.c +@@ -178,7 +178,7 @@ static int sprd_thm_sensor_calibration(s + static int sprd_thm_rawdata_to_temp(struct sprd_thermal_sensor *sen, + u32 rawdata) + { +- clamp(rawdata, (u32)SPRD_THM_RAW_DATA_LOW, (u32)SPRD_THM_RAW_DATA_HIGH); ++ rawdata = clamp(rawdata, SPRD_THM_RAW_DATA_LOW, SPRD_THM_RAW_DATA_HIGH); + + /* + * According to the thermal datasheet, the formula of converting diff --git a/queue-7.0/thermal-drivers-sprd-fix-temperature-clamping-in-sprd_thm_temp_to_rawdata.patch b/queue-7.0/thermal-drivers-sprd-fix-temperature-clamping-in-sprd_thm_temp_to_rawdata.patch new file mode 100644 index 0000000000..f6a868ccb3 --- /dev/null +++ b/queue-7.0/thermal-drivers-sprd-fix-temperature-clamping-in-sprd_thm_temp_to_rawdata.patch @@ -0,0 +1,38 @@ +From 83c0f9a5d679a6f8d84fc49b2f62ea434ccab4b6 Mon Sep 17 00:00:00 2001 +From: Thorsten Blum +Date: Sat, 7 Mar 2026 11:24:20 +0100 +Subject: thermal/drivers/sprd: Fix temperature clamping in sprd_thm_temp_to_rawdata + +From: Thorsten Blum + +commit 83c0f9a5d679a6f8d84fc49b2f62ea434ccab4b6 upstream. + +The temperature was never clamped to SPRD_THM_TEMP_LOW or +SPRD_THM_TEMP_HIGH because the return value of clamp() was not used. Fix +this by assigning the clamped value to 'temp'. + +Casting SPRD_THM_TEMP_LOW and SPRD_THM_TEMP_HIGH to int is also +redundant and can be removed. + +Fixes: 554fdbaf19b1 ("thermal: sprd: Add Spreadtrum thermal driver support") +Signed-off-by: Thorsten Blum +Signed-off-by: Daniel Lezcano +Reviewed-by: Baolin Wang +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260307102422.306055-1-thorsten.blum@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + drivers/thermal/sprd_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/sprd_thermal.c ++++ b/drivers/thermal/sprd_thermal.c +@@ -192,7 +192,7 @@ static int sprd_thm_temp_to_rawdata(int + { + u32 val; + +- clamp(temp, (int)SPRD_THM_TEMP_LOW, (int)SPRD_THM_TEMP_HIGH); ++ temp = clamp(temp, SPRD_THM_TEMP_LOW, SPRD_THM_TEMP_HIGH); + + /* + * According to the thermal datasheet, the formula of converting diff --git a/queue-7.0/tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch b/queue-7.0/tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch new file mode 100644 index 0000000000..db0ab37bb0 --- /dev/null +++ b/queue-7.0/tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch @@ -0,0 +1,51 @@ +From e8368d1f4bedbb0cce4cfe33a1d2664bb0fd4f27 Mon Sep 17 00:00:00 2001 +From: David Carlier +Date: Sat, 4 Apr 2026 14:47:47 +0100 +Subject: tracefs: Fix default permissions not being applied on initial mount + +From: David Carlier + +commit e8368d1f4bedbb0cce4cfe33a1d2664bb0fd4f27 upstream. + +Commit e4d32142d1de ("tracing: Fix tracefs mount options") moved the +option application from tracefs_fill_super() to tracefs_reconfigure() +called from tracefs_get_tree(). This fixed mount options being ignored +on user-space mounts when the superblock already exists, but introduced +a regression for the initial kernel-internal mount. + +On the first mount (via simple_pin_fs during init), sget_fc() transfers +fc->s_fs_info to sb->s_fs_info and sets fc->s_fs_info to NULL. When +tracefs_get_tree() then calls tracefs_reconfigure(), it sees a NULL +fc->s_fs_info and returns early without applying any options. The root +inode keeps mode 0755 from simple_fill_super() instead of the intended +TRACEFS_DEFAULT_MODE (0700). + +Furthermore, even on subsequent user-space mounts without an explicit +mode= option, tracefs_apply_options(sb, true) gates the mode behind +fsi->opts & BIT(Opt_mode), which is unset for the defaults. So the +mode is never corrected unless the user explicitly passes mode=0700. + +Restore the tracefs_apply_options(sb, false) call in tracefs_fill_super() +to apply default permissions on initial superblock creation, matching +what debugfs does in debugfs_fill_super(). + +Cc: stable@vger.kernel.org +Fixes: e4d32142d1de ("tracing: Fix tracefs mount options") +Link: https://patch.msgid.link/20260404134747.98867-1-devnexen@gmail.com +Signed-off-by: David Carlier +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + fs/tracefs/inode.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/tracefs/inode.c ++++ b/fs/tracefs/inode.c +@@ -491,6 +491,7 @@ static int tracefs_fill_super(struct sup + return err; + + sb->s_op = &tracefs_super_operations; ++ tracefs_apply_options(sb, false); + set_default_d_op(sb, &tracefs_dentry_operations); + + return 0; diff --git a/queue-7.0/tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch b/queue-7.0/tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch new file mode 100644 index 0000000000..835fe2556a --- /dev/null +++ b/queue-7.0/tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch @@ -0,0 +1,183 @@ +From aa72812b49104bb5a38272fc9541feb62ca6fd32 Mon Sep 17 00:00:00 2001 +From: "Masami Hiramatsu (Google)" +Date: Mon, 20 Apr 2026 23:01:12 +0900 +Subject: tracing/fprobe: Avoid kcalloc() in rcu_read_lock section + +From: Masami Hiramatsu (Google) + +commit aa72812b49104bb5a38272fc9541feb62ca6fd32 upstream. + +fprobe_remove_node_in_module() is called under RCU read locked, but +this invokes kcalloc() if there are more than 8 fprobes installed +on the module. Sashiko warns it because kcalloc() can sleep [1]. + + [1] https://sashiko.dev/#/patchset/177552432201.853249.5125045538812833325.stgit%40mhiramat.tok.corp.google.com + +To fix this issue, expand the batch size to 128 and do not expand +the fprobe_addr_list, but just cancel walking on fprobe_ip_table, +update fgraph/ftrace_ops and retry the loop again. + +Link: https://lore.kernel.org/all/177669367206.132053.1493637946869032744.stgit@mhiramat.tok.corp.google.com/ + +Fixes: 0de4c70d04a4 ("tracing: fprobe: use rhltable for fprobe_ip_table") +Cc: stable@vger.kernel.org +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/fprobe.c | 92 ++++++++++++++++++++++++-------------------------- + 1 file changed, 45 insertions(+), 47 deletions(-) + +--- a/kernel/trace/fprobe.c ++++ b/kernel/trace/fprobe.c +@@ -336,11 +336,10 @@ static bool fprobe_is_ftrace(struct fpro + } + + #ifdef CONFIG_MODULES +-static void fprobe_set_ips(unsigned long *ips, unsigned int cnt, int remove, +- int reset) ++static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt) + { +- ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, remove, reset); +- ftrace_set_filter_ips(&fprobe_ftrace_ops, ips, cnt, remove, reset); ++ ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, 1, 0); ++ ftrace_set_filter_ips(&fprobe_ftrace_ops, ips, cnt, 1, 0); + } + #endif + #else +@@ -359,10 +358,9 @@ static bool fprobe_is_ftrace(struct fpro + } + + #ifdef CONFIG_MODULES +-static void fprobe_set_ips(unsigned long *ips, unsigned int cnt, int remove, +- int reset) ++static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt) + { +- ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, remove, reset); ++ ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, 1, 0); + } + #endif + #endif /* !CONFIG_DYNAMIC_FTRACE_WITH_ARGS && !CONFIG_DYNAMIC_FTRACE_WITH_REGS */ +@@ -536,7 +534,7 @@ static void fprobe_graph_remove_ips(unsi + + #ifdef CONFIG_MODULES + +-#define FPROBE_IPS_BATCH_INIT 8 ++#define FPROBE_IPS_BATCH_INIT 128 + /* instruction pointer address list */ + struct fprobe_addr_list { + int index; +@@ -544,45 +542,24 @@ struct fprobe_addr_list { + unsigned long *addrs; + }; + +-static int fprobe_addr_list_add(struct fprobe_addr_list *alist, unsigned long addr) ++static int fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node, ++ struct fprobe_addr_list *alist) + { +- unsigned long *addrs; +- +- /* Previously we failed to expand the list. */ +- if (alist->index == alist->size) +- return -ENOSPC; +- +- alist->addrs[alist->index++] = addr; +- if (alist->index < alist->size) ++ if (!within_module(node->addr, mod)) + return 0; + +- /* Expand the address list */ +- addrs = kcalloc(alist->size * 2, sizeof(*addrs), GFP_KERNEL); +- if (!addrs) +- return -ENOMEM; +- +- memcpy(addrs, alist->addrs, alist->size * sizeof(*addrs)); +- alist->size *= 2; +- kfree(alist->addrs); +- alist->addrs = addrs; ++ if (delete_fprobe_node(node)) ++ return 0; ++ /* If no address list is available, we can't track this address. */ ++ if (!alist->addrs) ++ return 0; + ++ alist->addrs[alist->index++] = node->addr; ++ if (alist->index == alist->size) ++ return -ENOSPC; + return 0; + } + +-static void fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node, +- struct fprobe_addr_list *alist) +-{ +- if (!within_module(node->addr, mod)) +- return; +- if (delete_fprobe_node(node)) +- return; +- /* +- * If failed to update alist, just continue to update hlist. +- * Therefore, at list user handler will not hit anymore. +- */ +- fprobe_addr_list_add(alist, node->addr); +-} +- + /* Handle module unloading to manage fprobe_ip_table. */ + static int fprobe_module_callback(struct notifier_block *nb, + unsigned long val, void *data) +@@ -591,29 +568,50 @@ static int fprobe_module_callback(struct + struct fprobe_hlist_node *node; + struct rhashtable_iter iter; + struct module *mod = data; ++ bool retry; + + if (val != MODULE_STATE_GOING) + return NOTIFY_DONE; + + alist.addrs = kcalloc(alist.size, sizeof(*alist.addrs), GFP_KERNEL); +- /* If failed to alloc memory, we can not remove ips from hash. */ +- if (!alist.addrs) +- return NOTIFY_DONE; ++ /* ++ * If failed to alloc memory, ftrace_ops will not be able to remove ips from ++ * hash, but we can still remove nodes from fprobe_ip_table, so we can avoid ++ * the potential wrong callback. So just print a warning here and try to ++ * continue without address list. ++ */ ++ WARN_ONCE(!alist.addrs, ++ "Failed to allocate memory for fprobe_addr_list, ftrace_ops will not be updated"); + + mutex_lock(&fprobe_mutex); ++again: ++ retry = false; ++ alist.index = 0; + rhltable_walk_enter(&fprobe_ip_table, &iter); + do { + rhashtable_walk_start(&iter); + + while ((node = rhashtable_walk_next(&iter)) && !IS_ERR(node)) +- fprobe_remove_node_in_module(mod, node, &alist); ++ if (fprobe_remove_node_in_module(mod, node, &alist) < 0) { ++ retry = true; ++ break; ++ } + + rhashtable_walk_stop(&iter); +- } while (node == ERR_PTR(-EAGAIN)); ++ } while (node == ERR_PTR(-EAGAIN) && !retry); + rhashtable_walk_exit(&iter); ++ /* Remove any ips from hash table(s) */ ++ if (alist.index > 0) { ++ fprobe_remove_ips(alist.addrs, alist.index); ++ /* ++ * If we break rhashtable walk loop except for -EAGAIN, we need ++ * to restart looping from start for safety. Anyway, this is ++ * not a hotpath. ++ */ ++ if (retry) ++ goto again; ++ } + +- if (alist.index > 0) +- fprobe_set_ips(alist.addrs, alist.index, 1, 0); + mutex_unlock(&fprobe_mutex); + + kfree(alist.addrs); diff --git a/queue-7.0/tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch b/queue-7.0/tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch new file mode 100644 index 0000000000..14331aa321 --- /dev/null +++ b/queue-7.0/tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch @@ -0,0 +1,203 @@ +From 0ac0058a74ac5765c7ce09ea630f4fdeaf4d80fa Mon Sep 17 00:00:00 2001 +From: "Masami Hiramatsu (Google)" +Date: Mon, 20 Apr 2026 23:01:20 +0900 +Subject: tracing/fprobe: Check the same type fprobe on table as the unregistered one + +From: Masami Hiramatsu (Google) + +commit 0ac0058a74ac5765c7ce09ea630f4fdeaf4d80fa upstream. + +Commit 2c67dc457bc6 ("tracing: fprobe: optimization for entry only case") +introduced a different ftrace_ops for entry-only fprobes. + +However, when unregistering an fprobe, the kernel only checks if another +fprobe exists at the same address, without checking which type of fprobe +it is. +If different fprobes are registered at the same address, the same address +will be registered in both fgraph_ops and ftrace_ops, but only one of +them will be deleted when unregistering. (the one removed first will not +be deleted from the ops). + +This results in junk entries remaining in either fgraph_ops or ftrace_ops. +For example: + ======= + cd /sys/kernel/tracing + + # 'Add entry and exit events on the same place' + echo 'f:event1 vfs_read' >> dynamic_events + echo 'f:event2 vfs_read%return' >> dynamic_events + + # 'Enable both of them' + echo 1 > events/fprobes/enable + cat enabled_functions +vfs_read (2) ->arch_ftrace_ops_list_func+0x0/0x210 + + # 'Disable and remove exit event' + echo 0 > events/fprobes/event2/enable + echo -:event2 >> dynamic_events + + # 'Disable and remove all events' + echo 0 > events/fprobes/enable + echo > dynamic_events + + # 'Add another event' + echo 'f:event3 vfs_open%return' > dynamic_events + cat dynamic_events +f:fprobes/event3 vfs_open%return + + echo 1 > events/fprobes/enable + cat enabled_functions +vfs_open (1) tramp: 0xffffffffa0001000 (ftrace_graph_func+0x0/0x60) ->ftrace_graph_func+0x0/0x60 subops: {ent:fprobe_fgraph_entry+0x0/0x620 ret:fprobe_return+0x0/0x150} +vfs_read (1) tramp: 0xffffffffa0001000 (ftrace_graph_func+0x0/0x60) ->ftrace_graph_func+0x0/0x60 subops: {ent:fprobe_fgraph_entry+0x0/0x620 ret:fprobe_return+0x0/0x150} + ======= + +As you can see, an entry for the vfs_read remains. + +To fix this issue, when unregistering, the kernel should also check if +there is the same type of fprobes still exist at the same address, and +if not, delete its entry from either fgraph_ops or ftrace_ops. + +Link: https://lore.kernel.org/all/177669367993.132053.10553046138528674802.stgit@mhiramat.tok.corp.google.com/ + +Fixes: 2c67dc457bc6 ("tracing: fprobe: optimization for entry only case") +Cc: stable@vger.kernel.org +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/fprobe.c | 82 +++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 65 insertions(+), 17 deletions(-) + +--- a/kernel/trace/fprobe.c ++++ b/kernel/trace/fprobe.c +@@ -92,11 +92,8 @@ static int insert_fprobe_node(struct fpr + return ret; + } + +-/* Return true if there are synonims */ +-static bool delete_fprobe_node(struct fprobe_hlist_node *node) ++static void delete_fprobe_node(struct fprobe_hlist_node *node) + { +- bool ret; +- + lockdep_assert_held(&fprobe_mutex); + + /* Avoid double deleting and non-inserted nodes */ +@@ -105,13 +102,6 @@ static bool delete_fprobe_node(struct fp + rhltable_remove(&fprobe_ip_table, &node->hlist, + fprobe_rht_params); + } +- +- rcu_read_lock(); +- ret = !!rhltable_lookup(&fprobe_ip_table, &node->addr, +- fprobe_rht_params); +- rcu_read_unlock(); +- +- return ret; + } + + /* Check existence of the fprobe */ +@@ -343,6 +333,32 @@ static bool fprobe_is_ftrace(struct fpro + return !fp->exit_handler; + } + ++static bool fprobe_exists_on_hash(unsigned long ip, bool ftrace) ++{ ++ struct rhlist_head *head, *pos; ++ struct fprobe_hlist_node *node; ++ struct fprobe *fp; ++ ++ guard(rcu)(); ++ head = rhltable_lookup(&fprobe_ip_table, &ip, ++ fprobe_rht_params); ++ if (!head) ++ return false; ++ /* We have to check the same type on the list. */ ++ rhl_for_each_entry_rcu(node, pos, head, hlist) { ++ if (node->addr != ip) ++ break; ++ fp = READ_ONCE(node->fp); ++ if (likely(fp)) { ++ if ((!ftrace && fp->exit_handler) || ++ (ftrace && !fp->exit_handler)) ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + #ifdef CONFIG_MODULES + static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt) + { +@@ -365,6 +381,29 @@ static bool fprobe_is_ftrace(struct fpro + return false; + } + ++static bool fprobe_exists_on_hash(unsigned long ip, bool ftrace __maybe_unused) ++{ ++ struct rhlist_head *head, *pos; ++ struct fprobe_hlist_node *node; ++ struct fprobe *fp; ++ ++ guard(rcu)(); ++ head = rhltable_lookup(&fprobe_ip_table, &ip, ++ fprobe_rht_params); ++ if (!head) ++ return false; ++ /* We only need to check fp is there. */ ++ rhl_for_each_entry_rcu(node, pos, head, hlist) { ++ if (node->addr != ip) ++ break; ++ fp = READ_ONCE(node->fp); ++ if (likely(fp)) ++ return true; ++ } ++ ++ return false; ++} ++ + #ifdef CONFIG_MODULES + static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt) + { +@@ -553,18 +592,25 @@ struct fprobe_addr_list { + static int fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node, + struct fprobe_addr_list *alist) + { ++ lockdep_assert_in_rcu_read_lock(); ++ + if (!within_module(node->addr, mod)) + return 0; + +- if (delete_fprobe_node(node)) +- return 0; ++ delete_fprobe_node(node); + /* If no address list is available, we can't track this address. */ + if (!alist->addrs) + return 0; ++ /* ++ * Don't care the type here, because all fprobes on the same ++ * address must be removed eventually. ++ */ ++ if (!rhltable_lookup(&fprobe_ip_table, &node->addr, fprobe_rht_params)) { ++ alist->addrs[alist->index++] = node->addr; ++ if (alist->index == alist->size) ++ return -ENOSPC; ++ } + +- alist->addrs[alist->index++] = node->addr; +- if (alist->index == alist->size) +- return -ENOSPC; + return 0; + } + +@@ -935,7 +981,9 @@ static int unregister_fprobe_nolock(stru + /* Remove non-synonim ips from table and hash */ + count = 0; + for (i = 0; i < hlist_array->size; i++) { +- if (!delete_fprobe_node(&hlist_array->array[i]) && addrs) ++ delete_fprobe_node(&hlist_array->array[i]); ++ if (addrs && !fprobe_exists_on_hash(hlist_array->array[i].addr, ++ fprobe_is_ftrace(fp))) + addrs[count++] = hlist_array->array[i].addr; + } + del_fprobe_hash(fp); diff --git a/queue-7.0/tracing-fprobe-remove-fprobe-from-hash-in-failure-path.patch b/queue-7.0/tracing-fprobe-remove-fprobe-from-hash-in-failure-path.patch new file mode 100644 index 0000000000..a1495d99e6 --- /dev/null +++ b/queue-7.0/tracing-fprobe-remove-fprobe-from-hash-in-failure-path.patch @@ -0,0 +1,183 @@ +From 845947aca6814f5723ed65e556eb5ee09493f05b Mon Sep 17 00:00:00 2001 +From: "Masami Hiramatsu (Google)" +Date: Mon, 20 Apr 2026 23:01:04 +0900 +Subject: tracing/fprobe: Remove fprobe from hash in failure path + +From: Masami Hiramatsu (Google) + +commit 845947aca6814f5723ed65e556eb5ee09493f05b upstream. + +When register_fprobe_ips() fails, it tries to remove a list of +fprobe_hash_node from fprobe_ip_table, but it missed to remove +fprobe itself from fprobe_table. Moreover, when removing +the fprobe_hash_node which is added to rhltable once, it must +use kfree_rcu() after removing from rhltable. + +To fix these issues, this reuses unregister_fprobe() internal +code to rollback the half-way registered fprobe. + +Link: https://lore.kernel.org/all/177669366417.132053.17874946321744910456.stgit@mhiramat.tok.corp.google.com/ + +Fixes: 4346ba160409 ("fprobe: Rewrite fprobe on function-graph tracer") +Cc: stable@vger.kernel.org +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/fprobe.c | 90 ++++++++++++++++++++++++++------------------------ + 1 file changed, 47 insertions(+), 43 deletions(-) + +--- a/kernel/trace/fprobe.c ++++ b/kernel/trace/fprobe.c +@@ -79,20 +79,27 @@ static const struct rhashtable_params fp + }; + + /* Node insertion and deletion requires the fprobe_mutex */ +-static int insert_fprobe_node(struct fprobe_hlist_node *node) ++static int insert_fprobe_node(struct fprobe_hlist_node *node, struct fprobe *fp) + { ++ int ret; ++ + lockdep_assert_held(&fprobe_mutex); + +- return rhltable_insert(&fprobe_ip_table, &node->hlist, fprobe_rht_params); ++ ret = rhltable_insert(&fprobe_ip_table, &node->hlist, fprobe_rht_params); ++ /* Set the fprobe pointer if insertion was successful. */ ++ if (!ret) ++ WRITE_ONCE(node->fp, fp); ++ return ret; + } + + /* Return true if there are synonims */ + static bool delete_fprobe_node(struct fprobe_hlist_node *node) + { +- lockdep_assert_held(&fprobe_mutex); + bool ret; + +- /* Avoid double deleting */ ++ lockdep_assert_held(&fprobe_mutex); ++ ++ /* Avoid double deleting and non-inserted nodes */ + if (READ_ONCE(node->fp) != NULL) { + WRITE_ONCE(node->fp, NULL); + rhltable_remove(&fprobe_ip_table, &node->hlist, +@@ -755,7 +762,6 @@ static int fprobe_init(struct fprobe *fp + fp->hlist_array = hlist_array; + hlist_array->fp = fp; + for (i = 0; i < num; i++) { +- hlist_array->array[i].fp = fp; + addr = ftrace_location(addrs[i]); + if (!addr) { + fprobe_fail_cleanup(fp); +@@ -819,6 +825,8 @@ int register_fprobe(struct fprobe *fp, c + } + EXPORT_SYMBOL_GPL(register_fprobe); + ++static int unregister_fprobe_nolock(struct fprobe *fp); ++ + /** + * register_fprobe_ips() - Register fprobe to ftrace by address. + * @fp: A fprobe data structure to be registered. +@@ -845,28 +853,25 @@ int register_fprobe_ips(struct fprobe *f + if (ret) + return ret; + +- hlist_array = fp->hlist_array; + if (fprobe_is_ftrace(fp)) + ret = fprobe_ftrace_add_ips(addrs, num); + else + ret = fprobe_graph_add_ips(addrs, num); +- +- if (!ret) { +- add_fprobe_hash(fp); +- for (i = 0; i < hlist_array->size; i++) { +- ret = insert_fprobe_node(&hlist_array->array[i]); +- if (ret) +- break; +- } +- /* fallback on insert error */ +- if (ret) { +- for (i--; i >= 0; i--) +- delete_fprobe_node(&hlist_array->array[i]); +- } ++ if (ret) { ++ fprobe_fail_cleanup(fp); ++ return ret; + } + +- if (ret) +- fprobe_fail_cleanup(fp); ++ hlist_array = fp->hlist_array; ++ ret = add_fprobe_hash(fp); ++ for (i = 0; i < hlist_array->size && !ret; i++) ++ ret = insert_fprobe_node(&hlist_array->array[i], fp); ++ ++ if (ret) { ++ unregister_fprobe_nolock(fp); ++ /* In error case, wait for clean up safely. */ ++ synchronize_rcu(); ++ } + + return ret; + } +@@ -910,27 +915,12 @@ bool fprobe_is_registered(struct fprobe + return true; + } + +-/** +- * unregister_fprobe() - Unregister fprobe. +- * @fp: A fprobe data structure to be unregistered. +- * +- * Unregister fprobe (and remove ftrace hooks from the function entries). +- * +- * Return 0 if @fp is unregistered successfully, -errno if not. +- */ +-int unregister_fprobe(struct fprobe *fp) ++static int unregister_fprobe_nolock(struct fprobe *fp) + { +- struct fprobe_hlist *hlist_array; ++ struct fprobe_hlist *hlist_array = fp->hlist_array; + unsigned long *addrs = NULL; +- int ret = 0, i, count; ++ int i, count; + +- mutex_lock(&fprobe_mutex); +- if (!fp || !fprobe_registered(fp)) { +- ret = -EINVAL; +- goto out; +- } +- +- hlist_array = fp->hlist_array; + addrs = kcalloc(hlist_array->size, sizeof(unsigned long), GFP_KERNEL); + if (!addrs) { + ret = -ENOMEM; /* TODO: Fallback to one-by-one loop */ +@@ -952,12 +942,26 @@ int unregister_fprobe(struct fprobe *fp) + + kfree_rcu(hlist_array, rcu); + fp->hlist_array = NULL; ++ kfree(addrs); + +-out: +- mutex_unlock(&fprobe_mutex); ++ return 0; ++} + +- kfree(addrs); +- return ret; ++/** ++ * unregister_fprobe() - Unregister fprobe. ++ * @fp: A fprobe data structure to be unregistered. ++ * ++ * Unregister fprobe (and remove ftrace hooks from the function entries). ++ * ++ * Return 0 if @fp is unregistered successfully, -errno if not. ++ */ ++int unregister_fprobe(struct fprobe *fp) ++{ ++ guard(mutex)(&fprobe_mutex); ++ if (!fp || !fprobe_registered(fp)) ++ return -EINVAL; ++ ++ return unregister_fprobe_nolock(fp); + } + EXPORT_SYMBOL_GPL(unregister_fprobe); + diff --git a/queue-7.0/tracing-fprobe-unregister-fprobe-even-if-memory-allocation-fails.patch b/queue-7.0/tracing-fprobe-unregister-fprobe-even-if-memory-allocation-fails.patch new file mode 100644 index 0000000000..a281b2838a --- /dev/null +++ b/queue-7.0/tracing-fprobe-unregister-fprobe-even-if-memory-allocation-fails.patch @@ -0,0 +1,82 @@ +From 1aec9e5c3e31ce1e28f914427fb7f90b91d310df Mon Sep 17 00:00:00 2001 +From: "Masami Hiramatsu (Google)" +Date: Mon, 20 Apr 2026 23:00:56 +0900 +Subject: tracing/fprobe: Unregister fprobe even if memory allocation fails + +From: Masami Hiramatsu (Google) + +commit 1aec9e5c3e31ce1e28f914427fb7f90b91d310df upstream. + +unregister_fprobe() can fail under memory pressure because of memory +allocation failure, but this maybe called from module unloading, and +usually there is no way to retry it. Moreover. trace_fprobe does not +check the return value. + +To fix this problem, unregister fprobe and fprobe_hash_node even if +working memory allocation fails. +Anyway, if the last fprobe is removed, the filter will be freed. + +Link: https://lore.kernel.org/all/177669365629.132053.8433032896213721288.stgit@mhiramat.tok.corp.google.com/ + +Fixes: 4346ba160409 ("fprobe: Rewrite fprobe on function-graph tracer") +Cc: stable@vger.kernel.org +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/fprobe.c | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +--- a/kernel/trace/fprobe.c ++++ b/kernel/trace/fprobe.c +@@ -331,9 +331,10 @@ static void fprobe_ftrace_remove_ips(uns + lockdep_assert_held(&fprobe_mutex); + + fprobe_ftrace_active--; +- if (!fprobe_ftrace_active) ++ if (!fprobe_ftrace_active) { + unregister_ftrace_function(&fprobe_ftrace_ops); +- if (num) ++ ftrace_free_filter(&fprobe_ftrace_ops); ++ } else if (num) + ftrace_set_filter_ips(&fprobe_ftrace_ops, addrs, num, 1, 0); + } + +@@ -532,10 +533,10 @@ static void fprobe_graph_remove_ips(unsi + + fprobe_graph_active--; + /* Q: should we unregister it ? */ +- if (!fprobe_graph_active) ++ if (!fprobe_graph_active) { + unregister_ftrace_graph(&fprobe_graph_ops); +- +- if (num) ++ ftrace_free_filter(&fprobe_graph_ops.ops); ++ } else if (num) + ftrace_set_filter_ips(&fprobe_graph_ops.ops, addrs, num, 1, 0); + } + +@@ -922,15 +923,19 @@ static int unregister_fprobe_nolock(stru + int i, count; + + addrs = kcalloc(hlist_array->size, sizeof(unsigned long), GFP_KERNEL); +- if (!addrs) { +- ret = -ENOMEM; /* TODO: Fallback to one-by-one loop */ +- goto out; +- } ++ /* ++ * This will remove fprobe_hash_node from the hash table even if ++ * memory allocation fails. However, ftrace_ops will not be updated. ++ * Anyway, when the last fprobe is unregistered, ftrace_ops is also ++ * unregistered. ++ */ ++ if (!addrs) ++ pr_warn("Failed to allocate working array. ftrace_ops may not sync.\n"); + + /* Remove non-synonim ips from table and hash */ + count = 0; + for (i = 0; i < hlist_array->size; i++) { +- if (!delete_fprobe_node(&hlist_array->array[i])) ++ if (!delete_fprobe_node(&hlist_array->array[i]) && addrs) + addrs[count++] = hlist_array->array[i].addr; + } + del_fprobe_hash(fp); diff --git a/queue-7.0/tracing-probes-limit-size-of-event-probe-to-3k.patch b/queue-7.0/tracing-probes-limit-size-of-event-probe-to-3k.patch new file mode 100644 index 0000000000..72cf4b4105 --- /dev/null +++ b/queue-7.0/tracing-probes-limit-size-of-event-probe-to-3k.patch @@ -0,0 +1,65 @@ +From b2aa3b4d64e460ac606f386c24e7d8a873ce6f1a Mon Sep 17 00:00:00 2001 +From: Steven Rostedt +Date: Tue, 28 Apr 2026 12:23:02 -0400 +Subject: tracing/probes: Limit size of event probe to 3K + +From: Steven Rostedt + +commit b2aa3b4d64e460ac606f386c24e7d8a873ce6f1a upstream. + +There currently isn't a max limit an event probe can be. One could make an +event greater than PAGE_SIZE, which makes the event useless because if +it's bigger than the max event that can be recorded into the ring buffer, +then it will never be recorded. + +A event probe should never need to be greater than 3K, so make that the +max size. As long as the max is less than the max that can be recorded +onto the ring buffer, it should be fine. + +Cc: stable@vger.kernel.org +Cc: Mathieu Desnoyers +Acked-by: Masami Hiramatsu (Google) +Fixes: 93ccae7a22274 ("tracing/kprobes: Support basic types on dynamic events") +Link: https://patch.msgid.link/20260428122302.706610ba@gandalf.local.home +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_probe.c | 6 ++++++ + kernel/trace/trace_probe.h | 4 +++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -1523,6 +1523,12 @@ static int traceprobe_parse_probe_arg_bo + parg->offset = *size; + *size += parg->type->size * (parg->count ?: 1); + ++ if (*size > MAX_PROBE_EVENT_SIZE) { ++ ret = -E2BIG; ++ trace_probe_log_err(ctx->offset, EVENT_TOO_BIG); ++ goto fail; ++ } ++ + if (parg->count) { + len = strlen(parg->type->fmttype) + 6; + parg->fmt = kmalloc(len, GFP_KERNEL); +--- a/kernel/trace/trace_probe.h ++++ b/kernel/trace/trace_probe.h +@@ -38,6 +38,7 @@ + #define MAX_BTF_ARGS_LEN 128 + #define MAX_DENTRY_ARGS_LEN 256 + #define MAX_STRING_SIZE PATH_MAX ++#define MAX_PROBE_EVENT_SIZE 3072 + + /* Reserved field names */ + #define FIELD_STRING_IP "__probe_ip" +@@ -561,7 +562,8 @@ extern int traceprobe_define_arg_fields( + C(BAD_TYPE4STR, "This type does not fit for string."),\ + C(NEED_STRING_TYPE, "$comm and immediate-string only accepts string type"),\ + C(TOO_MANY_ARGS, "Too many arguments are specified"), \ +- C(TOO_MANY_EARGS, "Too many entry arguments specified"), ++ C(TOO_MANY_EARGS, "Too many entry arguments specified"), \ ++ C(EVENT_TOO_BIG, "Event too big (too many fields?)"), + + #undef C + #define C(a, b) TP_ERR_##a diff --git a/queue-7.0/udf-reject-descriptors-with-oversized-crc-length.patch b/queue-7.0/udf-reject-descriptors-with-oversized-crc-length.patch new file mode 100644 index 0000000000..0339628f8a --- /dev/null +++ b/queue-7.0/udf-reject-descriptors-with-oversized-crc-length.patch @@ -0,0 +1,48 @@ +From 55d41b0a20128e86b9e960dd2e3f0a2d69a18df7 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Mon, 13 Apr 2026 17:12:40 -0400 +Subject: udf: reject descriptors with oversized CRC length + +From: Michael Bommarito + +commit 55d41b0a20128e86b9e960dd2e3f0a2d69a18df7 upstream. + +udf_read_tagged() skips CRC verification when descCRCLength + +sizeof(struct tag) exceeds the block size. A crafted UDF image can +set descCRCLength to an oversized value to bypass CRC validation +entirely; the descriptor is then accepted based solely on the 8-bit +tag checksum, which is trivially recomputable. + +Reject such descriptors instead of silently accepting them. A +legitimate single-block descriptor should never have a CRC length that +exceeds the block. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-6 +Assisted-by: Codex:gpt-5-4 +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/20260413211240.853662-1-michael.bommarito@gmail.com +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/misc.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/udf/misc.c ++++ b/fs/udf/misc.c +@@ -230,8 +230,12 @@ struct buffer_head *udf_read_tagged(stru + } + + /* Verify the descriptor CRC */ +- if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize || +- le16_to_cpu(tag_p->descCRC) == crc_itu_t(0, ++ if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize) { ++ udf_err(sb, "block %u: CRC length %u exceeds block size\n", ++ block, le16_to_cpu(tag_p->descCRCLength)); ++ goto error_out; ++ } ++ if (le16_to_cpu(tag_p->descCRC) == crc_itu_t(0, + bh->b_data + sizeof(struct tag), + le16_to_cpu(tag_p->descCRCLength))) + return bh; diff --git a/queue-7.0/x86-boot-e820-re-enable-bios-fallback-if-e820-table-is-empty.patch b/queue-7.0/x86-boot-e820-re-enable-bios-fallback-if-e820-table-is-empty.patch new file mode 100644 index 0000000000..ecf6ef28f7 --- /dev/null +++ b/queue-7.0/x86-boot-e820-re-enable-bios-fallback-if-e820-table-is-empty.patch @@ -0,0 +1,76 @@ +From 5772f6535227ebd104065d80afa8ed3478d34c5c Mon Sep 17 00:00:00 2001 +From: David Gow +Date: Thu, 16 Apr 2026 14:57:43 +0800 +Subject: x86/boot/e820: Re-enable BIOS fallback if e820 table is empty + +From: David Gow + +commit 5772f6535227ebd104065d80afa8ed3478d34c5c upstream. + +In commit: + + 157266edcc56 ("x86/boot/e820: Simplify append_e820_table() and remove restriction on single-entry tables") + +the check on the number of entries in the e820 table was removed. The intention +was to support single-entry maps, but by removing the check entirely, we also +skip the fallback (to, e.g., the BIOS 88h function). + +This means that if no E820 map is passed in from the bootloader (which is the +case on some bootloaders, like linld), we end up with an empty memory map, and +the kernel fails to boot (either by deadlocking on OOM, or by failing to +allocate the real mode trampoline, or similar). + +Re-instate the check in append_e820_table(), but only check that nr_entries is +non-zero. This allows e820__memory_setup_default() to fall back to other memory +size sources, and doesn't affect e820__memory_setup_extended(), as the latter +ignores the return value from append_e820_table(). + +In doing so, we also update the return values to be proper error codes, with +-ENOENT for this case (there are no entries), and -EINVAL for the case where an +entry appears invalid. Given none of the callers check the actual value -- just +whether it's nonzero -- this is largely aesthetic in practice. + +Tested against linld, and the kernel boots again fine. + +[ mingo: Readability edits to the comment and the changelog. ] + +Fixes: 157266edcc56 ("x86/boot/e820: Simplify append_e820_table() and remove restriction on single-entry tables") +Signed-off-by: David Gow +Signed-off-by: Ingo Molnar +Reviewed-by: Andy Shevchenko +Cc: stable@vger.kernel.org +Cc: Arnd Bergmann +Cc: "H. Peter Anvin" +Link: https://patch.msgid.link/20260416065746.1896647-1-david@davidgow.net +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/e820.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c +index 2a9992758933..eb72537bc0b1 100644 +--- a/arch/x86/kernel/e820.c ++++ b/arch/x86/kernel/e820.c +@@ -450,6 +450,10 @@ __init static int append_e820_table(struct boot_e820_entry *entries, u32 nr_entr + { + struct boot_e820_entry *entry = entries; + ++ /* If there aren't any entries, we'll want to fall back to another source: */ ++ if (!nr_entries) ++ return -ENOENT; ++ + while (nr_entries) { + u64 start = entry->addr; + u64 size = entry->size; +@@ -458,7 +462,7 @@ __init static int append_e820_table(struct boot_e820_entry *entries, u32 nr_entr + + /* Ignore the remaining entries on 64-bit overflow: */ + if (start > end && likely(size)) +- return -1; ++ return -EINVAL; + + e820__range_add(start, size, type); + +-- +2.54.0 + diff --git a/queue-7.0/x86-efi-fix-graceful-fault-handling-after-fpu-softirq-changes.patch b/queue-7.0/x86-efi-fix-graceful-fault-handling-after-fpu-softirq-changes.patch new file mode 100644 index 0000000000..6209681fd6 --- /dev/null +++ b/queue-7.0/x86-efi-fix-graceful-fault-handling-after-fpu-softirq-changes.patch @@ -0,0 +1,56 @@ +From 088f65e206087bf903743bd18417261d7a4c9644 Mon Sep 17 00:00:00 2001 +From: Ivan Hu +Date: Thu, 30 Apr 2026 15:41:07 +0800 +Subject: x86/efi: Fix graceful fault handling after FPU softirq changes + +From: Ivan Hu + +commit 088f65e206087bf903743bd18417261d7a4c9644 upstream. + +Since commit d02198550423 ("x86/fpu: Improve crypto performance by +making kernel-mode FPU reliably usable in softirqs"), kernel_fpu_begin() +calls fpregs_lock() which uses local_bh_disable() instead of the +previous preempt_disable(). This sets SOFTIRQ_OFFSET in preempt_count +during the entire EFI runtime service call, causing in_interrupt() to +return true in normal task context. + +The graceful page fault handler efi_crash_gracefully_on_page_fault() +uses in_interrupt() to bail out for faults in real interrupt context. +With SOFTIRQ_OFFSET now set, the handler always bails out, leaving EFI +firmware page faults unhandled. This escalates to die() which also sees +in_interrupt() as true and calls panic("Fatal exception in interrupt"), +resulting in a hard system freeze. On systems with buggy firmware that +triggers page faults during EFI runtime calls (e.g., accessing unmapped +memory in GetTime()), this causes an unrecoverable hang instead of the +expected graceful EFI_ABORTED recovery. + +Fix by replacing in_interrupt() with !in_task(). This preserves the +original intent of bailing for interrupts or NMI faults, while no longer +falsely triggering from the FPU code path's local_bh_disable(). + +Fixes: d02198550423 ("x86/fpu: Improve crypto performance by making kernel-mode FPU reliably usable in softirqs") +Cc: +Signed-off-by: Ivan Hu +[ardb: Sashiko spotted that using 'in_hardirq() || in_nmi()' leaves a + window where a softirq may be taken before fpregs_lock() is + called, but after efi_rts_work.efi_rts_id has been assigned, + and any page faults occurring in that window will then be + misidentified as having been caused by the firmware. Instead, + use !in_task(), which incorporates in_serving_softirq(). ] +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/platform/efi/quirks.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/platform/efi/quirks.c ++++ b/arch/x86/platform/efi/quirks.c +@@ -771,7 +771,7 @@ void efi_crash_gracefully_on_page_fault( + * If we get an interrupt/NMI while processing an EFI runtime service + * then this is a regular OOPS, not an EFI failure. + */ +- if (in_interrupt()) ++ if (!in_task()) + return; + + /*