From: Greg Kroah-Hartman Date: Wed, 5 Aug 2026 11:48:08 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;h=06c0f32e6ef09dfb292deeafef2bd818ede1bd87;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: cifs-add-fscache_resize_cookie-to-cifs_setsize.patch cpufreq-powernow-k8-fix-possible-memory-leak-in-powernowk8_cpu_init.patch cpufreq-schedutil-publish-util-hooks-only-after-all-sg_cpu-are-initialized.patch gpio-pca953x-fix-cache_only-and-irq-state-on-restore_context-failure.patch gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch hwmon-npcm750-pwm-fan-stop-fan-timer-on-device-detach.patch hwmon-pmbus-core-notify-on-the-hwmon-device-not-the-i2c-client.patch i2c-amd-mp2-unregister-callback-on-adapter-add-failure.patch i2c-imx-cancel-hrtimer-before-clearing-slave-pointer.patch i2c-imx-fix-slave-registration-race-and-error-handling.patch i2c-imx-mark-i2c-adapter-when-hardware-is-powered-down.patch i2c-iproc-reset-bus-after-timeout-if-start_busy-is-stuck.patch i2c-jz4780-cache-host-clock-rate-at-probe-to-prevent-ccf-prepare_lock-deadlock.patch i2c-qcom-cci-drop-custom-suspend-resume-and-rely-on-runtime-pm-helpers.patch i2c-spacemit-request-irq-after-controller-initialization.patch ice-fix-memory-leak-in-ice_lbtest_prepare_rings.patch ice-fix-vf-interrupts-cleanup.patch ice-wait-for-reset-completion-in-ice_resume.patch io_uring-net-initialize-mshot_len-for-send.patch mm-memcg-initialize-locked-in-memcg1_oom_prepare-stub.patch mm-page_reporting-use-system_freezable_wq-to-fix-uaf-during-suspend.patch net-bridge-stop-fast-leave-after-deleting-a-port-group.patch net-ipv6-clear-suppressed-fib6-rule-result.patch net-openvswitch-fix-potential-uaf-on-meter-attach-failure.patch net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-ct.patch net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-recirculation.patch net-pktgen-fix-proc-entry-use-after-free.patch phy-zynqmp-fix-l0_tm_disable_scramble_encoder-mask.patch phy-zynqmp-keep-serdes-scrambler-and-8b-10b-enabled-for-usb.patch phy-zynqmp-use-read-modify-write-for-serdes-scrambler-bypass.patch power-supply-bq25890-fix-the-10-c-ntc-lookup-entry.patch power-supply-max17040-handle-missing-status-supplier.patch powerpc-ps3-fix-map-failure-path-in-dma_ioc0_map_pages.patch s390-dasd-fix-potential-null-pointer-dereference.patch s390-dasd-fix-undersized-format-check-buffer.patch s390-pci-fix-s390_pci_mmio_write-syscall-error-return-without-mio.patch s390-qeth-check-cap_net_admin-for-private-ioctls.patch s390-zcrypt-fix-buffer-over-read-in-cca_cipher2protkey.patch s390-zcrypt-fix-missing-mem-scrub-at-clear-key-import-in-cca_clr2cipherkey.patch s390-zcrypt-fix-wrong-domain-value-verification-with-ep11-cprbs.patch s390-zcrypt-validate-length-for-cca-aes-cipher-key-requests.patch s390-zcrypt-validate-length-for-cca-ecc-private-key-requests.patch scsi-scsi_debug-fix-report-zones-alloc_len-underflow-oob-write.patch sctp-prevent-peer-transport-count-overflow.patch sctp-reject-stale-cookies-with-mismatched-verification-tags.patch selftests-clone3-fix-wild-pointer-access-of-getline-due-to-missing-init.patch selftests-mm-fix-potential-wild-pointer-access-of-getline-due-to-missing-init.patch spi-qcom-qspi-correct-max-dma-length-to-avoid-64k-boundary-failure.patch spi-spi-qpic-snand-write-the-feature-value-before-executing-set_feature.patch tracing-check-return-value-of-__register_event-in-trace_module_add_events.patch tracing-filters-fix-false-positive-match-in-regex_match_full.patch ublk-reset-kernel-owned-dev_info-fields-in-ublk_ctrl_add_dev.patch um-vector-fix-use-after-free-in-vector_mmsg_rx.patch uprobes-fix-null-pointer-dereference-in-hprobe_expire.patch veth-convert-frag_list-skbs-before-running-xdp.patch vxlan-re-fetch-eth-header-after-route_shortcircuit.patch vxlan-unclone-skb-head-before-modifying-eth-header-in-route_shortcircuit.patch vxlan-use-neigh_ha_snapshot-in-route_shortcircuit.patch vxlan-use-pskb_network_may_pull-for-transmit-path-header-pulls.patch vxlan-use-pskb_network_may_pull-in-route_shortcircuit.patch --- diff --git a/queue-6.18/cifs-add-fscache_resize_cookie-to-cifs_setsize.patch b/queue-6.18/cifs-add-fscache_resize_cookie-to-cifs_setsize.patch new file mode 100644 index 0000000000..0f38ea0ee9 --- /dev/null +++ b/queue-6.18/cifs-add-fscache_resize_cookie-to-cifs_setsize.patch @@ -0,0 +1,50 @@ +From fa724e235cfdb0fb0bb427d0f9dfe864ae27403e Mon Sep 17 00:00:00 2001 +From: Frank Sorenson +Date: Sat, 25 Jul 2026 21:04:44 +0000 +Subject: cifs: add fscache_resize_cookie() to cifs_setsize() + +From: Frank Sorenson + +commit fa724e235cfdb0fb0bb427d0f9dfe864ae27403e upstream. + +Several code paths update the VFS inode size by calling +netfs_resize_file() and cifs_setsize(), but omit the corresponding +fscache_resize_cookie() call, leaving the fscache cookie out of sync +with the actual file size: + + - cifs_file_set_size() in inode.c: server-side truncation via setattr + - cifs_do_truncate() in file.c: truncates to zero on O_TRUNC open + - smb2_duplicate_extents() in smb2ops.c: file clone extending EOF + - smb3_simple_falloc() in smb2ops.c: two branches that extend EOF + via write-range and SMB2_set_eof respectively + +Since every caller of cifs_setsize() must resize the fscache cookie, +add the call to cifs_setsize() itself, consistent with how +truncate_pagecache() is already consolidated there. + +Fixes: 70431bfd825d ("cifs: Support fscache indexing rewrite") +Fixes: 93a43155127f ("cifs: Fix missing set of remote_i_size") +Fixes: 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC") +Fixes: 7a06d3b816d7 ("smb/client: emulate small EOF-extending mode 0 fallocate ranges") +Cc: stable@vger.kernel.org +Cc: David Howells +Cc: Paulo Alcantara +Cc: Huiwen He +Signed-off-by: Frank Sorenson +Reviewed-by: Paulo Alcantara +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/inode.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/smb/client/inode.c ++++ b/fs/smb/client/inode.c +@@ -3039,6 +3039,7 @@ void cifs_setsize(struct inode *inode, l + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + truncate_pagecache(inode, offset); + netfs_wait_for_outstanding_io(inode); ++ fscache_resize_cookie(cifs_inode_cookie(inode), offset); + } + + int cifs_file_set_size(const unsigned int xid, struct dentry *dentry, diff --git a/queue-6.18/cpufreq-powernow-k8-fix-possible-memory-leak-in-powernowk8_cpu_init.patch b/queue-6.18/cpufreq-powernow-k8-fix-possible-memory-leak-in-powernowk8_cpu_init.patch new file mode 100644 index 0000000000..e2f2c33cb5 --- /dev/null +++ b/queue-6.18/cpufreq-powernow-k8-fix-possible-memory-leak-in-powernowk8_cpu_init.patch @@ -0,0 +1,35 @@ +From d5f8e5f6040d052d44fcbf4f31dd35145c0c8d7d Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Mon, 27 Jul 2026 15:05:51 +0530 +Subject: cpufreq: powernow-k8: Fix possible memory leak in powernowk8_cpu_init() + +From: Abdun Nihaal + +commit d5f8e5f6040d052d44fcbf4f31dd35145c0c8d7d upstream. + +The memory allocated for data->powernow_table inside +powernow_k8_cpu_init_acpi() or find_psb_table() is not freed in one of +the error paths in powernowk8_cpu_init(). Fix that by adding a kfree(). + +Fixes: 1ff6e97f1d99 ("[CPUFREQ] cpumask: avoid playing with cpus_allowed in powernow-k8.c") +Cc: stable@vger.kernel.org +Signed-off-by: Abdun Nihaal +Acked-by: Viresh Kumar +Reviewed-by: Zhongqiu Han +Link: https://patch.msgid.link/20260727093553.98246-1-nihaal@cse.iitm.ac.in +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + drivers/cpufreq/powernow-k8.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/cpufreq/powernow-k8.c ++++ b/drivers/cpufreq/powernow-k8.c +@@ -1083,6 +1083,7 @@ static int powernowk8_cpu_init(struct cp + + err_out_exit_acpi: + powernow_k8_cpu_exit_acpi(data); ++ kfree(data->powernow_table); + + err_out: + kfree(data); diff --git a/queue-6.18/cpufreq-schedutil-publish-util-hooks-only-after-all-sg_cpu-are-initialized.patch b/queue-6.18/cpufreq-schedutil-publish-util-hooks-only-after-all-sg_cpu-are-initialized.patch new file mode 100644 index 0000000000..27cce4d502 --- /dev/null +++ b/queue-6.18/cpufreq-schedutil-publish-util-hooks-only-after-all-sg_cpu-are-initialized.patch @@ -0,0 +1,68 @@ +From f0a3f042293a8c5a2152346b3637ea60866c503a Mon Sep 17 00:00:00 2001 +From: Zhongqiu Han +Date: Thu, 16 Jul 2026 19:51:58 +0800 +Subject: cpufreq: schedutil: Publish util hooks only after all sg_cpu are initialized + +From: Zhongqiu Han + +commit f0a3f042293a8c5a2152346b3637ea60866c503a upstream. + +Commit 16a03c71bba0 ("cpufreq: schedutil: Merge initialization code of +sg_cpu in single loop") merged the per-CPU initialization and the +utilization-hook registration into a single loop in sugov_start(). + +For a shared cpufreq policy this re-introduces the race originally fixed +by commit ab2f7cf141aa ("cpufreq: schedutil: Fix sugov_start() versus +sugov_update_shared() race"). + +The scheduler's util path reaches the hook under RCU-sched and never takes +policy->rwsem, so the rwsem held across sugov_start() cannot serialize the +two. Once the first CPU's hook is published, sugov_update_shared() may run +and, via sugov_next_freq_shared(), read/write each sibling sugov_cpu +(iowait_boost, util, bw_min, ...) concurrently with the memset() still +initializing them, with no lock common to both sides: the update side holds +sg_policy->update_lock while the init side holds only policy->rwsem, which +the scheduler's util path never takes. + +The walk only accesses scalar members, never a pointer like ->sg_policy, +so it does not crash today; it merely uses stale (or zero on first start) +values that skew the frequency selection and tracepoints. It is still a +genuine data race, and a latent crash once any pointer member is +dereferenced there. + +Restore the two-phase approach: initialize all per-CPU structures first, +and only then publish the per-CPU utilization update hooks. + +Fixes: 16a03c71bba0 ("cpufreq: schedutil: Merge initialization code of sg_cpu in single loop") +Cc: stable@vger.kernel.org +Signed-off-by: Zhongqiu Han +Reviewed-by: Christian Loehle +Link: https://patch.msgid.link/20260716115159.848403-1-zhongqiu.han@oss.qualcomm.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sched/cpufreq_schedutil.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/kernel/sched/cpufreq_schedutil.c ++++ b/kernel/sched/cpufreq_schedutil.c +@@ -870,8 +870,19 @@ static int sugov_start(struct cpufreq_po + memset(sg_cpu, 0, sizeof(*sg_cpu)); + sg_cpu->cpu = cpu; + sg_cpu->sg_policy = sg_policy; ++ } ++ ++ /* ++ * Publish the hooks only after all per-CPU data is initialized, so a ++ * shared policy's sugov_update_shared() never reads an uninitialized ++ * sibling sugov_cpu. ++ */ ++ for_each_cpu(cpu, policy->cpus) { ++ struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); ++ + cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, uu); + } ++ + return 0; + } + diff --git a/queue-6.18/gpio-pca953x-fix-cache_only-and-irq-state-on-restore_context-failure.patch b/queue-6.18/gpio-pca953x-fix-cache_only-and-irq-state-on-restore_context-failure.patch new file mode 100644 index 0000000000..c51b0483b1 --- /dev/null +++ b/queue-6.18/gpio-pca953x-fix-cache_only-and-irq-state-on-restore_context-failure.patch @@ -0,0 +1,51 @@ +From d233087c19f6607ef926ac3f47d776e2406ffd1f Mon Sep 17 00:00:00 2001 +From: bui duc phuc +Date: Mon, 27 Jul 2026 15:02:05 +0700 +Subject: gpio: pca953x: fix cache_only and IRQ state on restore_context() failure + +From: bui duc phuc + +commit d233087c19f6607ef926ac3f47d776e2406ffd1f upstream. + +When pca953x_restore_context() fails, cache_only is left disabled and +the IRQ left enabled, even though register synchronization may not have +completed successfully. Restore cache_only and disable the IRQ again on +failure, matching the state set by pca953x_save_context(). + +Fixes: ec5bde62019b ("gpio: pca953x: Split pca953x_restore_context() and pca953x_save_context()") +Fixes: 3e38f946062b ("gpio: pca953x: fix IRQ storm on system wake up") +Cc: stable@vger.kernel.org +Reviewed-by: Linus Walleij +Signed-off-by: bui duc phuc +Link: https://patch.msgid.link/20260727080205.16353-1-phucduc.bui@gmail.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpio/gpio-pca953x.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -1370,9 +1370,20 @@ static int pca953x_restore_context(struc + regcache_mark_dirty(chip->regmap); + ret = pca953x_regcache_sync(chip); + if (ret) +- return ret; ++ goto err; + +- return regcache_sync(chip->regmap); ++ ret = regcache_sync(chip->regmap); ++ if (ret) ++ goto err; ++ ++ return 0; ++ ++err: ++ if (chip->client->irq > 0) ++ disable_irq(chip->client->irq); ++ regcache_cache_only(chip->regmap, true); ++ ++ return ret; + } + + static void pca953x_save_context(struct pca953x_chip *chip) diff --git a/queue-6.18/gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch b/queue-6.18/gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch new file mode 100644 index 0000000000..0a58cc9dbf --- /dev/null +++ b/queue-6.18/gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch @@ -0,0 +1,173 @@ +From a02b8950d619123da64f69b70fe1dadef217dfe4 Mon Sep 17 00:00:00 2001 +From: Junjie Cao +Date: Thu, 23 Jul 2026 09:41:29 +0800 +Subject: gpio: pch: use raw_spinlock_t for the register lock + +From: Junjie Cao + +commit a02b8950d619123da64f69b70fe1dadef217dfe4 upstream. + +pch_irq_type() is registered as the irq_chip .irq_set_type callback and +takes chip->spinlock with spin_lock_irqsave(). This callback is reached +from __setup_irq() -> __irq_set_trigger() -> chip->irq_set_type() while +the caller holds desc->lock, a raw_spinlock_t, with hardirqs disabled. +That context is not sleepable, but on PREEMPT_RT a regular spinlock_t is +an rtmutex-backed sleeping lock, so acquiring it there is invalid. + +This was confirmed on a PREEMPT_RT kernel with lockdep +(PROVE_RAW_LOCK_NESTING and DEBUG_ATOMIC_SLEEP). A grounded PoC mirrored +pch_irq_type()'s locking and drove it through the real genirq carrier +irq_set_irq_type() -> __irq_set_trigger() -> chip->irq_set_type(), i.e. +the same __irq_set_trigger() edge that __setup_irq() takes for a +requested IRQ. With the original spin_lock_irqsave() edge lockdep +reported an invalid wait context, immediately followed by: + + BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48 + in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 95, name: insmod + hardirqs last disabled at (3784): _raw_spin_lock_irqsave+0x4f/0x60 + rt_spin_lock+0x3a/0x1c0 + repro_irq_set_type+0x64/0xa0 [pch_repro] + __irq_set_trigger+0x69/0x140 + irq_set_irq_type+0x78/0xd0 + +Switching the mirrored lock to raw_spinlock_t made both splats go away. + +Convert the register lock to raw_spinlock_t. The same lock also +serializes the GPIO direction/value callbacks and the suspend/resume +register save/restore, but all of those critical sections only perform +MMIO register accesses (ioread32()/iowrite32()) and +irq_set_handler_locked(); none of them contain sleepable operations. +Keeping this register lock non-sleeping is therefore appropriate for the +irqchip callbacks and does not change the GPIO-side locking contract. + +This is the same class of issue and fix as recently addressed for other +GPIO controllers, e.g. commit 286533cb14a3 ("gpio: sch: use raw_spinlock_t +in the irq startup path") and commit 90f0109019e6 ("gpio: eic-sprd: use +raw_spinlock_t in the irq startup path"). + +Fixes: 38eb18a6f92d ("gpio-pch: Support interrupt function") +Cc: stable@vger.kernel.org +Signed-off-by: Junjie Cao +Reviewed-by: Linus Walleij +Link: https://patch.msgid.link/20260723014129.1129730-1-junjie.cao@intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpio/gpio-pch.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +--- a/drivers/gpio/gpio-pch.c ++++ b/drivers/gpio/gpio-pch.c +@@ -96,7 +96,7 @@ struct pch_gpio { + struct pch_gpio_reg_data pch_gpio_reg; + int irq_base; + enum pch_type_t ioh; +- spinlock_t spinlock; ++ raw_spinlock_t spinlock; + }; + + static int pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val) +@@ -105,7 +105,7 @@ static int pch_gpio_set(struct gpio_chip + struct pch_gpio *chip = gpiochip_get_data(gpio); + unsigned long flags; + +- spin_lock_irqsave(&chip->spinlock, flags); ++ raw_spin_lock_irqsave(&chip->spinlock, flags); + reg_val = ioread32(&chip->reg->po); + if (val) + reg_val |= BIT(nr); +@@ -113,7 +113,7 @@ static int pch_gpio_set(struct gpio_chip + reg_val &= ~BIT(nr); + + iowrite32(reg_val, &chip->reg->po); +- spin_unlock_irqrestore(&chip->spinlock, flags); ++ raw_spin_unlock_irqrestore(&chip->spinlock, flags); + + return 0; + } +@@ -133,7 +133,7 @@ static int pch_gpio_direction_output(str + u32 reg_val; + unsigned long flags; + +- spin_lock_irqsave(&chip->spinlock, flags); ++ raw_spin_lock_irqsave(&chip->spinlock, flags); + + reg_val = ioread32(&chip->reg->po); + if (val) +@@ -147,7 +147,7 @@ static int pch_gpio_direction_output(str + pm |= BIT(nr); + iowrite32(pm, &chip->reg->pm); + +- spin_unlock_irqrestore(&chip->spinlock, flags); ++ raw_spin_unlock_irqrestore(&chip->spinlock, flags); + + return 0; + } +@@ -158,12 +158,12 @@ static int pch_gpio_direction_input(stru + u32 pm; + unsigned long flags; + +- spin_lock_irqsave(&chip->spinlock, flags); ++ raw_spin_lock_irqsave(&chip->spinlock, flags); + pm = ioread32(&chip->reg->pm); + pm &= BIT(gpio_pins[chip->ioh]) - 1; + pm &= ~BIT(nr); + iowrite32(pm, &chip->reg->pm); +- spin_unlock_irqrestore(&chip->spinlock, flags); ++ raw_spin_unlock_irqrestore(&chip->spinlock, flags); + + return 0; + } +@@ -265,7 +265,7 @@ static int pch_irq_type(struct irq_data + return 0; + } + +- spin_lock_irqsave(&chip->spinlock, flags); ++ raw_spin_lock_irqsave(&chip->spinlock, flags); + + /* Set interrupt mode */ + im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4)); +@@ -277,7 +277,7 @@ static int pch_irq_type(struct irq_data + else if (type & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(d, handle_edge_irq); + +- spin_unlock_irqrestore(&chip->spinlock, flags); ++ raw_spin_unlock_irqrestore(&chip->spinlock, flags); + return 0; + } + +@@ -374,7 +374,7 @@ static int pch_gpio_probe(struct pci_dev + chip->ioh = id->driver_data; + chip->reg = chip->base; + pci_set_drvdata(pdev, chip); +- spin_lock_init(&chip->spinlock); ++ raw_spin_lock_init(&chip->spinlock); + pch_gpio_setup(chip); + + ret = devm_gpiochip_add_data(dev, &chip->gpio, chip); +@@ -407,9 +407,9 @@ static int __maybe_unused pch_gpio_suspe + struct pch_gpio *chip = dev_get_drvdata(dev); + unsigned long flags; + +- spin_lock_irqsave(&chip->spinlock, flags); ++ raw_spin_lock_irqsave(&chip->spinlock, flags); + pch_gpio_save_reg_conf(chip); +- spin_unlock_irqrestore(&chip->spinlock, flags); ++ raw_spin_unlock_irqrestore(&chip->spinlock, flags); + + return 0; + } +@@ -419,11 +419,11 @@ static int __maybe_unused pch_gpio_resum + struct pch_gpio *chip = dev_get_drvdata(dev); + unsigned long flags; + +- spin_lock_irqsave(&chip->spinlock, flags); ++ raw_spin_lock_irqsave(&chip->spinlock, flags); + iowrite32(0x01, &chip->reg->reset); + iowrite32(0x00, &chip->reg->reset); + pch_gpio_restore_reg_conf(chip); +- spin_unlock_irqrestore(&chip->spinlock, flags); ++ raw_spin_unlock_irqrestore(&chip->spinlock, flags); + + return 0; + } diff --git a/queue-6.18/hwmon-npcm750-pwm-fan-stop-fan-timer-on-device-detach.patch b/queue-6.18/hwmon-npcm750-pwm-fan-stop-fan-timer-on-device-detach.patch new file mode 100644 index 0000000000..c6f1491564 --- /dev/null +++ b/queue-6.18/hwmon-npcm750-pwm-fan-stop-fan-timer-on-device-detach.patch @@ -0,0 +1,57 @@ +From f27f6976ea269219c1259a7c2f8c6dfe782540a3 Mon Sep 17 00:00:00 2001 +From: Hongyan Xu +Date: Wed, 29 Jul 2026 18:01:16 +0800 +Subject: hwmon: (npcm750-pwm-fan): stop fan timer on device detach + +From: Hongyan Xu + +commit f27f6976ea269219c1259a7c2f8c6dfe782540a3 upstream. + +When a fan tach channel is present, npcm7xx_pwm_fan_probe() starts +fan_timer. The timer callback polls tach state and rearms the timer, but +the driver has no remove callback or devm cleanup action to stop it. On +device detach, the devm-managed driver data and I/O mappings can be +released while the timer is still pending or running. + +Register a devm cleanup action before starting the timer and shut the +timer down synchronously from that action. + +This issue was found by a static analysis tool. + +Fixes: f1fd4a4db777 ("hwmon: Add NPCM7xx PWM and Fan driver") +Cc: stable@vger.kernel.org +Signed-off-by: Hongyan Xu +Link: https://lore.kernel.org/r/20260729100116.790-1-getshell@seu.edu.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/npcm750-pwm-fan.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/hwmon/npcm750-pwm-fan.c ++++ b/drivers/hwmon/npcm750-pwm-fan.c +@@ -364,6 +364,11 @@ static void npcm7xx_fan_polling(struct t + add_timer(&data->fan_timer); + } + ++static void npcm7xx_fan_cleanup(void *timer) ++{ ++ timer_shutdown_sync(timer); ++} ++ + static inline void npcm7xx_fan_compute(struct npcm7xx_pwm_fan_data *data, + u8 fan, u8 cmp, u8 fan_id, u8 flag_int, + u8 flag_mode, u8 flag_clear) +@@ -1027,6 +1032,12 @@ static int npcm7xx_pwm_fan_probe(struct + msecs_to_jiffies(NPCM7XX_FAN_POLL_TIMER_200MS); + timer_setup(&data->fan_timer, + npcm7xx_fan_polling, 0); ++ ret = devm_add_action_or_reset(dev, ++ npcm7xx_fan_cleanup, ++ &data->fan_timer); ++ if (ret) ++ return ret; ++ + add_timer(&data->fan_timer); + break; + } diff --git a/queue-6.18/hwmon-pmbus-core-notify-on-the-hwmon-device-not-the-i2c-client.patch b/queue-6.18/hwmon-pmbus-core-notify-on-the-hwmon-device-not-the-i2c-client.patch new file mode 100644 index 0000000000..c2f8dbada8 --- /dev/null +++ b/queue-6.18/hwmon-pmbus-core-notify-on-the-hwmon-device-not-the-i2c-client.patch @@ -0,0 +1,43 @@ +From a64a7e8a0b012ba81b0eadbd7afc84ab0dbfd70c Mon Sep 17 00:00:00 2001 +From: Vincent Jardin +Date: Thu, 23 Jul 2026 17:44:56 +0200 +Subject: hwmon: (pmbus/core) notify on the hwmon device, not the i2c client + +From: Vincent Jardin + +commit a64a7e8a0b012ba81b0eadbd7afc84ab0dbfd70c upstream. + +pmbus_notify() calls sysfs_notify() and kobject_uevent() on the i2c +client's kobject, but the alarm attributes live on the hwmon class +device registered by pmbus_do_probe(). Notifying the parent i2c device +is a no-op for both poll(POLLPRI) waiters and udev listeners: the named +attribute does not exist on that kobject. + +Notify the hwmon device instead, so poll() wakes up and "change" +uevents fire on the inX_alarm/tempX_alarm attributes when SMBALERT# +reports a fault. + +Fixes: f469bde9afd1 ("hwmon: (pmbus/core) Notify hwmon events") +Cc: stable@vger.kernel.org # v6.4+ +Signed-off-by: Vincent Jardin +Link: https://lore.kernel.org/r/20260723-fix_hwmon_notify_v1-v1-1-5a24c528686d@free.fr +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/pmbus/pmbus_core.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/pmbus/pmbus_core.c ++++ b/drivers/hwmon/pmbus/pmbus_core.c +@@ -2977,8 +2977,9 @@ static void pmbus_notify(struct pmbus_da + + if (reg == sreg && page == spage && (smask & flags)) { + dev_dbg(data->dev, "sysfs notify: %s", da->attr.name); +- sysfs_notify(&data->dev->kobj, NULL, da->attr.name); +- kobject_uevent(&data->dev->kobj, KOBJ_CHANGE); ++ sysfs_notify(&data->hwmon_dev->kobj, NULL, ++ da->attr.name); ++ kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE); + flags &= ~smask; + } + diff --git a/queue-6.18/i2c-amd-mp2-unregister-callback-on-adapter-add-failure.patch b/queue-6.18/i2c-amd-mp2-unregister-callback-on-adapter-add-failure.patch new file mode 100644 index 0000000000..af71d42bda --- /dev/null +++ b/queue-6.18/i2c-amd-mp2-unregister-callback-on-adapter-add-failure.patch @@ -0,0 +1,43 @@ +From 82048795242f04275a3f49ffc66ad851b6120954 Mon Sep 17 00:00:00 2001 +From: Myeonghun Pak +Date: Tue, 21 Jul 2026 23:41:47 +0900 +Subject: i2c: amd-mp2: Unregister callback on adapter add failure + +From: Myeonghun Pak + +commit 82048795242f04275a3f49ffc66ad851b6120954 upstream. + +amd_mp2_register_cb() stores the platform I2C context in the MP2 PCI +driver's callback table before the adapter is registered. If +i2c_add_adapter() fails, probe returns and devres frees the context, +but the PCI driver can still dereference the stale pointer from its IRQ +and system-sleep callbacks. + +Unregister the callback before returning the adapter registration error. + +Fixes: 529766e0a011 ("i2c: Add drivers for the AMD PCIe MP2 I2C controller") +Co-developed-by: Ijae Kim +Signed-off-by: Ijae Kim +Signed-off-by: Myeonghun Pak +Cc: # v5.2+ +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260721144147.31150-1-mhun512@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-amd-mp2-plat.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-amd-mp2-plat.c ++++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c +@@ -316,8 +316,10 @@ static int i2c_amd_probe(struct platform + + amd_mp2_pm_runtime_put(mp2_dev); + +- if (ret < 0) ++ if (ret < 0) { + dev_err(&pdev->dev, "i2c add adapter failed = %d\n", ret); ++ amd_mp2_unregister_cb(&i2c_dev->common); ++ } + + return ret; + } diff --git a/queue-6.18/i2c-imx-cancel-hrtimer-before-clearing-slave-pointer.patch b/queue-6.18/i2c-imx-cancel-hrtimer-before-clearing-slave-pointer.patch new file mode 100644 index 0000000000..04f403a105 --- /dev/null +++ b/queue-6.18/i2c-imx-cancel-hrtimer-before-clearing-slave-pointer.patch @@ -0,0 +1,42 @@ +From 6ac7702b6cc2b94aaed9ef2d95bfbefcdc90061f Mon Sep 17 00:00:00 2001 +From: Liem +Date: Mon, 29 Jun 2026 10:38:29 +0800 +Subject: i2c: imx: Cancel hrtimer before clearing slave pointer + +From: Liem + +commit 6ac7702b6cc2b94aaed9ef2d95bfbefcdc90061f upstream. + +In i2c_imx_unreg_slave(), the slave pointer is set to NULL after +disabling interrupts. However, a pending interrupt might already +have started the hrtimer (i2c_imx_slave_timeout) before the pointer +was cleared. If the hrtimer fires after i2c_imx->slave is set to +NULL, the timer callback i2c_imx_slave_finish_op() will call +i2c_imx_slave_event() with a NULL slave pointer, which results in a +use-after-free / NULL pointer dereference. + +Fix by canceling the hrtimer and waiting for it to complete after +disabling interrupts, before clearing the slave pointer. + +Fixes: f7414cd6923f ("i2c: imx: support slave mode for imx I2C driver") +Signed-off-by: Liem +Cc: # v5.11+ +Acked-by: Carlos Song +Reviewed-by: Frank Li +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260629023829.152651-3-liem16213@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-imx.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -960,6 +960,7 @@ static int i2c_imx_unreg_slave(struct i2 + + i2c_imx_reset_regs(i2c_imx); + ++ hrtimer_cancel(&i2c_imx->slave_timer); + i2c_imx->slave = NULL; + + /* Suspend */ diff --git a/queue-6.18/i2c-imx-fix-slave-registration-race-and-error-handling.patch b/queue-6.18/i2c-imx-fix-slave-registration-race-and-error-handling.patch new file mode 100644 index 0000000000..8a0549934a --- /dev/null +++ b/queue-6.18/i2c-imx-fix-slave-registration-race-and-error-handling.patch @@ -0,0 +1,64 @@ +From d64ec362c369bbc33833f7936d5f3a706b0d5c45 Mon Sep 17 00:00:00 2001 +From: Liem +Date: Mon, 29 Jun 2026 10:38:28 +0800 +Subject: i2c: imx: Fix slave registration race and error handling + +From: Liem + +commit d64ec362c369bbc33833f7936d5f3a706b0d5c45 upstream. + +In i2c_imx_reg_slave(), the slave pointer was assigned before +pm_runtime_resume_and_get(). If pm_runtime_resume_and_get() failed, +the error path returned without clearing i2c_imx->slave, leaving it +non-NULL and causing all subsequent registration attempts to fail +with -EBUSY. + +Additionally, because this driver uses a shared IRQ, the interrupt +handler i2c_imx_isr() can execute concurrently and, after acquiring +slave_lock, dereference i2c_imx->slave. The previous fix attempt +added a lockless i2c_imx->slave = NULL on the error path, but that +could race with the ISR under the lock and still cause a NULL pointer +dereference. + +Fix both issues by deferring the assignment of i2c_imx->slave and +i2c_imx->last_slave_event to after a successful resume, and by +performing the assignment inside the slave_lock critical section. +This guarantees that the slave pointer is never left stale on the +error path and is always valid when observed by the interrupt handler. + +Fixes: f7414cd6923f ("i2c: imx: support slave mode for imx I2C driver") +Signed-off-by: Liem +Cc: # v5.11+ +Reviewed-by: Frank Li +Acked-by: Carlos Song +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260629023829.152651-2-liem16213@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-imx.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -930,9 +930,6 @@ static int i2c_imx_reg_slave(struct i2c_ + if (i2c_imx->slave) + return -EBUSY; + +- i2c_imx->slave = client; +- i2c_imx->last_slave_event = I2C_SLAVE_STOP; +- + /* Resume */ + ret = pm_runtime_resume_and_get(i2c_imx->adapter.dev.parent); + if (ret < 0) { +@@ -940,6 +937,11 @@ static int i2c_imx_reg_slave(struct i2c_ + return ret; + } + ++ scoped_guard(spinlock_irqsave, &i2c_imx->slave_lock) { ++ i2c_imx->slave = client; ++ i2c_imx->last_slave_event = I2C_SLAVE_STOP; ++ } ++ + i2c_imx_slave_init(i2c_imx); + + return 0; diff --git a/queue-6.18/i2c-imx-mark-i2c-adapter-when-hardware-is-powered-down.patch b/queue-6.18/i2c-imx-mark-i2c-adapter-when-hardware-is-powered-down.patch new file mode 100644 index 0000000000..76fcd6d8ec --- /dev/null +++ b/queue-6.18/i2c-imx-mark-i2c-adapter-when-hardware-is-powered-down.patch @@ -0,0 +1,100 @@ +From 00d86dd5c2034e0e139e4806137b3b43e07ddd83 Mon Sep 17 00:00:00 2001 +From: Carlos Song +Date: Mon, 25 May 2026 11:04:00 +0800 +Subject: i2c: imx: mark I2C adapter when hardware is powered down + +From: Carlos Song + +commit 00d86dd5c2034e0e139e4806137b3b43e07ddd83 upstream. + +On some i.MX platforms, certain I2C client drivers keep a periodic +workqueue which continues to trigger I2C transfers. + +During system suspend/resume, there exists a time window between: + - suspend_noirq and the system entering suspend + - the system starting to resume and resume_noirq + +In this window, the I2C controller resources such as clock and pinctrl +may already be disabled or not yet restored. + +If a workqueue triggers an I2C transfer in this period, the driver +attempts to access I2C registers while the hardware resources are +unavailable, which may lead to system hang. + +Mark the I2C adapter as suspended during noirq suspend and block new +transfers until resume, ensuring that I2C transfers are only issued +when hardware resources are available. + +Fixes: 358025ac091e ("i2c: imx: make controller available until system suspend_noirq() and from resume_noirq()") +Signed-off-by: Carlos Song +Cc: # v6.14+ +Reviewed-by: Frank Li +Acked-by: Oleksij Rempel +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260525030400.3182911-1-carlos.song@oss.nxp.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-imx.c | 45 +++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 43 insertions(+), 2 deletions(-) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -1952,6 +1952,47 @@ static int i2c_imx_runtime_resume(struct + return 0; + } + ++static int __maybe_unused i2c_imx_suspend_noirq(struct device *dev) ++{ ++ struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); ++ int ret; ++ ++ i2c_mark_adapter_suspended(&i2c_imx->adapter); ++ ++ /* ++ * Cancel the slave timer before powering down to prevent ++ * i2c_imx_slave_timeout() from accessing hardware registers ++ * while the clock is disabled. ++ */ ++ hrtimer_cancel(&i2c_imx->slave_timer); ++ ++ ret = pm_runtime_force_suspend(dev); ++ if (ret) { ++ i2c_mark_adapter_resumed(&i2c_imx->adapter); ++ if (i2c_imx->slave) { ++ hrtimer_forward_now(&i2c_imx->slave_timer, I2C_IMX_CHECK_DELAY); ++ hrtimer_restart(&i2c_imx->slave_timer); ++ } ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int __maybe_unused i2c_imx_resume_noirq(struct device *dev) ++{ ++ struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = pm_runtime_force_resume(dev); ++ if (ret) ++ return ret; ++ ++ i2c_mark_adapter_resumed(&i2c_imx->adapter); ++ ++ return 0; ++} ++ + static int i2c_imx_suspend(struct device *dev) + { + /* +@@ -1985,8 +2026,8 @@ static int i2c_imx_resume(struct device + } + + static const struct dev_pm_ops i2c_imx_pm_ops = { +- NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, +- pm_runtime_force_resume) ++ NOIRQ_SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend_noirq, ++ i2c_imx_resume_noirq) + SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume) + RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL) + }; diff --git a/queue-6.18/i2c-iproc-reset-bus-after-timeout-if-start_busy-is-stuck.patch b/queue-6.18/i2c-iproc-reset-bus-after-timeout-if-start_busy-is-stuck.patch new file mode 100644 index 0000000000..16c3f8ea16 --- /dev/null +++ b/queue-6.18/i2c-iproc-reset-bus-after-timeout-if-start_busy-is-stuck.patch @@ -0,0 +1,69 @@ +From 98f2e9e6d6f91a6abb43f166b244b428ba85fa2b Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 17 Jul 2026 10:55:07 +0200 +Subject: i2c: iproc: reset bus after timeout if START_BUSY is stuck + +From: Jonas Gorski + +commit 98f2e9e6d6f91a6abb43f166b244b428ba85fa2b upstream. + +If a transaction times out, the START_BUSY signal can stay up, and +subsequent transactaction attempts will fail as the bus is still +considered busy. + +I can easily trigger this by attempting to read from an address with no +device, e.g. when running i2cdetect. After the first read times out, all +subsequent read attempts return busy. + +To get to a working state again, the controller needs to be reset to +clear the START_BUSY signal. So check for START_BUSY still asserted on a +timeout, and do reset in case it is, + +This is also done by the original non-upstream iproc-smbus driver +implementation [1]. + +Works around situations like: + + bcm-iproc-2c 1803b000.i2c: transaction timed out + bcm-iproc-2c 1803b000.i2c: bus is busy + bcm-iproc-2c 1803b000.i2c: bus is busy + bcm-iproc-2c 1803b000.i2c: bus is busy + bcm-iproc-2c 1803b000.i2c: bus is busy + bcm-iproc-2c 1803b000.i2c: bus is busy + ... + +where the bus never recovers after a timeout. + +[1] https://github.com/opencomputeproject/onie/blob/master/patches/kernel/3.2.69/driver-iproc-smbus.patch + +Fixes: e6e5dd3566e0 ("i2c: iproc: Add Broadcom iProc I2C Driver") +Signed-off-by: Jonas Gorski +Cc: # v4.0+ +Acked-by: Ray Jui +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260717085507.34209-1-jonas.gorski@bisdn.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-bcm-iproc.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/i2c/busses/i2c-bcm-iproc.c ++++ b/drivers/i2c/busses/i2c-bcm-iproc.c +@@ -803,6 +803,17 @@ static int bcm_iproc_i2c_xfer_wait(struc + } + + if (!time_left && !iproc_i2c->xfer_is_done) { ++ /* ++ * The controller may fail to clear START_BUSY after a timeout, ++ * reset the controller to recover in that case. ++ */ ++ if (!!(iproc_i2c_rd_reg(iproc_i2c, M_CMD_OFFSET) & ++ BIT(M_CMD_START_BUSY_SHIFT))) { ++ bcm_iproc_i2c_enable_disable(iproc_i2c, false); ++ bcm_iproc_i2c_init(iproc_i2c); ++ bcm_iproc_i2c_enable_disable(iproc_i2c, true); ++ } ++ + /* flush both TX/RX FIFOs */ + val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, M_FIFO_CTRL_OFFSET, val); diff --git a/queue-6.18/i2c-jz4780-cache-host-clock-rate-at-probe-to-prevent-ccf-prepare_lock-deadlock.patch b/queue-6.18/i2c-jz4780-cache-host-clock-rate-at-probe-to-prevent-ccf-prepare_lock-deadlock.patch new file mode 100644 index 0000000000..8a7aa7338b --- /dev/null +++ b/queue-6.18/i2c-jz4780-cache-host-clock-rate-at-probe-to-prevent-ccf-prepare_lock-deadlock.patch @@ -0,0 +1,75 @@ +From d99607c888f26e8a4e9fe9772860cef4aff86bb4 Mon Sep 17 00:00:00 2001 +From: "H. Nikolaus Schaller" +Date: Sun, 19 Jul 2026 22:19:43 +0200 +Subject: i2c: jz4780: Cache host clock rate at probe to prevent CCF prepare_lock deadlock + +From: H. Nikolaus Schaller + +commit d99607c888f26e8a4e9fe9772860cef4aff86bb4 upstream. + +Fix a severe AB/BA deadlock between the Common Clock Framework (CCF) +and the I2C adapter lock, which triggers when an I2C-controlled clock +generator client (like the Si5351) is registered or modified under the CCF. + +During an i2c client clock (generator) frequency change, the CCF acquires its global +'prepare_lock' mutex and the driver calls i2c_transfer() to update the client's +chip registers, stalling for the adapter's I2C bus lock. + +Concurrently, an independent, parallel transfer on the same bus (e.g., a GPIO +expander handling LEDs) can hold the I2C adapter lock. Inside this parallel +transfer path, jz4780_i2c_set_speed() calls clk_get_rate() on the host +controller's input clock to calculate bus timings. This call attempts to acquire +the blocked CCF 'prepare_lock', creating a circular dependency that freezes +the system. + +The jz4780 host controller clock itself is static and never changes at runtime. + +However, calling clk_get_rate() inside the active transfer path introduces +an unnecessary dependency on the CCF internal locks. + +Eliminate this synchronous clk_get_rate() call from the active transfer +path by caching the static host peripheral clock rate once - inside the private +jz4780_i2c structure during jz4780_i2c_probe(). Update jz4780_i2c_set_speed() +to use this cached value, safely decoupling active I2C transactions from the +CCF internal locks without any risk of stale timings. + +Assisted-by web based Google AI (pinpointing the bug and writing the message). + +Fixes: ba92222ed63a12 ("i2c: jz4780: Add i2c bus controller driver for Ingenic JZ4780") +Signed-off-by: H. Nikolaus Schaller +Cc: # v4.1+ +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/2db6fd233aceb7238474e4833f4d25ca681c3ffb.1784492382.git.hns@goldelico.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-jz4780.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-jz4780.c ++++ b/drivers/i2c/busses/i2c-jz4780.c +@@ -141,6 +141,7 @@ struct jz4780_i2c { + void __iomem *iomem; + int irq; + struct clk *clk; ++ unsigned long clk_rate_khz; + struct i2c_adapter adap; + const struct ingenic_i2c_config *cdata; + +@@ -246,7 +247,7 @@ static int jz4780_i2c_set_target(struct + + static int jz4780_i2c_set_speed(struct jz4780_i2c *i2c) + { +- int dev_clk_khz = clk_get_rate(i2c->clk) / 1000; ++ int dev_clk_khz = i2c->clk_rate_khz; + int cnt_high = 0; /* HIGH period count of the SCL clock */ + int cnt_low = 0; /* LOW period count of the SCL clock */ + int cnt_period = 0; /* period count of the SCL clock */ +@@ -796,6 +797,8 @@ static int jz4780_i2c_probe(struct platf + if (IS_ERR(i2c->clk)) + return PTR_ERR(i2c->clk); + ++ i2c->clk_rate_khz = clk_get_rate(i2c->clk) / 1000; ++ + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &clk_freq); + if (ret) { diff --git a/queue-6.18/i2c-qcom-cci-drop-custom-suspend-resume-and-rely-on-runtime-pm-helpers.patch b/queue-6.18/i2c-qcom-cci-drop-custom-suspend-resume-and-rely-on-runtime-pm-helpers.patch new file mode 100644 index 0000000000..943f98855a --- /dev/null +++ b/queue-6.18/i2c-qcom-cci-drop-custom-suspend-resume-and-rely-on-runtime-pm-helpers.patch @@ -0,0 +1,58 @@ +From b08c9857aa1f5f3a81d375d6d4bb1d8b92f22ebc Mon Sep 17 00:00:00 2001 +From: Wenmeng Liu +Date: Thu, 25 Jun 2026 17:42:45 +0800 +Subject: i2c: qcom-cci: drop custom suspend/resume and rely on runtime PM helpers + +From: Wenmeng Liu + +commit b08c9857aa1f5f3a81d375d6d4bb1d8b92f22ebc upstream. + +cci_resume() unconditionally calls cci_resume_runtime() regardless of +the runtime PM state. + +If the device is already runtime-suspended before system suspend, +the clock is re-enabled while runtime_status remains RPM_SUSPENDED. +As a result, pm_request_autosuspend() does not arm the timer, +leaving the clock permanently enabled. + +Fixes: e517526195de ("i2c: Add Qualcomm CCI I2C driver") +Signed-off-by: Wenmeng Liu +Cc: # v5.8+ +Reviewed-by: Vladimir Zapolskiy +Reviewed-by: Konrad Dybcio +Reviewed-by: Loic Poulain +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260625-cci-v1-1-a100cda673ce@oss.qualcomm.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-qcom-cci.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +--- a/drivers/i2c/busses/i2c-qcom-cci.c ++++ b/drivers/i2c/busses/i2c-qcom-cci.c +@@ -496,24 +496,8 @@ static int __maybe_unused cci_resume_run + return 0; + } + +-static int __maybe_unused cci_suspend(struct device *dev) +-{ +- if (!pm_runtime_suspended(dev)) +- return cci_suspend_runtime(dev); +- +- return 0; +-} +- +-static int __maybe_unused cci_resume(struct device *dev) +-{ +- cci_resume_runtime(dev); +- pm_request_autosuspend(dev); +- +- return 0; +-} +- + static const struct dev_pm_ops qcom_cci_pm = { +- SET_SYSTEM_SLEEP_PM_OPS(cci_suspend, cci_resume) ++ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(cci_suspend_runtime, cci_resume_runtime, NULL) + }; + diff --git a/queue-6.18/i2c-spacemit-request-irq-after-controller-initialization.patch b/queue-6.18/i2c-spacemit-request-irq-after-controller-initialization.patch new file mode 100644 index 0000000000..89aa9449ab --- /dev/null +++ b/queue-6.18/i2c-spacemit-request-irq-after-controller-initialization.patch @@ -0,0 +1,54 @@ +From cdac670237258c8ca063aa8a16998f680d81b80d Mon Sep 17 00:00:00 2001 +From: Linmao Li +Date: Thu, 23 Jul 2026 10:11:40 +0800 +Subject: i2c: spacemit: request IRQ after controller initialization + +From: Linmao Li + +commit cdac670237258c8ca063aa8a16998f680d81b80d upstream. + +spacemit_i2c_probe() requests the IRQ before it enables the clocks, resets +the controller and runs init_completion(). If an interrupt is already +pending, the handler runs too early: it reads registers while the clocks +are still off and calls complete() on an uninitialized completion. Request +the IRQ after the controller and completion are initialized, but still +before the adapter is registered. + +Fixes: 5ea558473fa3 ("i2c: spacemit: add support for SpacemiT K1 SoC") +Signed-off-by: Linmao Li +Cc: # v6.15+ +Reviewed-by: Troy Mitchell +Reviewed-by: Alex Elder +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260723021140.2293844-1-lilinmao@kylinos.cn +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-k1.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/i2c/busses/i2c-k1.c ++++ b/drivers/i2c/busses/i2c-k1.c +@@ -565,11 +565,6 @@ static int spacemit_i2c_probe(struct pla + if (i2c->irq < 0) + return dev_err_probe(dev, i2c->irq, "failed to get irq resource"); + +- ret = devm_request_irq(i2c->dev, i2c->irq, spacemit_i2c_irq_handler, +- IRQF_NO_SUSPEND, dev_name(i2c->dev), i2c); +- if (ret) +- return dev_err_probe(dev, ret, "failed to request irq"); +- + clk = devm_clk_get_enabled(dev, "func"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to enable func clock"); +@@ -592,6 +587,11 @@ static int spacemit_i2c_probe(struct pla + + init_completion(&i2c->complete); + ++ ret = devm_request_irq(i2c->dev, i2c->irq, spacemit_i2c_irq_handler, ++ IRQF_NO_SUSPEND, dev_name(i2c->dev), i2c); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to request irq"); ++ + platform_set_drvdata(pdev, i2c); + + ret = i2c_add_numbered_adapter(&i2c->adapt); diff --git a/queue-6.18/ice-fix-memory-leak-in-ice_lbtest_prepare_rings.patch b/queue-6.18/ice-fix-memory-leak-in-ice_lbtest_prepare_rings.patch new file mode 100644 index 0000000000..782750ae10 --- /dev/null +++ b/queue-6.18/ice-fix-memory-leak-in-ice_lbtest_prepare_rings.patch @@ -0,0 +1,68 @@ +From 3a9de5590da4ffd9e9c541c4c4d492aa2b54cf6e Mon Sep 17 00:00:00 2001 +From: Dawei Feng +Date: Tue, 16 Jun 2026 23:57:42 +0800 +Subject: ice: fix memory leak in ice_lbtest_prepare_rings() + +From: Dawei Feng + +commit 3a9de5590da4ffd9e9c541c4c4d492aa2b54cf6e upstream. + +ice_lbtest_prepare_rings() frees Rx rings only when +ice_vsi_start_all_rx_rings() fails. If ice_vsi_setup_rx_rings() fails +after allocating some descriptors, or if ice_vsi_cfg_lan() fails after +the Rx rings were prepared, the function reaches the Tx cleanup path +without releasing the initialized Rx resources. + +Fix this by adding separate unwind paths for Rx setup failure and LAN +configuration failure. The Rx setup failure path releases the partially +prepared Rx rings before freeing Tx rings, while later failures first +undo the LAN Tx configuration and then release the Rx rings in reverse +setup order. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still +present in v7.1-rc7. + +An x86_64 allyesconfig build showed no new warnings. As we do not have an +Intel E800 Series adapter available to run the ethtool offline loopback +selftest, no runtime testing was able to be performed. + +Fixes: 0e674aeb0b77 ("ice: Add handler for ethtool selftest") +Cc: stable@vger.kernel.org +Signed-off-by: Dawei Feng +Reviewed-by: Jacob Keller +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -1077,18 +1077,18 @@ static int ice_lbtest_prepare_rings(stru + + status = ice_vsi_cfg_lan(vsi); + if (status) +- goto err_setup_rx_ring; ++ goto err_cfg_lan; + + status = ice_vsi_start_all_rx_rings(vsi); + if (status) +- goto err_start_rx_ring; ++ goto err_cfg_lan; + + return 0; + +-err_start_rx_ring: +- ice_vsi_free_rx_rings(vsi); +-err_setup_rx_ring: ++err_cfg_lan: + ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); ++err_setup_rx_ring: ++ ice_vsi_free_rx_rings(vsi); + err_setup_tx_ring: + ice_vsi_free_tx_rings(vsi); + diff --git a/queue-6.18/ice-fix-vf-interrupts-cleanup.patch b/queue-6.18/ice-fix-vf-interrupts-cleanup.patch new file mode 100644 index 0000000000..9e2d0a7644 --- /dev/null +++ b/queue-6.18/ice-fix-vf-interrupts-cleanup.patch @@ -0,0 +1,128 @@ +From fb096882095e5a8d6b5159e43793d4a38a0c5b1f Mon Sep 17 00:00:00 2001 +From: Dawid Osuchowski +Date: Thu, 14 May 2026 18:35:55 +0200 +Subject: ice: fix VF interrupts cleanup + +From: Dawid Osuchowski + +commit fb096882095e5a8d6b5159e43793d4a38a0c5b1f upstream. + +When a virtual function sends an IRQ map command, the PF will set up +interrupts according to that request. However, because these interrupts are +never reset, the next time Virtual Function initializes, the interrupts are +still enabled for a given VF, which leads to performance degradation in +certain cases due to interrupts being unexpectedly enabled and thus causing +interrupt floods. + +Cc: stable@vger.kernel.org +Fixes: 1071a8358a28 ("ice: Implement virtchnl commands for AVF support") +Suggested-by: Vladimir Medvedkin +Reviewed-by: Aleksandr Loktionov +Signed-off-by: Dawid Osuchowski +Reviewed-by: Simon Horman +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 27 ++++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_vf_lib_private.h | 1 + drivers/net/ethernet/intel/ice/virt/queues.c | 21 +++++++++++++++ + 3 files changed, 49 insertions(+) + +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -849,6 +849,30 @@ static void ice_notify_vf_reset(struct i + } + + /** ++ * ice_reset_interrupts - clear all queue interrupt configuration for a VSI ++ * @vsi: the VSI whose interrupt registers should be cleared ++ * ++ * Zero the QINT_RQCTL and QINT_TQCTL registers for all allocated queues ++ * in the VSI. This clears the entire register including MSIX_INDX, ITR_INDX, ++ * CAUSE_ENA and NEXTQ fields, unlike ice_vf_dis_rxq_interrupt() which only ++ * clears the CAUSE_ENA bit. ++ */ ++void ice_reset_interrupts(struct ice_vsi *vsi) ++{ ++ struct ice_pf *pf = vsi->back; ++ struct ice_hw *hw = &pf->hw; ++ int i; ++ ++ ice_for_each_alloc_rxq(vsi, i) ++ wr32(hw, QINT_RQCTL(vsi->rxq_map[i]), 0); ++ ++ ice_for_each_alloc_txq(vsi, i) ++ wr32(hw, QINT_TQCTL(vsi->txq_map[i]), 0); ++ ++ ice_flush(hw); ++} ++ ++/** + * ice_reset_vf - Reset a particular VF + * @vf: pointer to the VF structure + * @flags: flags controlling behavior of the reset +@@ -919,6 +943,9 @@ int ice_reset_vf(struct ice_vf *vf, u32 + + ice_dis_vf_qs(vf); + ++ /* cleanup interrupt registers */ ++ ice_reset_interrupts(vsi); ++ + /* Call Disable LAN Tx queue AQ whether or not queues are + * enabled. This is needed for successful completion of VFR. + */ +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h +@@ -26,6 +26,7 @@ + void ice_initialize_vf_entry(struct ice_vf *vf); + void ice_deinitialize_vf_entry(struct ice_vf *vf); + void ice_dis_vf_qs(struct ice_vf *vf); ++void ice_reset_interrupts(struct ice_vsi *vsi); + int ice_check_vf_init(struct ice_vf *vf); + enum virtchnl_status_code ice_err_to_virt_err(int err); + struct ice_port_info *ice_vf_get_port_info(struct ice_vf *vf); +--- a/drivers/net/ethernet/intel/ice/virt/queues.c ++++ b/drivers/net/ethernet/intel/ice/virt/queues.c +@@ -225,6 +225,24 @@ void ice_vf_ena_rxq_interrupt(struct ice + } + + /** ++ * ice_vf_dis_rxq_interrupt - disable Rx queue interrupt via QINT_RQCTL ++ * @vsi: VSI of the VF to configure ++ * @q_idx: VF queue index used to determine the queue in the PF's space ++ */ ++static void ice_vf_dis_rxq_interrupt(struct ice_vsi *vsi, u32 q_idx) ++{ ++ struct ice_hw *hw = &vsi->back->hw; ++ u32 pfq = vsi->rxq_map[q_idx]; ++ u32 reg; ++ ++ reg = rd32(hw, QINT_RQCTL(pfq)); ++ reg &= ~QINT_RQCTL_CAUSE_ENA_M; ++ wr32(hw, QINT_RQCTL(pfq), reg); ++ ++ ice_flush(hw); ++} ++ ++/** + * ice_vc_ena_qs_msg + * @vf: pointer to the VF info + * @msg: pointer to the msg buffer +@@ -416,6 +434,8 @@ int ice_vc_dis_qs_msg(struct ice_vf *vf, + goto error_param; + } + ++ for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) ++ ice_vf_dis_rxq_interrupt(vsi, vf_q_id); + bitmap_zero(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF); + } else if (q_map) { + for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) { +@@ -436,6 +456,7 @@ int ice_vc_dis_qs_msg(struct ice_vf *vf, + goto error_param; + } + ++ ice_vf_dis_rxq_interrupt(vsi, vf_q_id); + /* Clear enabled queues flag */ + clear_bit(vf_q_id, vf->rxq_ena); + } diff --git a/queue-6.18/ice-wait-for-reset-completion-in-ice_resume.patch b/queue-6.18/ice-wait-for-reset-completion-in-ice_resume.patch new file mode 100644 index 0000000000..3739077c7d --- /dev/null +++ b/queue-6.18/ice-wait-for-reset-completion-in-ice_resume.patch @@ -0,0 +1,65 @@ +From c2816d613f388814d27bc9fd6dbd931a88056e19 Mon Sep 17 00:00:00 2001 +From: Aaron Ma +Date: Wed, 29 Apr 2026 11:48:49 +0800 +Subject: ice: wait for reset completion in ice_resume() + +From: Aaron Ma + +commit c2816d613f388814d27bc9fd6dbd931a88056e19 upstream. + +ice_resume() schedules an asynchronous PF reset and returns +immediately. The reset runs later in ice_service_task(). If +userspace tries to bring up the net device before the reset +finishes, ice_open() fails with -EBUSY: + + ice_resume() + ice_schedule_reset() # sets ICE_PFR_REQ, returns + ... + ice_open() + ice_is_reset_in_progress() # ICE_PFR_REQ still set, -EBUSY + ... + ice_service_task() + ice_do_reset() + ice_rebuild() # clears ICE_PFR_REQ, too late + +Reproduced on E800 series NICs during suspend/resume with irdma +enabled, where the aux device probe widens the race window. + + ice 0000:81:00.0: can't open net device while reset is in progress + +Add a best-effort wait (10s timeout, matching ice_devlink_info_get()) +for the reset to complete before returning from ice_resume(). In +practice the reset completes in ~300ms. + +Fixes: 769c500dcc1e ("ice: Add advanced power mgmt for WoL") +Cc: stable@vger.kernel.org +Reviewed-by: Kohei Enju +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Przemek Kitszel +Signed-off-by: Aaron Ma +Tested-by: Alexander Nowlin +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_main.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -5713,6 +5713,16 @@ static int ice_resume(struct device *dev + /* Restart the service task */ + mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period)); + ++ /* Best-effort wait for the scheduled reset to finish so that the ++ * device is operational before returning. Without this, userspace ++ * (e.g. NetworkManager) may try to open the net device while the ++ * asynchronous reset is still in progress, hitting -EBUSY. ++ */ ++ ret = ice_wait_for_reset(pf, secs_to_jiffies(10)); ++ if (ret) ++ dev_err(dev, "Wait for reset timed out (10s) during resume: %d\n", ++ ret); ++ + return 0; + } + diff --git a/queue-6.18/io_uring-net-initialize-mshot_len-for-send.patch b/queue-6.18/io_uring-net-initialize-mshot_len-for-send.patch new file mode 100644 index 0000000000..4b80a597fc --- /dev/null +++ b/queue-6.18/io_uring-net-initialize-mshot_len-for-send.patch @@ -0,0 +1,38 @@ +From c77ffbc980efb337fd750c337d8157d532ea14e5 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Sun, 26 Jul 2026 08:12:38 -0600 +Subject: io_uring/net: initialize mshot_len for send + +From: Jens Axboe + +commit c77ffbc980efb337fd750c337d8157d532ea14e5 upstream. + +Commit: + +6a8afb9fff64 ("io_uring/net: allow multishot receive per-invocation cap") + +changed how io_mshot_prep_retry() set sr->len, and added the same +initialization in io_mshot_prep_retry(). But it neglected to touch the +send path, which may also uses the mshot retry path. Ensure that +sr->mshot_len always gets initialized correctly. + +Fixes: 6a8afb9fff64 ("io_uring/net: allow multishot receive per-invocation cap") +Cc: stable@vger.kernel.org +Reported-by: Sung Keum +Reviewed-by: Gabriel Krisman Bertazi +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/net.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/io_uring/net.c ++++ b/io_uring/net.c +@@ -433,6 +433,7 @@ int io_sendmsg_prep(struct io_kiocb *req + req->flags |= REQ_F_NOWAIT; + if (req->flags & REQ_F_BUFFER_SELECT) + sr->buf_group = req->buf_index; ++ sr->mshot_total_len = sr->mshot_len = 0; + if (sr->flags & IORING_RECVSEND_BUNDLE) { + if (req->opcode == IORING_OP_SENDMSG) + return -EINVAL; diff --git a/queue-6.18/mm-memcg-initialize-locked-in-memcg1_oom_prepare-stub.patch b/queue-6.18/mm-memcg-initialize-locked-in-memcg1_oom_prepare-stub.patch new file mode 100644 index 0000000000..91c9481245 --- /dev/null +++ b/queue-6.18/mm-memcg-initialize-locked-in-memcg1_oom_prepare-stub.patch @@ -0,0 +1,64 @@ +From 1833ce36b35426504c64600c94f322437ea44bb2 Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Thu, 16 Jul 2026 06:42:18 -0700 +Subject: mm: memcg: initialize *locked in memcg1_oom_prepare() stub + +From: Breno Leitao + +commit 1833ce36b35426504c64600c94f322437ea44bb2 upstream. + +mem_cgroup_oom() passes an uninitialized "locked" to memcg1_oom_prepare() +and reads it back in memcg1_oom_finish(): + + bool locked, ret; + ... + if (!memcg1_oom_prepare(memcg, &locked)) + return false; + ret = mem_cgroup_out_of_memory(memcg, mask, order); + memcg1_oom_finish(memcg, locked); + +This relies on memcg1_oom_prepare() setting *locked whenever it returns +true. The CONFIG_MEMCG_V1=y version does, but the stub used when +CONFIG_MEMCG_V1=n returns true without touching *locked, so +memcg1_oom_finish() consumes an uninitialized value. On a memcg OOM this +is reported by UBSAN: + + UBSAN: invalid-load in mm/memcontrol.c:1932:27 + load of value 0 is not a valid value for type 'bool' (aka '_Bool') + +Initialize *locked to false in the stub; with cgroup v1 compiled out there +is no OOM lock to take. + +Link: https://lore.kernel.org/20260716-memcg-oom-uninit-locked-v2-1-63631d878eb4@debian.org +Fixes: e93d4166b40a ("mm: memcg: put cgroup v1-specific code under a config option") +Signed-off-by: Breno Leitao +Reviewed-by: Joshua Hahn +Acked-by: Johannes Weiner +Reviewed-by: SeongJae Park +Acked-by: Shakeel Butt +Cc: Michal Hocko +Cc: Muchun Song +Cc: Roman Gushchin +Cc: Shakeel Butt +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/memcontrol-v1.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/mm/memcontrol-v1.h ++++ b/mm/memcontrol-v1.h +@@ -103,7 +103,11 @@ static inline void memcg1_remove_from_tr + static inline void memcg1_soft_limit_reset(struct mem_cgroup *memcg) {} + static inline void memcg1_css_offline(struct mem_cgroup *memcg) {} + +-static inline bool memcg1_oom_prepare(struct mem_cgroup *memcg, bool *locked) { return true; } ++static inline bool memcg1_oom_prepare(struct mem_cgroup *memcg, bool *locked) ++{ ++ *locked = false; ++ return true; ++} + static inline void memcg1_oom_finish(struct mem_cgroup *memcg, bool locked) {} + static inline void memcg1_oom_recover(struct mem_cgroup *memcg) {} + diff --git a/queue-6.18/mm-page_reporting-use-system_freezable_wq-to-fix-uaf-during-suspend.patch b/queue-6.18/mm-page_reporting-use-system_freezable_wq-to-fix-uaf-during-suspend.patch new file mode 100644 index 0000000000..d2a53fe462 --- /dev/null +++ b/queue-6.18/mm-page_reporting-use-system_freezable_wq-to-fix-uaf-during-suspend.patch @@ -0,0 +1,98 @@ +From 0b45f6927a14914ff685fe0e6f9d11232a1e03df Mon Sep 17 00:00:00 2001 +From: Link Lin +Date: Tue, 21 Jul 2026 00:55:33 +0000 +Subject: mm/page_reporting: use system_freezable_wq to fix UAF during suspend +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Link Lin + +commit 0b45f6927a14914ff685fe0e6f9d11232a1e03df upstream. + +During PM freeze (e.g. S3 suspend or S4 hibernation), device drivers like +virtio_balloon reset their underlying virtio devices and delete their +virtqueues via vdev->config->del_vqs(). + +However, page reporting work (page_reporting_process) was scheduled on the +global system_wq. Because system_wq lacks the WQ_FREEZABLE flag, the PM +freezer skips it, leaving page_reporting_process active during suspend. + +If pages are freed into the buddy allocator while suspending (for example, +when core MM invokes the balloon shrinker during S4 hibernation image +saving), page reporting triggers virtballoon_free_page_report() on deleted +virtqueues, resulting in a Use-After-Free / General Protection Fault: + + [ 196.795226] general protection fault, probably for non-canonical address 0xaa1436fe70dae6df: 0000 [#1] SMP NOPTI + [ 196.825967] Workqueue: events page_reporting_process + [ 196.831038] RIP: 0010:virtqueue_add_split+0x233/0x4c0 [virtio_ring] + [ 196.927073] virtballoon_free_page_report+0x3a/0xe0 [virtio_balloon] + [ 196.946943] page_reporting_process+0x370/0x4f0 + +Fix this by switching page reporting work to system_freezable_wq. This +ensures that the PM freezer pauses page_reporting_process before device +drivers destroy their reporting virtqueues. Because the reporting worker +is frozen, memory reclamation/freeing (e.g. via shrinker execution) can +safely return pages to MM during freeze without triggering unfrozen +reporting work on deleted virtqueues. + +This aligns with the driver's existing design. The comment in +virtballoon_freeze() states: + /* + * The workqueue is already frozen by the PM core before this + * function is called. + */ + +Testing: +I have verified these fixes using Google’s virtualization infrastructure +by running continuous suspend/resume iterations (40+ cycles) while +churning memory using stress-ng (`stress-ng --vm 4 --vm-bytes 60% +--timeout 1`) to constantly create free pages for the buddy allocator. We +also set the `page_reporting_order` parameter to 0 to make the page +reporting worker highly sensitive, forcing it to pick up any 4K free +pages. This confirmed that the UAF crashes are no longer reproducible. + +Link: https://lore.kernel.org/20260721005603.1710551-1-linkl@google.com +Fixes: 36e66c554b5c ("mm: introduce Reported pages") +Signed-off-by: Link Lin +Suggested-by: David Hildenbrand (Arm) +Suggested-by: Michael S. Tsirkin +Acked-by: David Rientjes +Acked-by: David Hildenbrand (Arm) +Acked-by: Michael S. Tsirkin +Cc: Alexander Duyck +Cc: Greg Thelen +Cc: James Houghton +Cc: Jason Wang +Cc: Jiaqi Yan +Cc: Vlastimil Babka +Cc: Xuan Zhuo +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/page_reporting.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/mm/page_reporting.c ++++ b/mm/page_reporting.c +@@ -80,7 +80,8 @@ __page_reporting_request(struct page_rep + * now we are limiting this to running no more than once every + * couple of seconds. + */ +- schedule_delayed_work(&prdev->work, PAGE_REPORTING_DELAY); ++ queue_delayed_work(system_freezable_wq, &prdev->work, ++ PAGE_REPORTING_DELAY); + } + + /* notify prdev of free page reporting request */ +@@ -343,7 +344,8 @@ err_out: + */ + state = atomic_cmpxchg(&prdev->state, state, PAGE_REPORTING_IDLE); + if (state == PAGE_REPORTING_REQUESTED) +- schedule_delayed_work(&prdev->work, PAGE_REPORTING_DELAY); ++ queue_delayed_work(system_freezable_wq, &prdev->work, ++ PAGE_REPORTING_DELAY); + } + + static DEFINE_MUTEX(page_reporting_mutex); diff --git a/queue-6.18/net-bridge-stop-fast-leave-after-deleting-a-port-group.patch b/queue-6.18/net-bridge-stop-fast-leave-after-deleting-a-port-group.patch new file mode 100644 index 0000000000..3b76b8cd49 --- /dev/null +++ b/queue-6.18/net-bridge-stop-fast-leave-after-deleting-a-port-group.patch @@ -0,0 +1,47 @@ +From a39789f211b8a4125f0c70e05b30cf715f4f187d Mon Sep 17 00:00:00 2001 +From: Zhiling Zou +Date: Fri, 24 Jul 2026 00:52:48 +0800 +Subject: net: bridge: stop fast-leave after deleting a port group + +From: Zhiling Zou + +commit a39789f211b8a4125f0c70e05b30cf715f4f187d upstream. + +br_multicast_leave_group() iterates mp->ports with pp = &p->next in +its fast-leave path. After br_multicast_del_pg() removes p, +continuing the loop advances pp through the deleted entry. + +If multicast-to-unicast was enabled, the bridge can hold multiple port +groups for the same port and group with different source MAC +addresses. Once multicast-to-unicast is disabled, +br_port_group_equal() matches those entries by port only. A fast leave +can then delete one entry and continue from its stale next pointer, +leaving mp->ports pointing at a deleted port group. + +Fast leave only needs to remove one matching port group. Break after +br_multicast_del_pg() so the loop stops before dereferencing the +removed entry. + +Fixes: 6db6f0eae605 ("bridge: multicast to unicast") +Cc: stable@vger.kernel.org +Reported-by: Vega +Signed-off-by: Zhiling Zou +Signed-off-by: Ren Wei +Acked-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/1cf0898872ef7c72d5f4c0304414a192c6dac591.1784707712.git.zhilinz@nebusec.ai +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/br_multicast.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -3686,6 +3686,7 @@ br_multicast_leave_group(struct net_brid + + p->flags |= MDB_PG_FLAGS_FAST_LEAVE; + br_multicast_del_pg(mp, p, pp); ++ break; + } + goto out; + } diff --git a/queue-6.18/net-ipv6-clear-suppressed-fib6-rule-result.patch b/queue-6.18/net-ipv6-clear-suppressed-fib6-rule-result.patch new file mode 100644 index 0000000000..d2a8e613a1 --- /dev/null +++ b/queue-6.18/net-ipv6-clear-suppressed-fib6-rule-result.patch @@ -0,0 +1,43 @@ +From 6aea62e433fe1b586202a5fee8b5807ce635e1d7 Mon Sep 17 00:00:00 2001 +From: Zhiling Zou +Date: Fri, 24 Jul 2026 00:48:52 +0800 +Subject: net: ipv6: clear suppressed fib6 rule result + +From: Zhiling Zou + +commit 6aea62e433fe1b586202a5fee8b5807ce635e1d7 upstream. + +fib6_rule_suppress() drops a suppressed route with ip6_rt_put_flags(), +but leaves res->rt6 pointing at the released rt6_info. + +If no later rule supplies a replacement, fib6_rule_lookup() still sees +res.rt6 and returns that stale dst to its caller. A suppressing rule can +therefore leak a released route back to rt6_lookup(), and the next put +hits rcuref_put_slowpath() from dst_release(). + +Clear res->rt6 when suppressing the route so suppressed lookups fall +through to the null dst instead of reusing the released one. + +Fixes: cdef485217d3 ("ipv6: fix memory leak in fib6_rule_suppress") +Cc: stable@vger.kernel.org +Reported-by: Vega +Signed-off-by: Zhiling Zou +Signed-off-by: Ren Wei +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/4b8acb7787d54e440155585dd32ebdf0bef7d122.1784710966.git.zhilinz@nebusec.ai +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/fib6_rules.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -305,6 +305,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_s + + suppress_route: + ip6_rt_put_flags(rt, flags); ++ res->rt6 = NULL; + return true; + } + diff --git a/queue-6.18/net-openvswitch-fix-potential-uaf-on-meter-attach-failure.patch b/queue-6.18/net-openvswitch-fix-potential-uaf-on-meter-attach-failure.patch new file mode 100644 index 0000000000..6d3132eb4b --- /dev/null +++ b/queue-6.18/net-openvswitch-fix-potential-uaf-on-meter-attach-failure.patch @@ -0,0 +1,120 @@ +From a58a2b0ce354df531ebc71fc870058c2feb59f6b Mon Sep 17 00:00:00 2001 +From: Ilya Maximets +Date: Mon, 27 Jul 2026 14:10:21 +0200 +Subject: net: openvswitch: fix potential UAF on meter attach failure + +From: Ilya Maximets + +commit a58a2b0ce354df531ebc71fc870058c2feb59f6b upstream. + +While attaching a newly created meter attach_meter() function makes +the new meter visible to other CPUs but can still fail afterwards. +On failure, it detaches the meter back and returns an error. + +However, this is an unexpected behavior for the ovs_meter_cmd_set() +that uses a plain kfree(meter) on attach failure without waiting for +RCU readers to stop using it, assuming it was never visible. + +This is never a problem for ovs-vswitchd as it always creates meters +before creating any flows that use them. But the UAF can be triggered +with a custom application using uAPI: + + BUG: KASAN: slab-use-after-free in ovs_meter_execute (net/openvswitch/meter.c:653) + Read of size 8 at addr ffff88810d152650 by task meter/2508 + + Call Trace: + ovs_meter_execute (net/openvswitch/meter.c:653) + do_execute_actions (net/openvswitch/actions.c:1407) + ovs_execute_actions (net/openvswitch/actions.c:1584) + ovs_packet_cmd_execute (net/openvswitch/datapath.c:703) + ... + netlink_sendmsg (af_netlink.c:1900) + + Allocated by task 2519: + __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415) + ovs_meter_cmd_set (net/openvswitch/meter.c:422) + ... + netlink_sendmsg (af_netlink.c:1900) + + Freed by task 2519: + kfree (mm/slub.c:2705 mm/slub.c:6405 mm/slub.c:6720) + ovs_meter_cmd_set (net/openvswitch/meter.c:479) + ... + netlink_sendmsg (af_netlink.c:1900) + +Fix that by making sure attach_meter() doesn't make the meter visible +until all the checks are done and the function can't fail anymore. + +This also makes sure the "hash" value is calculated after the potential +re-sizing of the table. + +Reported by Trend Micro's Zero Day Initiative as ZDI-CAN-31642. + +Fixes: c7c4c44c9a95 ("net: openvswitch: expand the meters supported number") +Cc: stable@vger.kernel.org +Signed-off-by: Ilya Maximets +Reviewed-by: Eelco Chaudron +Link: https://patch.msgid.link/20260727121022.198461-1-i.maximets@ovn.org +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + net/openvswitch/meter.c | 33 +++++++++++++++++++-------------- + 1 file changed, 19 insertions(+), 14 deletions(-) + +--- a/net/openvswitch/meter.c ++++ b/net/openvswitch/meter.c +@@ -133,18 +133,10 @@ static void dp_meter_instance_remove(str + + static int attach_meter(struct dp_meter_table *tbl, struct dp_meter *meter) + { +- struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti); +- u32 hash = meter_hash(ti, meter->id); ++ struct dp_meter_instance *ti; ++ u32 hash; + int err; + +- /* In generally, slots selected should be empty, because +- * OvS uses id-pool to fetch a available id. +- */ +- if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash]))) +- return -EBUSY; +- +- dp_meter_instance_insert(ti, meter); +- + /* That function is thread-safe. */ + tbl->count++; + if (tbl->count >= tbl->max_meters_allowed) { +@@ -152,16 +144,29 @@ static int attach_meter(struct dp_meter_ + goto attach_err; + } + +- if (tbl->count >= ti->n_meters && +- dp_meter_instance_realloc(tbl, ti->n_meters * 2)) { +- err = -ENOMEM; ++ ti = rcu_dereference_ovsl(tbl->ti); ++ if (tbl->count >= ti->n_meters) { ++ err = dp_meter_instance_realloc(tbl, ti->n_meters * 2); ++ if (err) ++ goto attach_err; ++ ++ ti = rcu_dereference_ovsl(tbl->ti); ++ } ++ ++ hash = meter_hash(ti, meter->id); ++ ++ /* In general, selected slots should be empty, because ++ * OvS uses id-pool to fetch available ids. ++ */ ++ if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash]))) { ++ err = -EBUSY; + goto attach_err; + } + ++ dp_meter_instance_insert(ti, meter); + return 0; + + attach_err: +- dp_meter_instance_remove(ti, meter); + tbl->count--; + return err; + } diff --git a/queue-6.18/net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-ct.patch b/queue-6.18/net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-ct.patch new file mode 100644 index 0000000000..82d05d339d --- /dev/null +++ b/queue-6.18/net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-ct.patch @@ -0,0 +1,44 @@ +From bc62e843bc48f933da765ce47079fd992e535794 Mon Sep 17 00:00:00 2001 +From: Ilya Maximets +Date: Mon, 27 Jul 2026 20:18:31 +0200 +Subject: net: openvswitch: fix skb leak on flow key update failure during ct + +From: Ilya Maximets + +commit bc62e843bc48f933da765ce47079fd992e535794 upstream. + +ovs_ct_execute() always steals or frees the skb on failure while +ovs_flow_key_update() does not. So, if it fails and we return right +away, the skb ends up leaked. + +Fix that by breaking instead and letting the common error handling +code at the bottom of the loop to free the skb properly. + +This is a very unlikely scenario as it requires the packet to become +unparseable by applying a set of actions on a previously parseable skb, +but should be fixed nevertheless. + +Reported by Sashiko. + +Fixes: ec0d043d05e6 ("openvswitch: Ensure flow is valid before executing ct") +Cc: stable@vger.kernel.org +Signed-off-by: Ilya Maximets +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20260727181851.306076-3-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/openvswitch/actions.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -1379,7 +1379,7 @@ static int do_execute_actions(struct dat + if (!is_flow_key_valid(key)) { + err = ovs_flow_key_update(skb, key); + if (err) +- return err; ++ break; + } + + err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key, diff --git a/queue-6.18/net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-recirculation.patch b/queue-6.18/net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-recirculation.patch new file mode 100644 index 0000000000..89e1d2dab8 --- /dev/null +++ b/queue-6.18/net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-recirculation.patch @@ -0,0 +1,58 @@ +From e1cf066244dad576221b7123a0e5005967f25a20 Mon Sep 17 00:00:00 2001 +From: Ilya Maximets +Date: Mon, 27 Jul 2026 20:18:30 +0200 +Subject: net: openvswitch: fix skb leak on flow key update failure during recirculation + +From: Ilya Maximets + +commit e1cf066244dad576221b7123a0e5005967f25a20 upstream. + +do_execute_actions() returns right away when execute_recirc() fails on +the last action as it assumes this function always takes ownership of +the skb when 'last' is true. But when the flow key update fails, the +function doesn't free the skb and it ends up leaked. + +This is a very unlikely scenario as it requires the packet to become +unparseable by applying a set of actions on a previously parseable skb, +but should be fixed nevertheless. + +Reported by Sashiko. + +Fixes: 971427f353f3 ("openvswitch: Add recirc and hash action.") +Cc: stable@vger.kernel.org +Signed-off-by: Ilya Maximets +Reviewed-by: Aaron Conole +Link: https://patch.msgid.link/20260727181851.306076-2-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/openvswitch/actions.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -1107,6 +1107,10 @@ static int execute_masked_set_action(str + return err; + } + ++/* When 'last' is true, recirc() should always consume the 'skb'. ++ * Otherwise, recirc() should keep 'skb' intact regardless what ++ * actions are executed on recirculation. ++ */ + static int execute_recirc(struct datapath *dp, struct sk_buff *skb, + struct sw_flow_key *key, + const struct nlattr *a, bool last) +@@ -1117,8 +1121,12 @@ static int execute_recirc(struct datapat + int err; + + err = ovs_flow_key_update(skb, key); +- if (err) ++ if (err) { ++ if (last) ++ ovs_kfree_skb_reason(skb, ++ OVS_DROP_ACTION_ERROR); + return err; ++ } + } + BUG_ON(!is_flow_key_valid(key)); + diff --git a/queue-6.18/net-pktgen-fix-proc-entry-use-after-free.patch b/queue-6.18/net-pktgen-fix-proc-entry-use-after-free.patch new file mode 100644 index 0000000000..cb694f6671 --- /dev/null +++ b/queue-6.18/net-pktgen-fix-proc-entry-use-after-free.patch @@ -0,0 +1,79 @@ +From 817ff6efdb7f484ea547218e11e17d8e43daa3b4 Mon Sep 17 00:00:00 2001 +From: Chengfeng Ye +Date: Sun, 19 Jul 2026 22:57:40 +0800 +Subject: net: pktgen: fix proc entry use-after-free + +From: Chengfeng Ye + +commit 817ff6efdb7f484ea547218e11e17d8e43daa3b4 upstream. + +pktgen_change_name() replaces pkt_dev->entry while holding t->if_lock. +pktgen_remove_device() removes the same entry before +_rem_dev_from_if_list() takes that lock. + +This allows the following interleaving: + + CPU 0 (NETDEV_CHANGENAME) CPU 1 (kpktgend) + if_lock(t) + proc_remove(pkt_dev->entry) + proc_remove(pkt_dev->entry) + pkt_dev->entry = proc_create_data(...) + if_unlock(t) + +The kthread can pass the stale proc_dir_entry to proc_remove() after the +rename path has freed it. A reproducer with a widened race window reports: + + BUG: KASAN: slab-use-after-free in proc_remove+0x78/0x80 + Read of size 8 at addr ffff8881478fea70 by task kpktgend_0/67 + Call Trace: + proc_remove+0x78/0x80 + pktgen_remove_device.isra.0+0x11c/0x4c0 + pktgen_thread_worker+0x1214/0x6bc0 + kthread+0x2c6/0x3b0 + Allocated by task 95: + __proc_create+0x204/0x790 + proc_create_data+0x72/0xe0 + pktgen_thread_write+0xd61/0x1510 + Freed by task 28: + kmem_cache_free+0xcb/0x3d0 + proc_free_inode+0x5b/0x80 + rcu_core+0x50a/0x1850 + The buggy address belongs to the object at ffff8881478fea00 + which belongs to the cache proc_dir_entry of size 192 + +Move proc_remove() into the if_lock-protected list removal helper. Keep it +before list_del_rcu() to preserve the ordering required by add_device(). +The rename path must then finish replacing the entry before removal, or +it observes that the device is no longer on the list. + +Fixes: 39df232f1a9b ("[PKTGEN]: fix device name handling") +Cc: stable@vger.kernel.org +Signed-off-by: Chengfeng Ye +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260719145740.2888967-1-nicoyip.dev@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/core/pktgen.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -3971,6 +3971,7 @@ static void _rem_dev_from_if_list(struct + struct pktgen_dev *p; + + if_lock(t); ++ proc_remove(pkt_dev->entry); + list_for_each_safe(q, n, &t->if_list) { + p = list_entry(q, struct pktgen_dev, list); + if (p == pkt_dev) +@@ -4000,9 +4001,6 @@ static int pktgen_remove_device(struct p + * list to determine if interface already exist, avoid race + * with proc_create_data() + */ +- proc_remove(pkt_dev->entry); +- +- /* And update the thread if_list */ + _rem_dev_from_if_list(t, pkt_dev); + + #ifdef CONFIG_XFRM diff --git a/queue-6.18/phy-zynqmp-fix-l0_tm_disable_scramble_encoder-mask.patch b/queue-6.18/phy-zynqmp-fix-l0_tm_disable_scramble_encoder-mask.patch new file mode 100644 index 0000000000..0fe9349d25 --- /dev/null +++ b/queue-6.18/phy-zynqmp-fix-l0_tm_disable_scramble_encoder-mask.patch @@ -0,0 +1,40 @@ +From 6cb22477929489a412df8d153e550e77a012e701 Mon Sep 17 00:00:00 2001 +From: Nava kishore Manne +Date: Sat, 27 Jun 2026 21:22:27 +0530 +Subject: phy: zynqmp: fix L0_TM_DISABLE_SCRAMBLE_ENCODER mask + +From: Nava kishore Manne + +commit 6cb22477929489a412df8d153e550e77a012e701 upstream. + +The L0_TX_DIG_61 register bit 2 is a reserved read-only field. +The previous mask value 0x0f incorrectly included bit 2, causing +unintended writes to a reserved bit on every scrambler bypass +operation. + +Correct the mask to (BIT(3) | GENMASK(1, 0)) to cover only the +valid scramble bypass control bits. + +Fixes: 4a33bea00314 ("phy: zynqmp: Add PHY driver for the Xilinx ZynqMP Gigabit Transceiver") +Cc: stable@vger.kernel.org +Signed-off-by: Nava kishore Manne +Signed-off-by: Radhey Shyam Pandey +Acked-by: Michal Simek +Link: https://patch.msgid.link/20260627155229.2791113-2-radhey.shyam.pandey@amd.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/phy/xilinx/phy-zynqmp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/phy/xilinx/phy-zynqmp.c ++++ b/drivers/phy/xilinx/phy-zynqmp.c +@@ -53,7 +53,7 @@ + #define L0_TM_DIG_6 0x106c + #define L0_TM_DIS_DESCRAMBLE_DECODER 0x0f + #define L0_TX_DIG_61 0x00f4 +-#define L0_TM_DISABLE_SCRAMBLE_ENCODER 0x0f ++#define L0_TM_DISABLE_SCRAMBLE_ENCODER (BIT(3) | GENMASK(1, 0)) + + /* PLL Test Mode register parameters */ + #define L0_TM_PLL_DIG_37 0x2094 diff --git a/queue-6.18/phy-zynqmp-keep-serdes-scrambler-and-8b-10b-enabled-for-usb.patch b/queue-6.18/phy-zynqmp-keep-serdes-scrambler-and-8b-10b-enabled-for-usb.patch new file mode 100644 index 0000000000..eded934ff8 --- /dev/null +++ b/queue-6.18/phy-zynqmp-keep-serdes-scrambler-and-8b-10b-enabled-for-usb.patch @@ -0,0 +1,98 @@ +From 7eb61caf45607e1e1270f51f8f93f0ded53146da Mon Sep 17 00:00:00 2001 +From: Nava kishore Manne +Date: Sat, 27 Jun 2026 21:22:29 +0530 +Subject: phy: zynqmp: keep SERDES scrambler and 8b/10b enabled for USB + +From: Nava kishore Manne + +commit 7eb61caf45607e1e1270f51f8f93f0ded53146da upstream. + +USB Gen1 requires scrambling and 8b/10b encoding to be performed in the +physical layer. Do not bypass PHY-side scrambler or encoder/decoder for +USB operation, as mandated by the USB 3.x specification. + +Scrambler and 8b/10b bypass remain restricted to SATA and SGMII +modes, where encoding is handled in the controller. + +Fixes: 4a33bea00314 ("phy: zynqmp: Add PHY driver for the Xilinx ZynqMP Gigabit Transceiver") +Cc: stable@vger.kernel.org +Signed-off-by: Nava kishore Manne +Signed-off-by: Radhey Shyam Pandey +Acked-by: Michal Simek +Link: https://patch.msgid.link/20260627155229.2791113-4-radhey.shyam.pandey@amd.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/phy/xilinx/phy-zynqmp.c | 39 +++++++++++++++++++++++++++++---------- + 1 file changed, 29 insertions(+), 10 deletions(-) + +--- a/drivers/phy/xilinx/phy-zynqmp.c ++++ b/drivers/phy/xilinx/phy-zynqmp.c +@@ -502,15 +502,30 @@ static void xpsgtr_lane_set_protocol(str + } + } + +-/* Bypass (de)scrambler and 8b/10b decoder and encoder. */ +-static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy) ++/** ++ * xpsgtr_bypass_scrambler_8b10b - Configure scrambler/encoder behavior ++ * @gtr_phy: pointer to lane context ++ * @bypass: true to enable scrambler/encoder bypass (SATA/SGMII), ++ * false to disable scrambler/encoder bypass (USB3) ++ * ++ * Uses RMW to preserve reserved and unrelated register fields. ++ */ ++static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy, ++ bool bypass) + { +- xpsgtr_clr_set_phy(gtr_phy, L0_TM_DIG_6, +- L0_TM_DIS_DESCRAMBLE_DECODER, +- L0_TM_DIS_DESCRAMBLE_DECODER); +- xpsgtr_clr_set_phy(gtr_phy, L0_TX_DIG_61, +- L0_TM_DISABLE_SCRAMBLE_ENCODER, +- L0_TM_DISABLE_SCRAMBLE_ENCODER); ++ if (bypass) { ++ xpsgtr_clr_set_phy(gtr_phy, L0_TM_DIG_6, ++ L0_TM_DIS_DESCRAMBLE_DECODER, ++ L0_TM_DIS_DESCRAMBLE_DECODER); ++ xpsgtr_clr_set_phy(gtr_phy, L0_TX_DIG_61, ++ L0_TM_DISABLE_SCRAMBLE_ENCODER, ++ L0_TM_DISABLE_SCRAMBLE_ENCODER); ++ } else { ++ xpsgtr_clr_set_phy(gtr_phy, L0_TM_DIG_6, ++ L0_TM_DIS_DESCRAMBLE_DECODER, 0); ++ xpsgtr_clr_set_phy(gtr_phy, L0_TX_DIG_61, ++ L0_TM_DISABLE_SCRAMBLE_ENCODER, 0); ++ } + } + + /* DP-specific initialization. */ +@@ -531,7 +546,7 @@ static void xpsgtr_phy_init_sata(struct + { + struct xpsgtr_dev *gtr_dev = gtr_phy->dev; + +- xpsgtr_bypass_scrambler_8b10b(gtr_phy); ++ xpsgtr_bypass_scrambler_8b10b(gtr_phy, true); + + writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET); + } +@@ -547,7 +562,7 @@ static void xpsgtr_phy_init_sgmii(struct + xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, mask, val); + xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, mask, val); + +- xpsgtr_bypass_scrambler_8b10b(gtr_phy); ++ xpsgtr_bypass_scrambler_8b10b(gtr_phy, true); + } + + /* Configure TX de-emphasis and margining for DP. */ +@@ -708,6 +723,10 @@ static int xpsgtr_phy_init(struct phy *p + case ICM_PROTOCOL_SGMII: + xpsgtr_phy_init_sgmii(gtr_phy); + break; ++ ++ case ICM_PROTOCOL_USB: ++ xpsgtr_bypass_scrambler_8b10b(gtr_phy, false); ++ break; + } + + goto out; diff --git a/queue-6.18/phy-zynqmp-use-read-modify-write-for-serdes-scrambler-bypass.patch b/queue-6.18/phy-zynqmp-use-read-modify-write-for-serdes-scrambler-bypass.patch new file mode 100644 index 0000000000..41d9da75c5 --- /dev/null +++ b/queue-6.18/phy-zynqmp-use-read-modify-write-for-serdes-scrambler-bypass.patch @@ -0,0 +1,45 @@ +From 21e0749f931702765b9d52d05740092bc87fcd8d Mon Sep 17 00:00:00 2001 +From: Nava kishore Manne +Date: Sat, 27 Jun 2026 21:22:28 +0530 +Subject: phy: zynqmp: use read-modify-write for SERDES scrambler bypass + +From: Nava kishore Manne + +commit 21e0749f931702765b9d52d05740092bc87fcd8d upstream. + +xpsgtr_bypass_scrambler_8b10b() used xpsgtr_write_phy() which performs +a full register write, silently clearing any bits beyond the intended +bypass control fields. + +Switch to xpsgtr_clr_set_phy() with clr=mask, set=mask to set only +the bypass bits while preserving the remaining bits in each register. + +Fixes: 4a33bea00314 ("phy: zynqmp: Add PHY driver for the Xilinx ZynqMP Gigabit Transceiver") +Cc: stable@vger.kernel.org +Signed-off-by: Nava kishore Manne +Signed-off-by: Radhey Shyam Pandey +Acked-by: Michal Simek +Link: https://patch.msgid.link/20260627155229.2791113-3-radhey.shyam.pandey@amd.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/phy/xilinx/phy-zynqmp.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/phy/xilinx/phy-zynqmp.c ++++ b/drivers/phy/xilinx/phy-zynqmp.c +@@ -505,8 +505,12 @@ static void xpsgtr_lane_set_protocol(str + /* Bypass (de)scrambler and 8b/10b decoder and encoder. */ + static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy) + { +- xpsgtr_write_phy(gtr_phy, L0_TM_DIG_6, L0_TM_DIS_DESCRAMBLE_DECODER); +- xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61, L0_TM_DISABLE_SCRAMBLE_ENCODER); ++ xpsgtr_clr_set_phy(gtr_phy, L0_TM_DIG_6, ++ L0_TM_DIS_DESCRAMBLE_DECODER, ++ L0_TM_DIS_DESCRAMBLE_DECODER); ++ xpsgtr_clr_set_phy(gtr_phy, L0_TX_DIG_61, ++ L0_TM_DISABLE_SCRAMBLE_ENCODER, ++ L0_TM_DISABLE_SCRAMBLE_ENCODER); + } + + /* DP-specific initialization. */ diff --git a/queue-6.18/power-supply-bq25890-fix-the-10-c-ntc-lookup-entry.patch b/queue-6.18/power-supply-bq25890-fix-the-10-c-ntc-lookup-entry.patch new file mode 100644 index 0000000000..1d6e52e48f --- /dev/null +++ b/queue-6.18/power-supply-bq25890-fix-the-10-c-ntc-lookup-entry.patch @@ -0,0 +1,38 @@ +From 160a783aa65b74782bc17cb874af1a6d3f5fba3c Mon Sep 17 00:00:00 2001 +From: Xu Rao +Date: Thu, 23 Jul 2026 14:54:44 +0800 +Subject: power: supply: bq25890: fix the -10 C NTC lookup entry + +From: Xu Rao + +commit 160a783aa65b74782bc17cb874af1a6d3f5fba3c upstream. + +The TSPCT lookup table is monotonically decreasing except for ADC code +121, where the sequence reads -9.0 C, -1.0 C, -12.0 C. This makes the +reported battery temperature jump upward by eight degrees for one code +and then downward by eleven degrees for the next code. + +The entry is a missing zero: use -10.0 C so the sequence remains +monotonic between -9.0 C and -12.0 C. + +Fixes: 9652c02428f3 ("power: bq25890: add POWER_SUPPLY_PROP_TEMP") +Cc: stable@vger.kernel.org +Signed-off-by: Xu Rao +Link: https://patch.msgid.link/0619C8BF15F43B7C+20260723065444.1796002-1-raoxu@uniontech.com +Signed-off-by: Sebastian Reichel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/supply/bq25890_charger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/power/supply/bq25890_charger.c ++++ b/drivers/power/supply/bq25890_charger.c +@@ -320,7 +320,7 @@ static const u32 bq25890_tspct_tbl[] = { + 145, 140, 130, 120, 115, 110, 100, 90, + 80, 70, 60, 50, 40, 30, 20, 10, + 0, -10, -20, -30, -40, -60, -70, -80, +- -90, -10, -120, -140, -150, -170, -190, -210, ++ -90, -100, -120, -140, -150, -170, -190, -210, + }; + + #define BQ25890_TSPCT_TBL_SIZE ARRAY_SIZE(bq25890_tspct_tbl) diff --git a/queue-6.18/power-supply-max17040-handle-missing-status-supplier.patch b/queue-6.18/power-supply-max17040-handle-missing-status-supplier.patch new file mode 100644 index 0000000000..8f409a0dd0 --- /dev/null +++ b/queue-6.18/power-supply-max17040-handle-missing-status-supplier.patch @@ -0,0 +1,47 @@ +From 725668c6b6aa3971fe850659102c250d0d676e18 Mon Sep 17 00:00:00 2001 +From: Jianing Li +Date: Wed, 1 Jul 2026 14:10:42 +0800 +Subject: power: supply: max17040: handle missing status supplier + +From: Jianing Li + +commit 725668c6b6aa3971fe850659102c250d0d676e18 upstream. + +MAX17040 does not report charger state itself, so the driver forwards +POWER_SUPPLY_PROP_STATUS to a supplier power supply. If no supplier is +registered, power_supply_get_property_from_supplier() returns -ENODEV and +leaves the output value untouched. + +max17040_get_property() currently ignores that error and returns success, +so userspace can read an uninitialized status value from the battery power +supply. This happens on systems that use the fuel gauge without a charger +supplier relationship in firmware. + +Return POWER_SUPPLY_STATUS_UNKNOWN when no supplier provides STATUS, and +propagate other supplier lookup errors. + +Fixes: f4b782af61ae ("power: max17040: pass status property from supplier") +Cc: stable@vger.kernel.org # 6.7+ +Signed-off-by: Jianing Li +Link: https://patch.msgid.link/20260701061042.1008-1-m13940358460@163.com +Signed-off-by: Sebastian Reichel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/supply/max17040_battery.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/power/supply/max17040_battery.c ++++ b/drivers/power/supply/max17040_battery.c +@@ -405,7 +405,11 @@ static int max17040_get_property(struct + val->intval = chip->low_soc_alert; + break; + case POWER_SUPPLY_PROP_STATUS: +- power_supply_get_property_from_supplier(psy, psp, val); ++ ret = power_supply_get_property_from_supplier(psy, psp, val); ++ if (ret == -ENODEV) ++ val->intval = POWER_SUPPLY_STATUS_UNKNOWN; ++ else if (ret) ++ return ret; + break; + case POWER_SUPPLY_PROP_TEMP: + if (!chip->channel_temp) diff --git a/queue-6.18/powerpc-ps3-fix-map-failure-path-in-dma_ioc0_map_pages.patch b/queue-6.18/powerpc-ps3-fix-map-failure-path-in-dma_ioc0_map_pages.patch new file mode 100644 index 0000000000..0a64583c1f --- /dev/null +++ b/queue-6.18/powerpc-ps3-fix-map-failure-path-in-dma_ioc0_map_pages.patch @@ -0,0 +1,38 @@ +From 0bb024f11d120abff3e8db9144a585b9d7fb8459 Mon Sep 17 00:00:00 2001 +From: Thorsten Blum +Date: Sat, 11 Jul 2026 15:09:32 +0200 +Subject: powerpc/ps3: Fix map failure path in dma_ioc0_map_pages() + +From: Thorsten Blum + +commit 0bb024f11d120abff3e8db9144a585b9d7fb8459 upstream. + +If lv1_put_iopte() fails in dma_ioc0_map_pages(), the error path +decrements iopage but keeps using the failed mapping's offset. As a +result, it repeatedly tries to invalidate the failed IOPTE slot and +leaves the already installed IOPTEs valid. + +Recompute offset and invalidate the installed IOPTEs instead. + +Fixes: 6bb5cf102541 ("[POWERPC] PS3: System-bus rework") +Cc: stable@vger.kernel.org +Signed-off-by: Thorsten Blum +Reviewed-by: Ritesh Harjani (IBM) +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260711130931.740719-3-thorsten.blum@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/ps3/mm.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/powerpc/platforms/ps3/mm.c ++++ b/arch/powerpc/platforms/ps3/mm.c +@@ -615,6 +615,7 @@ static int dma_ioc0_map_pages(struct ps3 + + fail_map: + for (iopage--; 0 <= iopage; iopage--) { ++ offset = (1 << r->page_size) * iopage; + lv1_put_iopte(0, + c->bus_addr + offset, + c->lpar_addr + offset, diff --git a/queue-6.18/s390-dasd-fix-potential-null-pointer-dereference.patch b/queue-6.18/s390-dasd-fix-potential-null-pointer-dereference.patch new file mode 100644 index 0000000000..816b61b6ea --- /dev/null +++ b/queue-6.18/s390-dasd-fix-potential-null-pointer-dereference.patch @@ -0,0 +1,47 @@ +From 9973026f572db6b67570cadc30942f3014e41079 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan=20H=C3=B6ppner?= +Date: Mon, 27 Jul 2026 16:28:39 +0200 +Subject: s390/dasd: Fix potential NULL pointer dereference +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jan Höppner + +commit 9973026f572db6b67570cadc30942f3014e41079 upstream. + +dasd_release_space() checks the implementation of the is_ese() +discipline function before calling it to determine if a given device is +an ESE DASD. + +The current usage of the logical AND operator will lead to a NULL +pointer dereference as the function is called even if the function +pointer is NULL. + +Fix this by using the logical OR operator. + +Fixes: 91dc4a197569 ("s390/dasd: Add new ioctl to release space") +Cc: stable@vger.kernel.org # v5.3+ +Reported-by: Vasily Gorbik +Acked-by: Eduard Shishkin +Reviewed-by: Stefan Haberland +Signed-off-by: Jan Höppner +Signed-off-by: Stefan Haberland +Link: https://patch.msgid.link/20260727142840.567286-3-sth@linux.ibm.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/block/dasd_ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/s390/block/dasd_ioctl.c ++++ b/drivers/s390/block/dasd_ioctl.c +@@ -325,7 +325,7 @@ out_err: + static int dasd_release_space(struct dasd_device *device, + struct format_data_t *rdata) + { +- if (!device->discipline->is_ese && !device->discipline->is_ese(device)) ++ if (!device->discipline->is_ese || !device->discipline->is_ese(device)) + return -ENOTSUPP; + if (!device->discipline->release_space) + return -ENOTSUPP; diff --git a/queue-6.18/s390-dasd-fix-undersized-format-check-buffer.patch b/queue-6.18/s390-dasd-fix-undersized-format-check-buffer.patch new file mode 100644 index 0000000000..a27cab4583 --- /dev/null +++ b/queue-6.18/s390-dasd-fix-undersized-format-check-buffer.patch @@ -0,0 +1,78 @@ +From 7f40b346462f563a0d6e841a77b5163d2a882a04 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Mon, 27 Jul 2026 16:28:40 +0200 +Subject: s390/dasd: Fix undersized format-check buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stefan Haberland + +commit 7f40b346462f563a0d6e841a77b5163d2a882a04 upstream. + +fmt_buffer_size in dasd_eckd_check_device_format() is declared as +int, even though one of the multiplicands, sizeof(struct eckd_count), +is a size_t. The expression + + trkcount * rpt_max * sizeof(struct eckd_count) + +is therefore correctly evaluated at 64-bit width, but the result is +silently truncated when it is stored back into the 32-bit +fmt_buffer_size variable. For a sufficiently large track range +(start_unit/stop_unit are caller-controlled) this truncation +yields a buffer size far smaller than the number of tracks actually +requested. kzalloc() then succeeds with an undersized allocation, +while the subsequent channel program build still operates on the +untruncated track count and writes past the end of that buffer. + +Compute the buffer size with check_mul_overflow() and keep it in a +size_t, so that a value that no longer fits results in -EINVAL +instead of a silently truncated allocation size. + +Fixes: 8fd575200db5 ("s390/dasd: Add new ioctl BIODASDCHECKFMT") +Cc: stable@vger.kernel.org #4.7 +Reviewed-by: Jan Höppner +Signed-off-by: Stefan Haberland +Link: https://patch.msgid.link/20260727142840.567286-4-sth@linux.ibm.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/block/dasd_eckd.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/s390/block/dasd_eckd.c ++++ b/drivers/s390/block/dasd_eckd.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -3476,11 +3477,11 @@ static int dasd_eckd_check_device_format + { + struct dasd_eckd_private *private = base->private; + struct eckd_count *fmt_buffer; +- struct irb irb; ++ size_t fmt_buffer_size; ++ unsigned int trkcount; + int rpt_max, rpt_exp; +- int fmt_buffer_size; ++ struct irb irb; + int trk_per_cyl; +- int trkcount; + int tpm = 0; + int rc; + +@@ -3491,7 +3492,9 @@ static int dasd_eckd_check_device_format + rpt_exp = recs_per_track(&private->rdc_data, 0, cdata->expect.blksize); + + trkcount = cdata->expect.stop_unit - cdata->expect.start_unit + 1; +- fmt_buffer_size = trkcount * rpt_max * sizeof(struct eckd_count); ++ if (check_mul_overflow(trkcount, rpt_max, &fmt_buffer_size) || ++ check_mul_overflow(fmt_buffer_size, sizeof(struct eckd_count), &fmt_buffer_size)) ++ return -EINVAL; + + fmt_buffer = kzalloc(fmt_buffer_size, GFP_KERNEL | GFP_DMA); + if (!fmt_buffer) diff --git a/queue-6.18/s390-pci-fix-s390_pci_mmio_write-syscall-error-return-without-mio.patch b/queue-6.18/s390-pci-fix-s390_pci_mmio_write-syscall-error-return-without-mio.patch new file mode 100644 index 0000000000..eb9dadedfd --- /dev/null +++ b/queue-6.18/s390-pci-fix-s390_pci_mmio_write-syscall-error-return-without-mio.patch @@ -0,0 +1,41 @@ +From b7ab86bdc65eadcfc43a0e3faf682a3f750cfb96 Mon Sep 17 00:00:00 2001 +From: Niklas Schnelle +Date: Wed, 22 Jul 2026 15:08:34 +0200 +Subject: s390/pci: Fix s390_pci_mmio_write syscall error return without MIO + +From: Niklas Schnelle + +commit b7ab86bdc65eadcfc43a0e3faf682a3f750cfb96 upstream. + +On a machine without PCI memory-I/O (MIO) support or when running with +pci=nomio the s390 specific PCI MMIO write syscall checks if the MMIO +cookie is above ZPCI_IOMAP_ADDR_BASE as a sanity check before even +trying to perform the MMIO. If this check fails the return value was +left unchanged and thus 0 from prior operations falsely indicating +success. This could potentially confuse user-space into falsely +believing the MMIO, on a mapping not valid for MMIO was successful. + +Fix this by setting the return value to -EFAULT prior to the check +following the same pattern as elsewhere in the same function. + +Cc: stable@vger.kernel.org +Reviewed-by: Julian Ruess +Reviewed-by: Farhan Ali +Fixes: a67a88b0b8de ("s390/pci: remove races against pte updates") +Signed-off-by: Niklas Schnelle +Signed-off-by: Vasily Gorbik +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/pci/pci_mmio.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/s390/pci/pci_mmio.c ++++ b/arch/s390/pci/pci_mmio.c +@@ -188,6 +188,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, uns + goto out_unlock_mmap; + } + ++ ret = -EFAULT; + io_addr = (void __iomem *)((args.pfn << PAGE_SHIFT) | + (mmio_addr & ~PAGE_MASK)); + diff --git a/queue-6.18/s390-qeth-check-cap_net_admin-for-private-ioctls.patch b/queue-6.18/s390-qeth-check-cap_net_admin-for-private-ioctls.patch new file mode 100644 index 0000000000..cd20c04ccf --- /dev/null +++ b/queue-6.18/s390-qeth-check-cap_net_admin-for-private-ioctls.patch @@ -0,0 +1,38 @@ +From d211028bac1bd0fff0026bfa2a8328e5b78cd0e6 Mon Sep 17 00:00:00 2001 +From: Aswin Karuvally +Date: Thu, 23 Jul 2026 16:00:50 +0200 +Subject: s390/qeth: Check CAP_NET_ADMIN for private ioctls + +From: Aswin Karuvally + +commit d211028bac1bd0fff0026bfa2a8328e5b78cd0e6 upstream. + +Gate the SIOCDEVPRIVATE ioctl commands SIOC_QETH_ADP_SET_SNMP_CONTROL, +SIOC_QETH_GET_CARD_TYPE and SIOC_QETH_QUERY_OAT with CAP_NET_ADMIN +capable check to ensure unprivileged users cannot invoke them. + +Fixes: 18787eeebd71 ("qeth: use ndo_siocdevprivate") +Cc: stable@vger.kernel.org +Suggested-by: Christian Borntraeger +Reviewed-by: Christian Borntraeger +Reviewed-by: Alexandra Winter +Signed-off-by: Aswin Karuvally +Link: https://patch.msgid.link/20260723140050.762991-1-aswin@linux.ibm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/net/qeth_core_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -6528,6 +6528,9 @@ int qeth_siocdevprivate(struct net_devic + struct qeth_card *card = dev->ml_priv; + int rc = 0; + ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ + switch (cmd) { + case SIOC_QETH_ADP_SET_SNMP_CONTROL: + rc = qeth_snmp_command(card, data); diff --git a/queue-6.18/s390-zcrypt-fix-buffer-over-read-in-cca_cipher2protkey.patch b/queue-6.18/s390-zcrypt-fix-buffer-over-read-in-cca_cipher2protkey.patch new file mode 100644 index 0000000000..cc8c735397 --- /dev/null +++ b/queue-6.18/s390-zcrypt-fix-buffer-over-read-in-cca_cipher2protkey.patch @@ -0,0 +1,260 @@ +From 36b230835b8a008266aad22168ca52afacc8a58d Mon Sep 17 00:00:00 2001 +From: Harald Freudenberger +Date: Wed, 29 Jul 2026 13:40:09 +0200 +Subject: s390/zcrypt: Fix buffer over-read in cca_cipher2protkey + +From: Harald Freudenberger + +commit 36b230835b8a008266aad22168ca52afacc8a58d upstream. + +Add validation of both the actual key buffer size and token length +fields in all the cca_check_sec*token() functions. Additionally check +in cca_gencipherkey() for possible underflow with returned key size. + +The CCA token structures contain user-controlled len fields that +were used in operations without proper validation against both the +actual buffer size and minimum token structure size. An attacker +could set this field larger than the actual buffer size, leading to +reading beyond buffer boundaries. This may result in a kernel crash or +exposure of memory via sending this as part of a request down to the +crypto card. Also an attacker could have used a very small len value +and thus enforce a buffer under-run which may produce similar effects +as a over-read. + +So now a key must +- key buf length must be at least sizeof the token struct +- the key len field inside the token must fit into the range of + sizeof key token struct ... key buf length + +Fixes: 4bc123b18ce6 ("s390/zcrypt: Add low level functions for CCA AES cipher keys") +Cc: stable@vger.kernel.org +Reviewed-by: Ingo Franzki +Signed-off-by: Harald Freudenberger +Signed-off-by: Vasily Gorbik +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/crypto/pkey_cca.c | 15 ++------ + drivers/s390/crypto/zcrypt_ccamisc.c | 64 +++++++++++++++++++++++++++++------ + drivers/s390/crypto/zcrypt_ccamisc.h | 6 +-- + 3 files changed, 62 insertions(+), 23 deletions(-) + +--- a/drivers/s390/crypto/pkey_cca.c ++++ b/drivers/s390/crypto/pkey_cca.c +@@ -233,22 +233,16 @@ static int cca_key2protkey(const struct + if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_AES) { + /* CCA AES data key */ +- if (keylen < sizeof(struct secaeskeytoken)) +- return -EINVAL; +- if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0)) ++ if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, keylen, 0)) + return -EINVAL; + } else if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_VLSC) { + /* CCA AES cipher key */ +- if (keylen < hdr->len) +- return -EINVAL; + if (cca_check_secaescipherkey(pkey_dbf_info, +- 3, key, 0, 1)) ++ 3, key, keylen, 0, 1)) + return -EINVAL; + } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { + /* CCA ECC (private) key */ +- if (keylen < sizeof(struct eccprivkeytoken)) +- return -EINVAL; + if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1)) + return -EINVAL; + } else { +@@ -476,7 +470,7 @@ static int cca_verifykey(const u8 *key, + hdr->version == TOKVER_CCA_AES) { + struct secaeskeytoken *t = (struct secaeskeytoken *)key; + +- rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0); ++ rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, keylen, 0); + if (rc) + goto out; + *keytype = PKEY_TYPE_CCA_DATA; +@@ -504,7 +498,8 @@ static int cca_verifykey(const u8 *key, + hdr->version == TOKVER_CCA_VLSC) { + struct cipherkeytoken *t = (struct cipherkeytoken *)key; + +- rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1); ++ rc = cca_check_secaescipherkey(pkey_dbf_info, 3, ++ key, keylen, 0, 1); + if (rc) + goto out; + *keytype = PKEY_TYPE_CCA_CIPHER; +--- a/drivers/s390/crypto/zcrypt_ccamisc.c ++++ b/drivers/s390/crypto/zcrypt_ccamisc.c +@@ -63,12 +63,18 @@ static DEFINE_MUTEX(dev_status_mem_mutex + * also checked. Returns 0 on success or errno value on failure. + */ + int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, +- const u8 *token, int keybitsize) ++ const u8 *token, u32 keysize, int keybitsize) + { + struct secaeskeytoken *t = (struct secaeskeytoken *)token; + + #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) + ++ if (keysize < sizeof(*t)) { ++ if (dbg) ++ DBF("%s keysize %u < min token size %zu\n", ++ __func__, keysize, sizeof(*t)); ++ return -EINVAL; ++ } + if (t->type != TOKTYPE_CCA_INTERNAL) { + if (dbg) + DBF("%s token check failed, type 0x%02x != 0x%02x\n", +@@ -102,14 +108,20 @@ EXPORT_SYMBOL(cca_check_secaeskeytoken); + * Returns 0 on success or errno value on failure. + */ + int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl, +- const u8 *token, int keybitsize, +- int checkcpacfexport) ++ const u8 *token, u32 keysize, ++ int keybitsize, int checkcpacfexport) + { + struct cipherkeytoken *t = (struct cipherkeytoken *)token; + bool keybitsizeok = true; + + #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) + ++ if (keysize < sizeof(*t)) { ++ if (dbg) ++ DBF("%s keysize %u < min token size %zu\n", ++ __func__, keysize, sizeof(*t)); ++ return -EINVAL; ++ } + if (t->type != TOKTYPE_CCA_INTERNAL) { + if (dbg) + DBF("%s token check failed, type 0x%02x != 0x%02x\n", +@@ -122,6 +134,18 @@ int cca_check_secaescipherkey(debug_info + __func__, (int)t->version, TOKVER_CCA_VLSC); + return -EINVAL; + } ++ if (t->len > keysize) { ++ if (dbg) ++ DBF("%s token check failed, len %d > keysize %u\n", ++ __func__, (int)t->len, keysize); ++ return -EINVAL; ++ } ++ if (t->len < sizeof(*t)) { ++ if (dbg) ++ DBF("%s token check failed, len %d < min token size %zu\n", ++ __func__, (int)t->len, sizeof(*t)); ++ return -EINVAL; ++ } + if (t->algtype != 0x02) { + if (dbg) + DBF("%s token check failed, algtype 0x%02x != 0x02\n", +@@ -196,6 +220,12 @@ int cca_check_sececckeytoken(debug_info_ + + #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) + ++ if (keysize < sizeof(*t)) { ++ if (dbg) ++ DBF("%s keysize %u < min token size %zu\n", ++ __func__, keysize, sizeof(*t)); ++ return -EINVAL; ++ } + if (t->type != TOKTYPE_CCA_INTERNAL_PKA) { + if (dbg) + DBF("%s token check failed, type 0x%02x != 0x%02x\n", +@@ -208,6 +238,12 @@ int cca_check_sececckeytoken(debug_info_ + __func__, (int)t->len, keysize); + return -EINVAL; + } ++ if (t->len < sizeof(*t)) { ++ if (dbg) ++ DBF("%s token check failed, len %d < min token size %zu\n", ++ __func__, (int)t->len, sizeof(*t)); ++ return -EINVAL; ++ } + if (t->secid != 0x20) { + if (dbg) + DBF("%s token check failed, secid 0x%02x != 0x20\n", +@@ -444,7 +480,8 @@ int cca_genseckey(u16 cardnr, u16 domain + + /* check secure key token */ + rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR, +- prepparm->lv3.keyblock.tok, 8 * keysize); ++ prepparm->lv3.keyblock.tok, ++ seckeysize, 8 * keysize); + if (rc) { + rc = -EIO; + goto out; +@@ -583,7 +620,8 @@ int cca_clr2seckey(u16 cardnr, u16 domai + + /* check secure key token */ + rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR, +- prepparm->lv3.keyblock.tok, 8 * keysize); ++ prepparm->lv3.keyblock.tok, ++ seckeysize, 8 * keysize); + if (rc) { + rc = -EIO; + goto out; +@@ -843,6 +881,7 @@ int cca_gencipherkey(u16 cardnr, u16 dom + } kb; + } __packed * prepparm; + struct cipherkeytoken *t; ++ u32 keybuflen; + + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, +@@ -937,23 +976,28 @@ int cca_gencipherkey(u16 cardnr, u16 dom + } + + /* and some checks on the generated key */ ++ t = (struct cipherkeytoken *)prepparm->kb.tlv1.gen_key; ++ if (prepparm->kb.tlv1.len < 2 * sizeof(uint16_t) + sizeof(*t)) { ++ rc = -EIO; ++ goto out; ++ } ++ keybuflen = prepparm->kb.tlv1.len - 2 * sizeof(uint16_t); + rc = cca_check_secaescipherkey(zcrypt_dbf_info, DBF_ERR, + prepparm->kb.tlv1.gen_key, +- keybitsize, 1); ++ keybuflen, keybitsize, 1); + if (rc) { + rc = -EIO; + goto out; + } + + /* copy the generated vlsc key token */ +- t = (struct cipherkeytoken *)prepparm->kb.tlv1.gen_key; + if (keybuf) { +- if (*keybufsize >= t->len) +- memcpy(keybuf, t, t->len); ++ if (*keybufsize >= keybuflen) ++ memcpy(keybuf, t, keybuflen); + else + rc = -EINVAL; + } +- *keybufsize = t->len; ++ *keybufsize = keybuflen; + + out: + free_cprbmem(mem, PARMBSIZE, false, xflags); +--- a/drivers/s390/crypto/zcrypt_ccamisc.h ++++ b/drivers/s390/crypto/zcrypt_ccamisc.h +@@ -136,7 +136,7 @@ struct eccprivkeytoken { + * also checked. Returns 0 on success or errno value on failure. + */ + int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, +- const u8 *token, int keybitsize); ++ const u8 *token, u32 keysize, int keybitsize); + + /* + * Simple check if the token is a valid CCA secure AES cipher key +@@ -146,8 +146,8 @@ int cca_check_secaeskeytoken(debug_info_ + * Returns 0 on success or errno value on failure. + */ + int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl, +- const u8 *token, int keybitsize, +- int checkcpacfexport); ++ const u8 *token, u32 keysize, ++ int keybitsize, int checkcpacfexport); + + /* + * Simple check if the token is a valid CCA secure ECC private diff --git a/queue-6.18/s390-zcrypt-fix-missing-mem-scrub-at-clear-key-import-in-cca_clr2cipherkey.patch b/queue-6.18/s390-zcrypt-fix-missing-mem-scrub-at-clear-key-import-in-cca_clr2cipherkey.patch new file mode 100644 index 0000000000..dd635b045e --- /dev/null +++ b/queue-6.18/s390-zcrypt-fix-missing-mem-scrub-at-clear-key-import-in-cca_clr2cipherkey.patch @@ -0,0 +1,105 @@ +From 01476391aecef36a3b789ee844357b22fbc90665 Mon Sep 17 00:00:00 2001 +From: Harald Freudenberger +Date: Wed, 29 Jul 2026 16:01:34 +0200 +Subject: s390/zcrypt: Fix missing mem scrub at clear key import in cca_clr2cipherkey() + +From: Harald Freudenberger + +commit 01476391aecef36a3b789ee844357b22fbc90665 upstream. + +The helper function _ip_cprb_helper() uses internal buffer memory for +building and processing CPRBs. After use this buffer was never +scrubbed which could lead to leaving for example clear key material in +memory which could be exposed via tricky reuse of this same memory. + +Extend the _ip_cprb_helper() function with another parameter 'scrub' +used to steer scrubbing of this buffer. So now the caller has the +opportunity to decide if scrubbing is needed or not. + +Extend the clear key to secure key token import process in function +cca_clr2cipherkey() to tell the helper function from above to scrub +the cprb buffer when the clear key value is part of the request data. + +Add explicit scrubbing on return from function cca_clr2cipherkey() for +the random EXOR buffer and the cprb buffer. + +Overall this cleans the internal used buffer in case of clear key +import to prevent sensitive data to get exposed. + +Fixes: 4bc123b18ce6 ("s390/zcrypt: Add low level functions for CCA AES cipher keys") +Cc: stable@vger.kernel.org +Reviewed-by: Holger Dengler +Signed-off-by: Harald Freudenberger +Signed-off-by: Vasily Gorbik +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/crypto/zcrypt_ccamisc.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/s390/crypto/zcrypt_ccamisc.c ++++ b/drivers/s390/crypto/zcrypt_ccamisc.c +@@ -1016,7 +1016,8 @@ static int _ip_cprb_helper(u16 cardnr, u + int clr_key_bit_size, + u8 *key_token, + int *key_token_size, +- u32 xflags) ++ u32 xflags, ++ bool scrub) + { + int rc, n; + u8 *mem, *ptr; +@@ -1156,7 +1157,7 @@ static int _ip_cprb_helper(u16 cardnr, u + *key_token_size = t->len; + + out: +- free_cprbmem(mem, PARMBSIZE, false, xflags); ++ free_cprbmem(mem, PARMBSIZE, scrub, xflags); + return rc; + } + +@@ -1207,28 +1208,32 @@ int cca_clr2cipherkey(u16 card, u16 dom, + * 4/4 COMPLETE the secure cipher key import + */ + rc = _ip_cprb_helper(card, dom, "AES ", "FIRST ", "MIN3PART", +- exorbuf, keybitsize, token, &tokensize, xflags); ++ exorbuf, keybitsize, token, &tokensize, ++ xflags, true); + if (rc) { + ZCRYPT_DBF_ERR("%s clear key import 1/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); + goto out; + } + rc = _ip_cprb_helper(card, dom, "AES ", "ADD-PART", NULL, +- clrkey, keybitsize, token, &tokensize, xflags); ++ clrkey, keybitsize, token, &tokensize, ++ xflags, true); + if (rc) { + ZCRYPT_DBF_ERR("%s clear key import 2/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); + goto out; + } + rc = _ip_cprb_helper(card, dom, "AES ", "ADD-PART", NULL, +- exorbuf, keybitsize, token, &tokensize, xflags); ++ exorbuf, keybitsize, token, &tokensize, ++ xflags, true); + if (rc) { + ZCRYPT_DBF_ERR("%s clear key import 3/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); + goto out; + } + rc = _ip_cprb_helper(card, dom, "AES ", "COMPLETE", NULL, +- NULL, keybitsize, token, &tokensize, xflags); ++ NULL, keybitsize, token, &tokensize, ++ xflags, true); + if (rc) { + ZCRYPT_DBF_ERR("%s clear key import 4/4 with CSNBKPI2 failed, rc=%d\n", + __func__, rc); +@@ -1245,6 +1250,8 @@ int cca_clr2cipherkey(u16 card, u16 dom, + *keybufsize = tokensize; + + out: ++ memzero_explicit(exorbuf, sizeof(exorbuf)); ++ memzero_explicit(mem, CPRB_MEMPOOL_ITEM_SIZE); + mempool_free(mem, cprb_mempool); + return rc; + } diff --git a/queue-6.18/s390-zcrypt-fix-wrong-domain-value-verification-with-ep11-cprbs.patch b/queue-6.18/s390-zcrypt-fix-wrong-domain-value-verification-with-ep11-cprbs.patch new file mode 100644 index 0000000000..05c050c428 --- /dev/null +++ b/queue-6.18/s390-zcrypt-fix-wrong-domain-value-verification-with-ep11-cprbs.patch @@ -0,0 +1,36 @@ +From 983279d7f86ade73db86f886e09172dd567031b5 Mon Sep 17 00:00:00 2001 +From: Harald Freudenberger +Date: Thu, 23 Jul 2026 11:54:52 +0200 +Subject: s390/zcrypt: Fix wrong domain value verification with EP11 CPRBs + +From: Harald Freudenberger + +commit 983279d7f86ade73db86f886e09172dd567031b5 upstream. + +There is a wrong upper limit check for the domain value when an EP11 +CPRB is processed for sending to a crypto card. This check is only +active on custom device nodes but may lead to access heap memory +behind perms->adm when an administrative CPRB is sent. +Add correct limit (AP_DOMAINS = 256) checking to fix this. + +Fixes: cfd68b33094e ("s390/zcrypt: Filter admin CPRBs on custom devices") +Cc: stable@vger.kernel.org +Reviewed-by: Finn Callies +Signed-off-by: Harald Freudenberger +Signed-off-by: Vasily Gorbik +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/crypto/zcrypt_api.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/s390/crypto/zcrypt_api.c ++++ b/drivers/s390/crypto/zcrypt_api.c +@@ -1083,7 +1083,7 @@ static long _zcrypt_send_ep11_cprb(u32 x + print_hex_dump_debug("ep11req: ", DUMP_PREFIX_ADDRESS, 16, 1, + ap_msg.msg, ap_msg.len, false); + +- if (perms != &ap_perms && domain < AUTOSEL_DOM) { ++ if (perms != &ap_perms && domain < AP_DOMAINS) { + if (ap_msg.flags & AP_MSG_FLAG_ADMIN) { + if (!test_bit_inv(domain, perms->adm)) { + rc = -ENODEV; diff --git a/queue-6.18/s390-zcrypt-validate-length-for-cca-aes-cipher-key-requests.patch b/queue-6.18/s390-zcrypt-validate-length-for-cca-aes-cipher-key-requests.patch new file mode 100644 index 0000000000..a02ea3bbf1 --- /dev/null +++ b/queue-6.18/s390-zcrypt-validate-length-for-cca-aes-cipher-key-requests.patch @@ -0,0 +1,36 @@ +From 06afe425d5283b9764303de47f554da5a808ce8a Mon Sep 17 00:00:00 2001 +From: Holger Dengler +Date: Wed, 29 Jul 2026 11:36:15 +0200 +Subject: s390/zcrypt: Validate length for CCA AES cipher key requests + +From: Holger Dengler + +commit 06afe425d5283b9764303de47f554da5a808ce8a upstream. + +cca_cipher2protkey() derives the copy length for the CPRB parameter +block directly from the length field in the key token. Reject the +request early if the token length exceeds the available space in the +parameter block. + +Fixes: 4bc123b18ce6 ("s390/zcrypt: Add low level functions for CCA AES cipher keys") +Signed-off-by: Holger Dengler +Cc: stable@vger.kernel.org # 5.4+ +Reviewed-by: Harald Freudenberger +Signed-off-by: Vasily Gorbik +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/crypto/zcrypt_ccamisc.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/s390/crypto/zcrypt_ccamisc.c ++++ b/drivers/s390/crypto/zcrypt_ccamisc.c +@@ -1313,6 +1313,9 @@ int cca_cipher2protkey(u16 cardnr, u16 d + } __packed * prepparm; + int keytoklen = ((struct cipherkeytoken *)ckey)->len; + ++ if (keytoklen > PARMBSIZE - sizeof(struct aureqparm)) ++ return -EINVAL; ++ + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, + &preqcblk, &prepcblk, xflags); diff --git a/queue-6.18/s390-zcrypt-validate-length-for-cca-ecc-private-key-requests.patch b/queue-6.18/s390-zcrypt-validate-length-for-cca-ecc-private-key-requests.patch new file mode 100644 index 0000000000..9ce3650dcc --- /dev/null +++ b/queue-6.18/s390-zcrypt-validate-length-for-cca-ecc-private-key-requests.patch @@ -0,0 +1,36 @@ +From a9ae0f6dd45c3ccc1d69363f7aea8af179122730 Mon Sep 17 00:00:00 2001 +From: Holger Dengler +Date: Wed, 29 Jul 2026 11:36:16 +0200 +Subject: s390/zcrypt: Validate length for CCA ECC private key requests + +From: Holger Dengler + +commit a9ae0f6dd45c3ccc1d69363f7aea8af179122730 upstream. + +cca_ecc2protkey() derives the copy length for the CPRB parameter +block directly from the length field in the key token. Reject the +request early if the token length exceeds the available space in the +parameter block. + +Fixes: fa6999e326fe ("s390/pkey: support CCA and EP11 secure ECC private keys") +Signed-off-by: Holger Dengler +Cc: stable@vger.kernel.org # 5.10+ +Reviewed-by: Harald Freudenberger +Signed-off-by: Vasily Gorbik +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/crypto/zcrypt_ccamisc.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/s390/crypto/zcrypt_ccamisc.c ++++ b/drivers/s390/crypto/zcrypt_ccamisc.c +@@ -1480,6 +1480,9 @@ int cca_ecc2protkey(u16 cardnr, u16 doma + } __packed * prepparm; + int keylen = ((struct eccprivkeytoken *)key)->len; + ++ if (keylen > PARMBSIZE - sizeof(struct aureqparm)) ++ return -EINVAL; ++ + /* get already prepared memory for 2 cprbs with param block each */ + rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, + &preqcblk, &prepcblk, xflags); diff --git a/queue-6.18/scsi-scsi_debug-fix-report-zones-alloc_len-underflow-oob-write.patch b/queue-6.18/scsi-scsi_debug-fix-report-zones-alloc_len-underflow-oob-write.patch new file mode 100644 index 0000000000..f6ba98b2ae --- /dev/null +++ b/queue-6.18/scsi-scsi_debug-fix-report-zones-alloc_len-underflow-oob-write.patch @@ -0,0 +1,68 @@ +From 93dde0bf2f39a0f9f57fd610aa3201ce5b753433 Mon Sep 17 00:00:00 2001 +From: Ibrahim Hashimov +Date: Sun, 12 Jul 2026 20:37:39 +0200 +Subject: scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write + +From: Ibrahim Hashimov + +commit 93dde0bf2f39a0f9f57fd610aa3201ce5b753433 upstream. + +resp_report_zones() sizes the reply buffer from the CDB allocation +length. The v3 fix rounds alloc_len up with ALIGN() before deriving the +descriptor count: + + rep_max_zones = (ALIGN((u64)alloc_len, RZONES_DESC_HD) - + RZONES_DESC_HD) >> ilog2(RZONES_DESC_HD); + arr_len = (u64)RZONES_DESC_HD * (rep_max_zones + 1); + +For alloc_len in 0xFFFFFFC1..0xFFFFFFFF, ALIGN() rounds up to +0x100000000, so arr_len is 4 GB. On 32-bit, kzalloc()'s size_t is 32-bit +and truncates 0x100000000 to 0; kzalloc(0) returns ZERO_SIZE_PTR, which +passes the !arr check, and desc = arr + 64 is then dereferenced in the +loop -> out-of-bounds write / panic. + +Clamp rep_max_zones to devip->nr_zones. The loop already stops at +sdebug_capacity (after nr_zones zones), so a report can never hold more +than nr_zones descriptors; the clamp does not change the report, it only +bounds arr_len to (nr_zones + 1) * RZONES_DESC_HD, a real device +property that can never reach 0x100000000. + +Fixes: 7db0e0c8190a ("scsi: scsi_debug: Fix buffer size of REPORT ZONES command") +Suggested-by: Damien Le Moal +Cc: stable@vger.kernel.org +Signed-off-by: Ibrahim Hashimov +Assisted-by: AuditCode-AI:2026.07 +Reviewed-by: Damien Le Moal +Reviewed-by: Bart Van Assche +Link: https://patch.msgid.link/20260712183739.83915-1-security@auditcode.ai +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/scsi_debug.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -5896,6 +5896,7 @@ static int resp_report_zones(struct scsi + u32 alloc_len, rep_opts, rep_len; + bool partial; + u64 lba, zs_lba; ++ u64 arr_len; + u8 *arr = NULL, *desc; + u8 *cmd = scp->cmnd; + struct sdeb_zone_state *zsp = NULL; +@@ -5917,9 +5918,12 @@ static int resp_report_zones(struct scsi + return check_condition_result; + } + +- rep_max_zones = (alloc_len - 64) >> ilog2(RZONES_DESC_HD); ++ rep_max_zones = (ALIGN((u64)alloc_len, RZONES_DESC_HD) - RZONES_DESC_HD) >> ++ ilog2(RZONES_DESC_HD); ++ rep_max_zones = min_t(unsigned int, rep_max_zones, devip->nr_zones); ++ arr_len = (u64)RZONES_DESC_HD * (rep_max_zones + 1); + +- arr = kzalloc(alloc_len, GFP_ATOMIC | __GFP_NOWARN); ++ arr = kzalloc(arr_len, GFP_ATOMIC | __GFP_NOWARN); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); diff --git a/queue-6.18/sctp-prevent-peer-transport-count-overflow.patch b/queue-6.18/sctp-prevent-peer-transport-count-overflow.patch new file mode 100644 index 0000000000..fa888fe6e4 --- /dev/null +++ b/queue-6.18/sctp-prevent-peer-transport-count-overflow.patch @@ -0,0 +1,45 @@ +From bd0e9289e2642f6a5c54faad304ce0f41e926d22 Mon Sep 17 00:00:00 2001 +From: Asim Viladi Oglu Manizada +Date: Sat, 25 Jul 2026 03:21:06 +0000 +Subject: sctp: prevent peer transport count overflow + +From: Asim Viladi Oglu Manizada + +commit bd0e9289e2642f6a5c54faad304ce0f41e926d22 upstream. + +sctp_assoc_add_peer() increments the association's 16-bit transport_count +for every new unique peer. Adding the 65,536th transport wraps the count to +zero. + +SCTP sock_diag uses transport_count to reserve the INET_DIAG_PEERS payload, +then copies one sockaddr_storage for every entry in transport_addr_list. +After the wrap, a diagnostic dump reserves an empty payload and writes +8 MiB of peer addresses past the skb tail. + +Reject a new unique peer when transport_count has reached U16_MAX. Perform +the check after the existing-peer lookup so a duplicate address continues +to return its existing transport at the limit. + +Fixes: 8f840e47f190 ("sctp: add the sctp_diag.c file") +Cc: stable@vger.kernel.org +Signed-off-by: Asim Viladi Oglu Manizada +Acked-by: Xin Long +Link: https://patch.msgid.link/20260725032053.521705-1-manizada@pm.me +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/associola.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -614,6 +614,9 @@ struct sctp_transport *sctp_assoc_add_pe + return peer; + } + ++ if (asoc->peer.transport_count == U16_MAX) ++ return NULL; ++ + peer = sctp_transport_new(asoc->base.net, addr, gfp); + if (!peer) + return NULL; diff --git a/queue-6.18/sctp-reject-stale-cookies-with-mismatched-verification-tags.patch b/queue-6.18/sctp-reject-stale-cookies-with-mismatched-verification-tags.patch new file mode 100644 index 0000000000..d5cb66ba53 --- /dev/null +++ b/queue-6.18/sctp-reject-stale-cookies-with-mismatched-verification-tags.patch @@ -0,0 +1,65 @@ +From 9d8da8e0a9bce4a340af60dd0446bc7eb8d07587 Mon Sep 17 00:00:00 2001 +From: Yuxiang Yang +Date: Thu, 23 Jul 2026 22:56:23 +0000 +Subject: sctp: reject stale cookies with mismatched verification tags + +From: Yuxiang Yang + +commit 9d8da8e0a9bce4a340af60dd0446bc7eb8d07587 upstream. + +sctp_unpack_cookie() skips cookie expiration checks whenever an +association already exists. This is broader than the exception in +RFC 9260 Section 5.2.4. + +For an existing association, Section 5.2.4 permits an expired State +Cookie only when both Verification Tags in the cookie match the current +association. Otherwise, the packet SHOULD be discarded and a Stale +Cookie ERROR MUST be sent. + +The broad check lets an expired Action A restart cookie reach +sctp_sf_do_dupcook_a(). In a runtime test with the default 60 second +cookie lifetime, replaying such a cookie after 65 seconds returned a +COOKIE-ACK and restarted the association. + +Check cookie expiration unless both Verification Tags match. This +preserves the Action D exception for a lost COOKIE ACK while rejecting +expired cookies in all other cases. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Yuxiang Yang +Acked-by: Xin Long +Link: https://patch.msgid.link/20260723225623.2658868-1-yangyx22@mails.tsinghua.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/sm_make_chunk.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -1802,9 +1802,9 @@ struct sctp_association *sctp_unpack_coo + goto fail; + } + +- /* Check to see if the cookie is stale. If there is already +- * an association, there is no need to check cookie's expiration +- * for init collision case of lost COOKIE ACK. ++ /* Check to see if the cookie is stale. RFC 9260 Section 5.2.4 ++ * exempts an expired cookie only when both Verification Tags match ++ * the current association. + * If skb has been timestamped, then use the stamp, otherwise + * use current time. This introduces a small possibility that + * a cookie may be considered expired, but this would only slow +@@ -1815,7 +1815,10 @@ struct sctp_association *sctp_unpack_coo + else + kt = ktime_get_real(); + +- if (!asoc && ktime_before(bear_cookie->expiration, kt)) { ++ if ((!asoc || ++ asoc->c.my_vtag != bear_cookie->my_vtag || ++ asoc->c.peer_vtag != bear_cookie->peer_vtag) && ++ ktime_before(bear_cookie->expiration, kt)) { + suseconds_t usecs = ktime_to_us(ktime_sub(kt, bear_cookie->expiration)); + __be32 n = htonl(usecs); + diff --git a/queue-6.18/selftests-clone3-fix-wild-pointer-access-of-getline-due-to-missing-init.patch b/queue-6.18/selftests-clone3-fix-wild-pointer-access-of-getline-due-to-missing-init.patch new file mode 100644 index 0000000000..d38a32861c --- /dev/null +++ b/queue-6.18/selftests-clone3-fix-wild-pointer-access-of-getline-due-to-missing-init.patch @@ -0,0 +1,95 @@ +From 8f6f9fd93cd7a5dd607ad5cd910476dd68fff3ed Mon Sep 17 00:00:00 2001 +From: Chris Gellermann +Date: Wed, 22 Jul 2026 15:02:45 +0200 +Subject: selftests/clone3: fix wild pointer access of getline due to missing init + +From: Chris Gellermann + +commit 8f6f9fd93cd7a5dd607ad5cd910476dd68fff3ed upstream. + +Patch series "selftests: Add missing initalization of pointer passed to +getline", v2. + + +This patch (of 2): + +Clone3_set_tid uses getline(&line, ...) in a loop to read the child's +process status. The code expects that getline allocates the buffer for +the line on the first loop iteration. According to the Open Group +Spec[1], char *line has to be null pointer for this: + +> ssize_t getline(char **restrict lineptr, ...); +> If *lineptr is a null pointer or if the object pointed to by *lineptr +> is of insufficient size, an object shall be allocated as if by +malloc() +> or the object shall be reallocated as if by realloc()[...]. + +However, char *line is only declared, leading to an undefined value that +is potentially non-null. In an example run with Musl v1.2.6, the realloc +call[2] of getdelim, which implements getline, triggers a segfault: + +./run_kselftest.sh --test clone3:clone3_set_tid +[ 1366.165898] kselftest: Running tests in clone3 +... +[ 1367.799244] clone3_set_tid[811]: unhandled signal 11 code 0x1 at +0x0000000000000000 in libc.so[68184,3fbf69f000+4c000] +[ 1367.802808] CPU: 0 UID: 0 PID: 811 Comm: clone3_set_tid Not tainted +.. +[ 1367.804188] epc: 0x0000003fbf6b0184 +[ 1367.804188] ra : 0x0000003fbf6d4664 +[ 1367.804188] sp : 0x0000003fce5f2e40 +[ 1367.805314] gp : 0x0000002aaab0dfb8 +[ 1367.805314] tp : 0x0000003fbf6f14a8 +[ 1367.805314] t0 : 0x0000003fbf63d000 +... + +Looking at the realloc implementation, Musl mallocs for a null pointer +memory. But for a non-null pointer, it assumes it's passed a valid +pointer to the heap and tries to access its meta-data. This leads to the +segfault we see: + +void *realloc(void *p, size_t n) +{ + if (!p) return malloc(n); + if (size_overflows(n)) return 0; + + struct meta *g = get_meta(p); + ... +} + +Fix this by properly initializing the line pointer to NULL. + +Link: https://lore.kernel.org/20260722130246.2135563-1-christian.gellermann@codasip.com +Link: https://lore.kernel.org/20260722130246.2135563-2-christian.gellermann@codasip.com +Link: https://pubs.opengroup.org/onlinepubs/9799919799/functions/getline.html [1] +Link: https://git.musl-libc.org/cgit/musl/tree/src/stdio/getdelim.c#n38 [2] +Fixes: 41585bbeeef9 ("selftests: add tests for clone3() with *set_tid") +Signed-off-by: Chris Gellermann +Acked-by: David Hildenbrand (arm) +Reviewed-by: Lorenzo Stoakes +Cc: Christian Brauner +Cc: Liam R. Howlett +Cc: Lorenzo Stoakes +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Shuah Khan +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/clone3/clone3_set_tid.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/testing/selftests/clone3/clone3_set_tid.c ++++ b/tools/testing/selftests/clone3/clone3_set_tid.c +@@ -141,7 +141,7 @@ int main(int argc, char *argv[]) + { + FILE *f; + char buf; +- char *line; ++ char *line = NULL; + int status; + int ret = -1; + size_t len = 0; diff --git a/queue-6.18/selftests-mm-fix-potential-wild-pointer-access-of-getline-due-to-missing-init.patch b/queue-6.18/selftests-mm-fix-potential-wild-pointer-access-of-getline-due-to-missing-init.patch new file mode 100644 index 0000000000..d813d5c7c9 --- /dev/null +++ b/queue-6.18/selftests-mm-fix-potential-wild-pointer-access-of-getline-due-to-missing-init.patch @@ -0,0 +1,52 @@ +From 9f1d75a4ce04095afdb63d8e540092ff8151dacf Mon Sep 17 00:00:00 2001 +From: Chris Gellermann +Date: Wed, 22 Jul 2026 15:02:46 +0200 +Subject: selftests/mm: fix potential wild pointer access of getline due to missing init + +From: Chris Gellermann + +commit 9f1d75a4ce04095afdb63d8e540092ff8151dacf upstream. + +This is another occurrence of using getline where the code assumes that +getline allocates memory to store the line, but the pointer passed to it +is uninitialized and potentially a non-null pointer. This violates the +Open Group Spec[1] and caused a segfault in a similar situation in +selftest/clone3/clone3_set_tid. Fix it by initializing the line pointer +to NULL. + +The issue has been found by simply grepping through the selftest code +after running into the issue in clone3_set_tid. Whether it segfaults in +its current state is unknown to me. But it's good to be addressed due to +defensive reasons. + +Link: https://lore.kernel.org/20260722130246.2135563-3-christian.gellermann@codasip.com +Link: https://pubs.opengroup.org/onlinepubs/9799919799/functions/getline.html [1] +Fixes: 26b4224d9961 ("selftests: expanding more mlock selftest") +Signed-off-by: Chris Gellermann +Acked-by: David Hildenbrand (arm) +Reviewed-by: Lorenzo Stoakes +Cc: Christian Brauner +Cc: Liam R. Howlett +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Shuah Khan +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/mm/mlock-random-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/testing/selftests/mm/mlock-random-test.c ++++ b/tools/testing/selftests/mm/mlock-random-test.c +@@ -84,7 +84,7 @@ int get_proc_locked_vm_size(void) + int get_proc_page_size(unsigned long addr) + { + FILE *smaps; +- char *line; ++ char *line = NULL; + unsigned long mmupage_size = 0; + size_t size; + diff --git a/queue-6.18/series b/queue-6.18/series index 883ffa0920..9fa53b40fe 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -232,3 +232,63 @@ binfmt_misc-restore-write-access-when-removing-an-entry.patch binfmt_misc-use-exe_file_deny_write_access-for-the-interpreter-clone.patch binfmt_misc-reject-a-flag-character-as-the-field-delimiter.patch binfmt_misc-don-t-let-an-f-entry-pin-its-own-instance.patch +io_uring-net-initialize-mshot_len-for-send.patch +mm-page_reporting-use-system_freezable_wq-to-fix-uaf-during-suspend.patch +mm-memcg-initialize-locked-in-memcg1_oom_prepare-stub.patch +net-bridge-stop-fast-leave-after-deleting-a-port-group.patch +net-ipv6-clear-suppressed-fib6-rule-result.patch +net-pktgen-fix-proc-entry-use-after-free.patch +powerpc-ps3-fix-map-failure-path-in-dma_ioc0_map_pages.patch +um-vector-fix-use-after-free-in-vector_mmsg_rx.patch +uprobes-fix-null-pointer-dereference-in-hprobe_expire.patch +veth-convert-frag_list-skbs-before-running-xdp.patch +vxlan-re-fetch-eth-header-after-route_shortcircuit.patch +vxlan-unclone-skb-head-before-modifying-eth-header-in-route_shortcircuit.patch +vxlan-use-neigh_ha_snapshot-in-route_shortcircuit.patch +vxlan-use-pskb_network_may_pull-for-transmit-path-header-pulls.patch +vxlan-use-pskb_network_may_pull-in-route_shortcircuit.patch +ublk-reset-kernel-owned-dev_info-fields-in-ublk_ctrl_add_dev.patch +tracing-check-return-value-of-__register_event-in-trace_module_add_events.patch +tracing-filters-fix-false-positive-match-in-regex_match_full.patch +spi-spi-qpic-snand-write-the-feature-value-before-executing-set_feature.patch +spi-qcom-qspi-correct-max-dma-length-to-avoid-64k-boundary-failure.patch +selftests-mm-fix-potential-wild-pointer-access-of-getline-due-to-missing-init.patch +selftests-clone3-fix-wild-pointer-access-of-getline-due-to-missing-init.patch +scsi-scsi_debug-fix-report-zones-alloc_len-underflow-oob-write.patch +sctp-reject-stale-cookies-with-mismatched-verification-tags.patch +sctp-prevent-peer-transport-count-overflow.patch +hwmon-npcm750-pwm-fan-stop-fan-timer-on-device-detach.patch +hwmon-pmbus-core-notify-on-the-hwmon-device-not-the-i2c-client.patch +i2c-amd-mp2-unregister-callback-on-adapter-add-failure.patch +gpio-pca953x-fix-cache_only-and-irq-state-on-restore_context-failure.patch +gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch +cifs-add-fscache_resize_cookie-to-cifs_setsize.patch +cpufreq-powernow-k8-fix-possible-memory-leak-in-powernowk8_cpu_init.patch +cpufreq-schedutil-publish-util-hooks-only-after-all-sg_cpu-are-initialized.patch +power-supply-bq25890-fix-the-10-c-ntc-lookup-entry.patch +power-supply-max17040-handle-missing-status-supplier.patch +s390-pci-fix-s390_pci_mmio_write-syscall-error-return-without-mio.patch +s390-qeth-check-cap_net_admin-for-private-ioctls.patch +s390-dasd-fix-potential-null-pointer-dereference.patch +s390-dasd-fix-undersized-format-check-buffer.patch +s390-zcrypt-fix-wrong-domain-value-verification-with-ep11-cprbs.patch +s390-zcrypt-fix-buffer-over-read-in-cca_cipher2protkey.patch +s390-zcrypt-fix-missing-mem-scrub-at-clear-key-import-in-cca_clr2cipherkey.patch +s390-zcrypt-validate-length-for-cca-aes-cipher-key-requests.patch +s390-zcrypt-validate-length-for-cca-ecc-private-key-requests.patch +phy-zynqmp-fix-l0_tm_disable_scramble_encoder-mask.patch +phy-zynqmp-use-read-modify-write-for-serdes-scrambler-bypass.patch +phy-zynqmp-keep-serdes-scrambler-and-8b-10b-enabled-for-usb.patch +net-openvswitch-fix-potential-uaf-on-meter-attach-failure.patch +net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-recirculation.patch +net-openvswitch-fix-skb-leak-on-flow-key-update-failure-during-ct.patch +ice-wait-for-reset-completion-in-ice_resume.patch +ice-fix-vf-interrupts-cleanup.patch +ice-fix-memory-leak-in-ice_lbtest_prepare_rings.patch +i2c-spacemit-request-irq-after-controller-initialization.patch +i2c-qcom-cci-drop-custom-suspend-resume-and-rely-on-runtime-pm-helpers.patch +i2c-jz4780-cache-host-clock-rate-at-probe-to-prevent-ccf-prepare_lock-deadlock.patch +i2c-iproc-reset-bus-after-timeout-if-start_busy-is-stuck.patch +i2c-imx-mark-i2c-adapter-when-hardware-is-powered-down.patch +i2c-imx-fix-slave-registration-race-and-error-handling.patch +i2c-imx-cancel-hrtimer-before-clearing-slave-pointer.patch diff --git a/queue-6.18/spi-qcom-qspi-correct-max-dma-length-to-avoid-64k-boundary-failure.patch b/queue-6.18/spi-qcom-qspi-correct-max-dma-length-to-avoid-64k-boundary-failure.patch new file mode 100644 index 0000000000..5bed613202 --- /dev/null +++ b/queue-6.18/spi-qcom-qspi-correct-max-dma-length-to-avoid-64k-boundary-failure.patch @@ -0,0 +1,49 @@ +From 90ef2f2961c2dc55957dafe2f53b3efdb4675efc Mon Sep 17 00:00:00 2001 +From: Vijaya Krishna Nivarthi +Date: Wed, 22 Jul 2026 14:53:58 +0530 +Subject: spi: qcom-qspi: Correct max DMA length to avoid 64K boundary failure + +From: Vijaya Krishna Nivarthi + +commit 90ef2f2961c2dc55957dafe2f53b3efdb4675efc upstream. + +The maximum size for a DMA data descriptor is 64KB-1 because the size +field in HW is 16 bits wide. For this reason, transfers fail at 64KB +and beyond. + +Lower max_dma_len to 60KB so larger transfers are split into multiple +DMA blocks and do not hit the failing 64KB boundary. 60KB is chosen as +a safe round number below the 64KB-1 hardware limit while satisfying +alignment requirements. + +Tested on x1e80100 (Hamoa) with SPI-NOR flash (/dev/mtd0): + +Without patch: + dd if=/dev/mtd0 of=/tmp/spi_dump.bin bs=32768 count=2 # works + dd if=/dev/mtd0 of=/tmp/spi_dump.bin bs=65536 count=1 # fails + +With patch: + dd if=/dev/mtd0 of=/tmp/spi_dump.bin bs=65536 count=1 # works + +Fixes: b5762d95607e ("spi: spi-qcom-qspi: Add DMA mode support") +Cc: stable@vger.kernel.org +Signed-off-by: Vijaya Krishna Nivarthi +Link: https://patch.msgid.link/20260722092358.459943-1-vnivarth@qti.qualcomm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-qcom-qspi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-qcom-qspi.c ++++ b/drivers/spi/spi-qcom-qspi.c +@@ -759,7 +759,8 @@ static int qcom_qspi_probe(struct platfo + return dev_err_probe(dev, ret, "could not set DMA mask\n"); + + host->max_speed_hz = 300000000; +- host->max_dma_len = 65536; /* as per HPG */ ++ /* as per HPG, it is 64KB, limit to 60KB to avoid boundary condition failures */ ++ host->max_dma_len = 0xf000; + host->dma_alignment = QSPI_ALIGN_REQ; + host->num_chipselect = QSPI_NUM_CS; + host->bus_num = -1; diff --git a/queue-6.18/spi-spi-qpic-snand-write-the-feature-value-before-executing-set_feature.patch b/queue-6.18/spi-spi-qpic-snand-write-the-feature-value-before-executing-set_feature.patch new file mode 100644 index 0000000000..8704d768f5 --- /dev/null +++ b/queue-6.18/spi-spi-qpic-snand-write-the-feature-value-before-executing-set_feature.patch @@ -0,0 +1,90 @@ +From 8fd62901d6bf03f274a49dd0060793cc07dd51b0 Mon Sep 17 00:00:00 2001 +From: Stanislaw Pal +Date: Mon, 27 Jul 2026 18:32:16 +0200 +Subject: spi: spi-qpic-snand: write the feature value before executing SET_FEATURE + +From: Stanislaw Pal + +commit 8fd62901d6bf03f274a49dd0060793cc07dd51b0 upstream. + +qcom_spi_send_cmdaddr() programs NAND_FLASH_CMD/NAND_EXEC_CMD and submits +the descriptors, which makes the controller execute the command +immediately. For SPINAND_SET_FEATURE the value to be written is only +placed into NAND_FLASH_FEATURES afterwards, by qcom_spi_io_op(), in a +second submission - so the chip is programmed with whatever that register +happened to hold from a previous operation, and the intended value is only +applied by the *next* SET_FEATURE. + +Measured on a TP-Link Archer AX55 v1 (IPQ5018, ESMT F50L1G41LB): writing +0x40 to the configuration register (0xb0) leaves the chip at 0x00, and the +subsequent write of 0x00 leaves it at 0x40 - every write lands one +operation late. + +This stayed unnoticed until v6.18 added SPI-NAND OTP support together +with OTP entries for ESMT chips. spinand_otp_rw() enables OTP mode, +reads, and disables it again, and mtd_otp_nvmem_add() does this during +MTD registration. With the off-by-one, the "disable" write actually +applies the previously requested value, so CFG_OTP_ENABLE ends up set: +the chip stays in OTP mode, every subsequent array read returns the OTP +area instead of the array (UBI reports an empty device) and all writes +fail with -EIO because the OTP area is write protected. On this board +that makes the whole flash unusable and the device unbootable. + +Write the feature value into NAND_FLASH_FEATURES as part of the same +transaction, before NAND_EXEC_CMD. While at it, copy only the bytes the +operation actually carries - the previous code dereferenced a 4-byte +pointer on a one-byte buffer (spinand->scratchbuf). + +With this patch the flash contents read back bit-identical to a +known-good dump of the same board taken under the vendor firmware +(md5-verified across partitions), and writes work. + +Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Pal +Reviewed-by: Md Sadre Alam +Link: https://patch.msgid.link/20260727163216.109938-1-kuncy7@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-qpic-snand.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -1362,6 +1362,22 @@ static int qcom_spi_send_cmdaddr(struct + snandc->regs->addr0 = cpu_to_le32(op->addr.val); + snandc->regs->addr1 = cpu_to_le32(0); + ++ /* ++ * The feature value has to reach NAND_FLASH_FEATURES before the ++ * command is executed, otherwise the controller programs the chip ++ * with whatever the register happened to hold from a previous ++ * operation. ++ */ ++ if (opcode == SPINAND_SET_FEATURE) { ++ u32 ftr = 0; ++ ++ memcpy(&ftr, op->data.buf.out, ++ min_t(size_t, op->data.nbytes, sizeof(ftr))); ++ snandc->regs->flash_feature = cpu_to_le32(ftr); ++ qcom_write_reg_dma(snandc, &snandc->regs->flash_feature, ++ NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL); ++ } ++ + qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 3, NAND_BAM_NEXT_SGL); + qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); + +@@ -1399,10 +1415,8 @@ static int qcom_spi_io_op(struct qcom_na + copy_ftr = true; + break; + case SPINAND_SET_FEATURE: +- snandc->regs->flash_feature = cpu_to_le32(*(u32 *)op->data.buf.out); +- qcom_write_reg_dma(snandc, &snandc->regs->flash_feature, +- NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL); +- break; ++ /* fully handled by qcom_spi_send_cmdaddr() */ ++ return 0; + case SPINAND_PROGRAM_EXECUTE: + case SPINAND_WRITE_EN: + case SPINAND_RESET: diff --git a/queue-6.18/tracing-check-return-value-of-__register_event-in-trace_module_add_events.patch b/queue-6.18/tracing-check-return-value-of-__register_event-in-trace_module_add_events.patch new file mode 100644 index 0000000000..66c164b4e5 --- /dev/null +++ b/queue-6.18/tracing-check-return-value-of-__register_event-in-trace_module_add_events.patch @@ -0,0 +1,47 @@ +From ac8719969e6c3c54e939834df812bc41f25453cf Mon Sep 17 00:00:00 2001 +From: "Masami Hiramatsu (Google)" +Date: Wed, 29 Jul 2026 09:27:58 +0900 +Subject: tracing: Check return value of __register_event() in trace_module_add_events() + +From: Masami Hiramatsu (Google) + +commit ac8719969e6c3c54e939834df812bc41f25453cf upstream. + +trace_module_add_events() ignores the return value of __register_event() +and unconditionally calls __add_event_to_tracers() for each event. + +If __register_event() fails (for example, if event_init() fails), the +trace_event_call is not added to ftrace_events list, but +__add_event_to_tracers() still creates a trace_event_file pointing to it. +If module loading subsequently fails and module memory is freed, tracing +state retains a stale trace_event_call pointer in trace_event_file, +leading to a use-after-free when tracefs or tracing subsystem operations +are later executed. + +Fix this by checking the return value of __register_event() and only +calling __add_event_to_tracers() if event registration succeeded. + +Fixes: ae63b31e4d0e ("tracing: Separate out trace events from global variables") +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/178528487878.124250.14170824576025743236.stgit@devnote2 +Assisted-by: Antigravity:gemini-3.5-flash +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_events.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -3771,8 +3771,8 @@ static void trace_module_add_events(stru + end = mod->trace_events + mod->num_trace_events; + + for_each_event(call, start, end) { +- __register_event(*call, mod); +- __add_event_to_tracers(*call); ++ if (!__register_event(*call, mod)) ++ __add_event_to_tracers(*call); + } + + update_cache_events(mod); diff --git a/queue-6.18/tracing-filters-fix-false-positive-match-in-regex_match_full.patch b/queue-6.18/tracing-filters-fix-false-positive-match-in-regex_match_full.patch new file mode 100644 index 0000000000..aac647ee4c --- /dev/null +++ b/queue-6.18/tracing-filters-fix-false-positive-match-in-regex_match_full.patch @@ -0,0 +1,46 @@ +From c22c7b735f9810ad276014f788f9aa5c879ec238 Mon Sep 17 00:00:00 2001 +From: "Masami Hiramatsu (Google)" +Date: Wed, 29 Jul 2026 09:28:07 +0900 +Subject: tracing/filters: Fix false positive match in regex_match_full() + +From: Masami Hiramatsu (Google) + +commit c22c7b735f9810ad276014f788f9aa5c879ec238 upstream. + +regex_match_full() calls strncmp(str, r->pattern, len) where len is the +target field buffer size. When len is smaller than r->len (the filter +pattern length), strncmp() checks only len bytes of r->pattern against +str. If those len bytes match, strncmp() returns 0, resulting in a +false-positive match where a shorter string in a fixed-size field +matches a longer filter pattern. + +For example, a 4-byte static string field containing "abcd" matched the +filter pattern "abcdefgh" because strncmp("abcd", "abcdefgh", 4) +returned 0. In this case, @len does NOT include '\0' because it is +fixed-size array. + +Fix this by returning 0 (no match) early when len < r->len. + +Fixes: 1889d20922d1 ("tracing/filters: Provide basic regex support") +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/178528488779.124250.5571741156199253769.stgit@devnote2 +Assisted-by: Antigravity:gemini-3.5-flash +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_events_filter.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/kernel/trace/trace_events_filter.c ++++ b/kernel/trace/trace_events_filter.c +@@ -1027,6 +1027,9 @@ static int regex_match_full(char *str, s + if (!len) + return strcmp(str, r->pattern) == 0; + ++ if (len < r->len) ++ return 0; ++ + return strncmp(str, r->pattern, len) == 0; + } + diff --git a/queue-6.18/ublk-reset-kernel-owned-dev_info-fields-in-ublk_ctrl_add_dev.patch b/queue-6.18/ublk-reset-kernel-owned-dev_info-fields-in-ublk_ctrl_add_dev.patch new file mode 100644 index 0000000000..d40c19add6 --- /dev/null +++ b/queue-6.18/ublk-reset-kernel-owned-dev_info-fields-in-ublk_ctrl_add_dev.patch @@ -0,0 +1,61 @@ +From e65848e4ce352bac9e3465099354c8b8f845391f Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Sun, 26 Jul 2026 09:50:25 -0500 +Subject: ublk: reset kernel-owned dev_info fields in ublk_ctrl_add_dev() + +From: Ming Lei + +commit e65848e4ce352bac9e3465099354c8b8f845391f upstream. + +ublk_ctrl_add_dev() memcpy()s the userspace ublksrv_ctrl_dev_info into +ub->dev_info and then fixes up the fields the driver owns, but misses +->state and ->ublksrv_pid. + +A device added with ->state = UBLK_S_DEV_LIVE passes the +"->state != UBLK_S_DEV_DEAD" test that ublk_stop_dev_unlocked() uses as its +proxy for "a disk is attached", while ->ub_disk is still NULL, so DEL_DEV +right after ADD_DEV oopses in del_gendisk(). UBLK_S_DEV_QUIESCED plus +UBLK_F_USER_RECOVERY dies one step earlier, in ublk_force_abort_dev(). A +poisoned ->state also gets START_USER_RECOVERY and the char device +read/write path onto a device that was never started, and wedges START_DEV +at -EEXIST. A poisoned ->ublksrv_pid just makes GET_DEV_INFO report an +unrelated task as the ublk server. + +Reset both after the memcpy(), as ublk_detach_disk() does. Userspace only +ever reads these back, so correcting them silently breaks nothing. + +ADD_DEV has copied ->state in unsanitized since ublk was merged, but back +then it was harmless: the gendisk was allocated during ADD_DEV, and both +teardown and the START_DEV -EEXIST check keyed off disk_live() rather than +->state. The oops became reachable once the disk allocation moved to +START_DEV and those checks switched to ->state. + +Fixes: 6d9e6dfdf3b2 ("ublk: defer disk allocation") +Cc: stable@vger.kernel.org +Signed-off-by: Ming Lei +Reviewed-by: Caleb Sander Mateos +Link: https://patch.msgid.link/20260726145025.1507383-1-tom.leiming@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/ublk_drv.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -3288,6 +3288,15 @@ static int ublk_ctrl_add_dev(const struc + ub->dev_info.dev_id = ub->ub_number; + + /* ++ * ->state and ->ublksrv_pid are owned by the driver and only read back ++ * by userspace, but they come from the copied-in dev_info, so reset ++ * them. Otherwise a device added with ->state != DEAD looks live while ++ * ->ub_disk is still NULL. ++ */ ++ ub->dev_info.state = UBLK_S_DEV_DEAD; ++ ub->dev_info.ublksrv_pid = -1; ++ ++ /* + * 64bit flags will be copied back to userspace as feature + * negotiation result, so have to clear flags which driver + * doesn't support yet, then userspace can get correct flags diff --git a/queue-6.18/um-vector-fix-use-after-free-in-vector_mmsg_rx.patch b/queue-6.18/um-vector-fix-use-after-free-in-vector_mmsg_rx.patch new file mode 100644 index 0000000000..053da07c78 --- /dev/null +++ b/queue-6.18/um-vector-fix-use-after-free-in-vector_mmsg_rx.patch @@ -0,0 +1,58 @@ +From af421e9aed3920c7ac88c24daa48606c7112feca Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Mon, 22 Jun 2026 08:47:22 -0400 +Subject: um: vector: fix use-after-free in vector_mmsg_rx() + +From: Michael Bommarito + +commit af421e9aed3920c7ac88c24daa48606c7112feca upstream. + +When vector_mmsg_rx() discards a packet whose overlay header fails +verify_header(), it frees the skb and continues the loop: + + if (header_check < 0) { + dev_kfree_skb_irq(skb); + vp->estats.rx_encaps_errors++; + continue; + } + +The normal and short-packet paths fall through to the bottom of the +loop body, which clears the consumed slot and advances the cursors: + + (*skbuff_vector) = NULL; + mmsg_vector++; + skbuff_vector++; + +The verify_header() < 0 path skips that via continue, so the freed skb +is left in skbuff_vector[] and the cursors do not advance. The next +iteration reads the same slot, gets the freed skb, and frees it again, +producing a refcount underflow / use-after-free in the RX path. + +Discard the slot the same way the other paths do before continuing. + +Only transports whose verify_header() can return negative are affected: +GRE and L2TPv3 do so on a cookie/session-id mismatch (raw/tap do not), +so any peer on such a transport can trigger it without authentication. + +Fixes: 49da7e64f33e ("High Performance UML Vector Network Driver") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Michael Bommarito +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman +--- + arch/um/drivers/vector_kern.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/um/drivers/vector_kern.c ++++ b/arch/um/drivers/vector_kern.c +@@ -1000,6 +1000,9 @@ static int vector_mmsg_rx(struct vector_ + */ + dev_kfree_skb_irq(skb); + vp->estats.rx_encaps_errors++; ++ (*skbuff_vector) = NULL; ++ mmsg_vector++; ++ skbuff_vector++; + continue; + } + if (header_check > 0) { diff --git a/queue-6.18/uprobes-fix-null-pointer-dereference-in-hprobe_expire.patch b/queue-6.18/uprobes-fix-null-pointer-dereference-in-hprobe_expire.patch new file mode 100644 index 0000000000..55de228a5d --- /dev/null +++ b/queue-6.18/uprobes-fix-null-pointer-dereference-in-hprobe_expire.patch @@ -0,0 +1,65 @@ +From cc679d7a6303e84d769f2afcde1fc51c51f127cd Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Wed, 29 Jul 2026 07:44:40 -0700 +Subject: uprobes: Fix NULL pointer dereference in hprobe_expire() + +From: Breno Leitao + +commit cc679d7a6303e84d769f2afcde1fc51c51f127cd upstream. + +Forking a task that has a pending uretprobe can oops the kernel with a +NULL pointer dereference in the clone() path: + + BUG: kernel NULL pointer dereference, address: 0000000000000018 + Oops: 0002 [#1] SMP NOPTI + RIP: 0010:hprobe_expire + CR2: 0000000000000018 + Call Trace: + uprobe_copy_process + copy_process + kernel_clone + __x64_sys_clone + do_syscall_64 + entry_SYSCALL_64_after_hwframe + +This was found on real hosts on Meta fleet. + +I've got the impression that this is what is happening: + + CPU 1 CPU 2 (traced task) + ----- ------------------- + hit uprobe, prepare_uretprobe(): + hprobe LEASED, refcount >= 1 + uprobe_unregister() + put_uprobe(): refcount -> 0 + fork() -> dup_utask() + hprobe_expire(hprobe, true) + try_get_uprobe() -> NULL + get_uprobe(NULL) <-- Oops + +Only take the extra reference when the uprobe is non-NULL; a NULL means +it is gone and is the correct value to return. + +Fixes: dd1a7567784e ("uprobes: SRCU-protect uretprobe lifetime (with timeout)") +Signed-off-by: Breno Leitao +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Oleg Nesterov +Acked-by: Andrii Nakryiko +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260729-uprobe-v1-1-61896b87c867@debian.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/events/uprobes.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -830,7 +830,7 @@ static struct uprobe *hprobe_expire(stru + if (try_cmpxchg(&hprobe->state, &hstate, uprobe ? HPROBE_STABLE : HPROBE_GONE)) { + /* We won the race, we are the ones to unlock SRCU */ + __srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx); +- return get ? get_uprobe(uprobe) : uprobe; ++ return get && uprobe ? get_uprobe(uprobe) : uprobe; + } + + /* diff --git a/queue-6.18/veth-convert-frag_list-skbs-before-running-xdp.patch b/queue-6.18/veth-convert-frag_list-skbs-before-running-xdp.patch new file mode 100644 index 0000000000..81f653b92e --- /dev/null +++ b/queue-6.18/veth-convert-frag_list-skbs-before-running-xdp.patch @@ -0,0 +1,96 @@ +From d0d6415963040c401e7a7e4e482a698ba52448cb Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Wed, 22 Jul 2026 20:19:25 +0100 +Subject: veth: convert frag_list skbs before running XDP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matt Fleming + +commit d0d6415963040c401e7a7e4e482a698ba52448cb upstream. + +A frag_list skb can reach veth with data_len set but nr_frags zero. +veth_convert_skb_to_xdp_buff() only converts skbs that are shared, +locked, have frags[], or do not have enough headroom. It later uses +skb_is_nonlinear() to decide whether to set XDP_FLAGS_HAS_FRAGS and +xdp_frags_size. + +That exposes frag_list data to XDP as if it were stored in frags[], but +frags[] is empty. AF_XDP copy mode can then trust the bogus XDP fragment +metadata, walk an empty fragment entry, and crash in memcpy() from +__xsk_rcv(). + +Route non-linear skbs through skb_pp_cow_data() before exposing them to +XDP, and only advertise XDP frags when the resulting skb has frags[]. +skb_copy_bits() already handles frag_list input, and skb_pp_cow_data() +builds frags[] output with skb_add_rx_frag(), which is the +representation XDP multi-buffer expects. + +Fixes: 718a18a0c8a6 ("veth: Rework veth_xdp_rcv_skb in order to accept non-linear skb") +Cc: stable@vger.kernel.org +Signed-off-by: Matt Fleming +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260722191925.2192070-1-matt@readmodwrite.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/veth.c | 4 ++-- + net/core/skbuff.c | 18 ++++++++++++------ + 2 files changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -756,7 +756,7 @@ static int veth_convert_skb_to_xdp_buff( + u32 frame_sz; + + if (skb_shared(skb) || skb_head_is_locked(skb) || +- skb_shinfo(skb)->nr_frags || ++ skb_is_nonlinear(skb) || + skb_headroom(skb) < XDP_PACKET_HEADROOM) { + if (skb_pp_cow_data(rq->page_pool, pskb, XDP_PACKET_HEADROOM)) + goto drop; +@@ -771,7 +771,7 @@ static int veth_convert_skb_to_xdp_buff( + xdp_prepare_buff(xdp, skb->head, skb_headroom(skb), + skb_headlen(skb), true); + +- if (skb_is_nonlinear(skb)) { ++ if (skb_shinfo(skb)->nr_frags) { + skb_shinfo(skb)->xdp_frags_size = skb->data_len; + xdp_buff_set_frags_flag(xdp); + } else { +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -895,6 +895,18 @@ static void skb_clone_fraglist(struct sk + skb_get(list); + } + ++/** ++ * skb_pp_cow_data() - copy skb data into page-pool backed storage ++ * @pool: page pool to allocate from ++ * @pskb: pointer to skb pointer, replaced with the copied skb on success ++ * @headroom: headroom to reserve in the copied skb ++ * ++ * skb_copy_bits() handles both frags[] and frag_list input. If the copied ++ * skb remains non-linear, it uses frags[], which is the representation used ++ * by XDP multi-buffer. ++ * ++ * Return: 0 on success or a negative errno on failure. ++ */ + int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb, + unsigned int headroom) + { +@@ -904,12 +916,6 @@ int skb_pp_cow_data(struct page_pool *po + int err, i, head_off; + void *data; + +- /* XDP does not support fraglist so we need to linearize +- * the skb. +- */ +- if (skb_has_frag_list(skb)) +- return -EOPNOTSUPP; +- + max_head_size = SKB_WITH_OVERHEAD(PAGE_SIZE - headroom); + if (skb->len > max_head_size + MAX_SKB_FRAGS * PAGE_SIZE) + return -ENOMEM; diff --git a/queue-6.18/vxlan-re-fetch-eth-header-after-route_shortcircuit.patch b/queue-6.18/vxlan-re-fetch-eth-header-after-route_shortcircuit.patch new file mode 100644 index 0000000000..b8a2acb9d5 --- /dev/null +++ b/queue-6.18/vxlan-re-fetch-eth-header-after-route_shortcircuit.patch @@ -0,0 +1,40 @@ +From 1395a676ec15a0a02a2a6d86602324f2d5fd41d5 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 23 Jul 2026 14:42:45 +0000 +Subject: vxlan: re-fetch eth header after route_shortcircuit() + +From: Eric Dumazet + +commit 1395a676ec15a0a02a2a6d86602324f2d5fd41d5 upstream. + +Before route_shortcircuit(), the eth header pointer is cached from eth_hdr(skb). + +Inside route_shortcircuit(), pskb_may_pull() can be called, which may +reallocate skb->head. + +In this case, returning to vxlan_xmit() leaves the cached eth pointer pointing to +freed memory, leading to a use-after-free when dereferencing eth->h_dest. + +Fix this by updating eth = eth_hdr(skb) after calling route_shortcircuit(). + +Fixes: ae8840825605 ("VXLAN: Allow L2 redirection with L3 switching") +Cc: stable@vger.kernel.org +Signed-off-by: Eric Dumazet +Reviewed-by: Vadim Fedorenko +Link: https://patch.msgid.link/20260723144249.759100-2-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan/vxlan_core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -2798,6 +2798,7 @@ static netdev_tx_t vxlan_xmit(struct sk_ + (ntohs(eth->h_proto) == ETH_P_IP || + ntohs(eth->h_proto) == ETH_P_IPV6)) { + did_rsc = route_shortcircuit(dev, skb); ++ eth = eth_hdr(skb); + if (did_rsc) + f = vxlan_find_mac_tx(vxlan, eth->h_dest, vni); + } diff --git a/queue-6.18/vxlan-unclone-skb-head-before-modifying-eth-header-in-route_shortcircuit.patch b/queue-6.18/vxlan-unclone-skb-head-before-modifying-eth-header-in-route_shortcircuit.patch new file mode 100644 index 0000000000..67e17a038d --- /dev/null +++ b/queue-6.18/vxlan-unclone-skb-head-before-modifying-eth-header-in-route_shortcircuit.patch @@ -0,0 +1,45 @@ +From 760d36e737f2b3867762f42af36c663f55babcc4 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 23 Jul 2026 14:42:46 +0000 +Subject: vxlan: unclone skb head before modifying eth header in route_shortcircuit() + +From: Eric Dumazet + +commit 760d36e737f2b3867762f42af36c663f55babcc4 upstream. + +When route_shortcircuit() performs L3 short-circuit routing, it modifies +the Ethernet header of the skb in-place: + memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, dev->addr_len); + memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len); + +If the incoming skb is cloned (for example by packet sockets, tcpdump, or +dev_queue_xmit), modifying the Ethernet header without uncloning can corrupt +the packet header for other readers holding a reference to the cloned skb. + +Ensure the skb header is writable and unshared by calling skb_cow_head(skb, 0) +prior to updating the Ethernet header. If skb_cow_head() fails, abort short-circuiting +and return false to allow standard packet processing fallback. + +Fixes: e4f67addf158 ("add DOVE extensions for VXLAN") +Cc: stable@vger.kernel.org +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20260723144249.759100-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan/vxlan_core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -2167,6 +2167,10 @@ static bool route_shortcircuit(struct ne + + diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha); + if (diff) { ++ if (skb_cow_head(skb, 0)) { ++ neigh_release(n); ++ return false; ++ } + memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, + dev->addr_len); + memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len); diff --git a/queue-6.18/vxlan-use-neigh_ha_snapshot-in-route_shortcircuit.patch b/queue-6.18/vxlan-use-neigh_ha_snapshot-in-route_shortcircuit.patch new file mode 100644 index 0000000000..160f5c4811 --- /dev/null +++ b/queue-6.18/vxlan-use-neigh_ha_snapshot-in-route_shortcircuit.patch @@ -0,0 +1,55 @@ +From 8eca411347e1d38964f9ed2c8d3b6ab0e7e4473d Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 23 Jul 2026 14:42:47 +0000 +Subject: vxlan: use neigh_ha_snapshot() in route_shortcircuit() + +From: Eric Dumazet + +commit 8eca411347e1d38964f9ed2c8d3b6ab0e7e4473d upstream. + +The neighbour hardware address n->ha can be updated asynchronously by the +neighbour subsystem, protected by n->ha_lock seqlock. Reading n->ha without +holding the seqlock loop can lead to torn reads or reading a partially updated +MAC address. + +Use neigh_ha_snapshot() in route_shortcircuit() to safely copy n->ha under +read_seqbegin()/read_seqretry() lock protection before using it. + +Note that arp_reduce() and neigh_reduce() seem to have the same issue +left for future patches. + +Fixes: e4f67addf158 ("add DOVE extensions for VXLAN") +Cc: stable@vger.kernel.org +Signed-off-by: Eric Dumazet +Reviewed-by: Vadim Fedorenko +Link: https://patch.msgid.link/20260723144249.759100-4-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan/vxlan_core.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -2163,9 +2163,11 @@ static bool route_shortcircuit(struct ne + } + + if (n) { ++ u8 haddr[ETH_ALEN]; + bool diff; + +- diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha); ++ neigh_ha_snapshot(haddr, n, dev); ++ diff = !ether_addr_equal_unaligned(eth_hdr(skb)->h_dest, haddr); + if (diff) { + if (skb_cow_head(skb, 0)) { + neigh_release(n); +@@ -2173,7 +2175,7 @@ static bool route_shortcircuit(struct ne + } + memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, + dev->addr_len); +- memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len); ++ memcpy(eth_hdr(skb)->h_dest, haddr, dev->addr_len); + } + neigh_release(n); + return diff; diff --git a/queue-6.18/vxlan-use-pskb_network_may_pull-for-transmit-path-header-pulls.patch b/queue-6.18/vxlan-use-pskb_network_may_pull-for-transmit-path-header-pulls.patch new file mode 100644 index 0000000000..b46a9dad04 --- /dev/null +++ b/queue-6.18/vxlan-use-pskb_network_may_pull-for-transmit-path-header-pulls.patch @@ -0,0 +1,78 @@ +From b9553558b48db54ac9273e6b98d7263ef5c1a329 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 23 Jul 2026 14:42:49 +0000 +Subject: vxlan: use pskb_network_may_pull() for transmit path header pulls + +From: Eric Dumazet + +commit b9553558b48db54ac9273e6b98d7263ef5c1a329 upstream. + +In vxlan_xmit(), arp_reduce(), and vxlan_mdb_entry_skb_get(), pskb_may_pull() was +being called to verify the availability of network layer headers (ARP, IPv6/ND, +IP/IPv6 MDB keys). + +However, during transmit skb->data points to the MAC header, so skb_network_offset(skb) +is ETH_HLEN (14 bytes). Using pskb_may_pull(skb, len) only checks len bytes from skb->data +rather than skb_network_offset(skb) + len, which can leave part of the network header +in non-linear frags. + +Replace these remaining pskb_may_pull() calls with pskb_network_may_pull() to properly +account for the MAC header offset. + +Fixes: e4f67addf158 ("add DOVE extensions for VXLAN") +Fixes: f564f45c4518 ("vxlan: add ipv6 proxy support") +Fixes: 0f83e69f44bf ("vxlan: Add MDB data path support") +Signed-off-by: Eric Dumazet +Cc: stable@vger.kernel.org +Reviewed-by: Vadim Fedorenko +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260723144249.759100-6-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan/vxlan_core.c | 6 +++--- + drivers/net/vxlan/vxlan_mdb.c | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -1852,7 +1852,7 @@ static int arp_reduce(struct net_device + if (dev->flags & IFF_NOARP) + goto out; + +- if (!pskb_may_pull(skb, arp_hdr_len(dev))) { ++ if (!pskb_network_may_pull(skb, arp_hdr_len(dev))) { + dev_dstats_tx_dropped(dev); + vxlan_vnifilter_count(vxlan, vni, NULL, + VXLAN_VNI_STATS_TX_DROPS, 0); +@@ -2765,8 +2765,8 @@ static netdev_tx_t vxlan_xmit(struct sk_ + return arp_reduce(dev, skb, vni); + #if IS_ENABLED(CONFIG_IPV6) + else if (ntohs(eth->h_proto) == ETH_P_IPV6 && +- pskb_may_pull(skb, sizeof(struct ipv6hdr) + +- sizeof(struct nd_msg)) && ++ pskb_network_may_pull(skb, sizeof(struct ipv6hdr) + ++ sizeof(struct nd_msg)) && + ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) { + struct nd_msg *m = (struct nd_msg *)(ipv6_hdr(skb) + 1); + +--- a/drivers/net/vxlan/vxlan_mdb.c ++++ b/drivers/net/vxlan/vxlan_mdb.c +@@ -1631,7 +1631,7 @@ struct vxlan_mdb_entry *vxlan_mdb_entry_ + + switch (skb->protocol) { + case htons(ETH_P_IP): +- if (!pskb_may_pull(skb, sizeof(struct iphdr))) ++ if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) + return NULL; + group.dst.sa.sa_family = AF_INET; + group.dst.sin.sin_addr.s_addr = ip_hdr(skb)->daddr; +@@ -1640,7 +1640,7 @@ struct vxlan_mdb_entry *vxlan_mdb_entry_ + break; + #if IS_ENABLED(CONFIG_IPV6) + case htons(ETH_P_IPV6): +- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) ++ if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) + return NULL; + group.dst.sa.sa_family = AF_INET6; + group.dst.sin6.sin6_addr = ipv6_hdr(skb)->daddr; diff --git a/queue-6.18/vxlan-use-pskb_network_may_pull-in-route_shortcircuit.patch b/queue-6.18/vxlan-use-pskb_network_may_pull-in-route_shortcircuit.patch new file mode 100644 index 0000000000..e8a5d4659e --- /dev/null +++ b/queue-6.18/vxlan-use-pskb_network_may_pull-in-route_shortcircuit.patch @@ -0,0 +1,53 @@ +From 26bb2dd0a8839617e2c79ffbbe1923f8e4bab9fb Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 23 Jul 2026 14:42:48 +0000 +Subject: vxlan: use pskb_network_may_pull() in route_shortcircuit() + +From: Eric Dumazet + +commit 26bb2dd0a8839617e2c79ffbbe1923f8e4bab9fb upstream. + +route_shortcircuit() currently calls pskb_may_pull(skb, sizeof(struct iphdr)) +(or ipv6hdr), which checks if bytes are available starting from skb->data. + +However, in vxlan_xmit(), skb->data points to the MAC header, so +skb_network_offset(skb) is ETH_HLEN (14 bytes). Using pskb_may_pull(skb, 20) +only checks 20 bytes from skb->data (which is 14 bytes MAC header + 6 bytes of +IP header), leaving the rest of the IP header potentially un-pulled in non-linear +frags. Subsequent dereferences of ip_hdr(skb)->daddr can read beyond the pulled +linear buffer length. + +Fix this by using pskb_network_may_pull(), which adds skb_network_offset(skb) to +the length check to ensure the full network header is present in the linear buffer. + +Fixes: e4f67addf158 ("add DOVE extensions for VXLAN") +Cc: stable@vger.kernel.org +Signed-off-by: Eric Dumazet +Reviewed-by: Vadim Fedorenko +Link: https://patch.msgid.link/20260723144249.759100-5-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan/vxlan_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -2115,7 +2115,7 @@ static bool route_shortcircuit(struct ne + { + struct iphdr *pip; + +- if (!pskb_may_pull(skb, sizeof(struct iphdr))) ++ if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) + return false; + pip = ip_hdr(skb); + n = neigh_lookup(&arp_tbl, &pip->daddr, dev); +@@ -2141,7 +2141,7 @@ static bool route_shortcircuit(struct ne + */ + if (!ipv6_stub->nd_tbl) + return false; +- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) ++ if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) + return false; + pip6 = ipv6_hdr(skb); + n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev);