]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 14 Jul 2026 14:55:18 +0000 (16:55 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 14 Jul 2026 14:55:18 +0000 (16:55 +0200)
added patches:
clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch
cpufreq-fix-hotplug-suspend-race-during-reboot.patch
cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch
cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch
cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch
firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch
hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch
hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch
hid-hid-lenovo-go-cancel-cfg_setup-work-in-hid_go_cfg_remove.patch
hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch
hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch
hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch
hid-pidff-use-correct-effect-type-in-effect-update.patch
hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch
hid-uhid-convert-to-hid_safe_input_report.patch
hid-wacom-fix-slab-out-of-bounds-write-in-wacom_wac_queue_insert.patch
hid-wacom-stop-hardware-after-post-start-probe-failures.patch
hid-wacom-use-gfp_atomic-in-wacom_wac_queue_flush.patch
libfs-set-sb_i_noexec-and-sb_i_nodev-by-default-in-init_pseudo.patch
mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch
opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch
perf-arm-cmn-fix-dvm-node-events.patch
perf-x86-intel-uncore-defer-adl-global-pmon-enable-to-enable_box.patch
posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch
proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch
proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch
s390-revert-support-for-dcache_word_access.patch
sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch
smb-server-do-not-require-delete-access-for-non-replacing-links.patch
time-jiffies-register-jiffies-clocksource-before-usage.patch
tools-mm-slabinfo-fix-total_objects-attribute-name.patch
tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch
writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch
x.509-fix-validation-of-asn.1-certificate-header.patch

35 files changed:
queue-7.1/clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch [new file with mode: 0644]
queue-7.1/cpufreq-fix-hotplug-suspend-race-during-reboot.patch [new file with mode: 0644]
queue-7.1/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch [new file with mode: 0644]
queue-7.1/cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch [new file with mode: 0644]
queue-7.1/cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch [new file with mode: 0644]
queue-7.1/firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch [new file with mode: 0644]
queue-7.1/hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch [new file with mode: 0644]
queue-7.1/hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch [new file with mode: 0644]
queue-7.1/hid-hid-lenovo-go-cancel-cfg_setup-work-in-hid_go_cfg_remove.patch [new file with mode: 0644]
queue-7.1/hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch [new file with mode: 0644]
queue-7.1/hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch [new file with mode: 0644]
queue-7.1/hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch [new file with mode: 0644]
queue-7.1/hid-pidff-use-correct-effect-type-in-effect-update.patch [new file with mode: 0644]
queue-7.1/hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch [new file with mode: 0644]
queue-7.1/hid-uhid-convert-to-hid_safe_input_report.patch [new file with mode: 0644]
queue-7.1/hid-wacom-fix-slab-out-of-bounds-write-in-wacom_wac_queue_insert.patch [new file with mode: 0644]
queue-7.1/hid-wacom-stop-hardware-after-post-start-probe-failures.patch [new file with mode: 0644]
queue-7.1/hid-wacom-use-gfp_atomic-in-wacom_wac_queue_flush.patch [new file with mode: 0644]
queue-7.1/libfs-set-sb_i_noexec-and-sb_i_nodev-by-default-in-init_pseudo.patch [new file with mode: 0644]
queue-7.1/mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch [new file with mode: 0644]
queue-7.1/opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch [new file with mode: 0644]
queue-7.1/perf-arm-cmn-fix-dvm-node-events.patch [new file with mode: 0644]
queue-7.1/perf-x86-intel-uncore-defer-adl-global-pmon-enable-to-enable_box.patch [new file with mode: 0644]
queue-7.1/posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch [new file with mode: 0644]
queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch [new file with mode: 0644]
queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch [new file with mode: 0644]
queue-7.1/s390-revert-support-for-dcache_word_access.patch [new file with mode: 0644]
queue-7.1/sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch [new file with mode: 0644]
queue-7.1/series
queue-7.1/smb-server-do-not-require-delete-access-for-non-replacing-links.patch [new file with mode: 0644]
queue-7.1/time-jiffies-register-jiffies-clocksource-before-usage.patch [new file with mode: 0644]
queue-7.1/tools-mm-slabinfo-fix-total_objects-attribute-name.patch [new file with mode: 0644]
queue-7.1/tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch [new file with mode: 0644]
queue-7.1/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch [new file with mode: 0644]
queue-7.1/x.509-fix-validation-of-asn.1-certificate-header.patch [new file with mode: 0644]

diff --git a/queue-7.1/clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch b/queue-7.1/clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch
new file mode 100644 (file)
index 0000000..c3b1425
--- /dev/null
@@ -0,0 +1,41 @@
+From ca57bf46e7a94f8c53d05c376df9fcfdcb482100 Mon Sep 17 00:00:00 2001
+From: Kartik Rajput <kkartik@nvidia.com>
+Date: Thu, 7 May 2026 21:15:54 +0530
+Subject: clocksource/drivers/timer-tegra186: Fix support for multiple watchdog instances
+
+From: Kartik Rajput <kkartik@nvidia.com>
+
+commit ca57bf46e7a94f8c53d05c376df9fcfdcb482100 upstream.
+
+Tegra SoCs support multiple watchdogs; currently only one (WDT0) is
+used. When multiple watchdogs are registered, tegra186_wdt_enable()
+overwrites the TKEIE(x) register, discarding any existing watchdog
+interrupt enable bits. As a result, enabling one watchdog inadvertently
+disables interrupts for the others.
+
+Fix this by preserving the existing TKEIE(x) value and updating it
+using a read-modify-write sequence.
+
+Fixes: 42cee19a9f83 ("clocksource: Add Tegra186 timers support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
+Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
+Link: https://patch.msgid.link/20260507154557.2082697-2-kkartik@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/clocksource/timer-tegra186.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/clocksource/timer-tegra186.c
++++ b/drivers/clocksource/timer-tegra186.c
+@@ -149,7 +149,8 @@ static void tegra186_wdt_enable(struct t
+       u32 value;
+       /* unmask hardware IRQ, this may have been lost across powergate */
+-      value = TKEIE_WDT_MASK(wdt->index, 1);
++      value = readl(tegra->regs + TKEIE(wdt->tmr->hwirq));
++      value |= TKEIE_WDT_MASK(wdt->index, 1);
+       writel(value, tegra->regs + TKEIE(wdt->tmr->hwirq));
+       /* clear interrupt */
diff --git a/queue-7.1/cpufreq-fix-hotplug-suspend-race-during-reboot.patch b/queue-7.1/cpufreq-fix-hotplug-suspend-race-during-reboot.patch
new file mode 100644 (file)
index 0000000..3db6817
--- /dev/null
@@ -0,0 +1,62 @@
+From a9029dd55696c651ee46912afa2a166fa456bb3e Mon Sep 17 00:00:00 2001
+From: Tianxiang Chen <nanmu@xiaomi.com>
+Date: Wed, 8 Apr 2026 22:19:14 +0800
+Subject: cpufreq: Fix hotplug-suspend race during reboot
+
+From: Tianxiang Chen <nanmu@xiaomi.com>
+
+commit a9029dd55696c651ee46912afa2a166fa456bb3e upstream.
+
+During system reboot, cpufreq_suspend() is called via the
+kernel_restart() -> device_shutdown() path. Unlike the normal system
+suspend path, the reboot path does not call freeze_processes(), so
+userspace processes and kernel threads remain active.
+
+This allows CPU hotplug operations to run concurrently with
+cpufreq_suspend(). The original code has no synchronization with CPU
+hotplug, leading to a race condition where governor_data can be freed
+by the hotplug path while cpufreq_suspend() is still accessing it,
+resulting in a null pointer dereference:
+
+  Unable to handle kernel NULL pointer dereference
+  Call Trace:
+   do_kernel_fault+0x28/0x3c
+   cpufreq_suspend+0xdc/0x160
+   device_shutdown+0x18/0x200
+   kernel_restart+0x40/0x80
+   arm64_sys_reboot+0x1b0/0x200
+
+Fix this by adding cpus_read_lock()/cpus_read_unlock() to
+cpufreq_suspend() to block CPU hotplug operations while suspend is in
+progress.
+
+Fixes: 65650b35133f ("cpufreq: Avoid cpufreq_suspend() deadlock on system shutdown")
+Signed-off-by: Tianxiang Chen <nanmu@xiaomi.com>
+Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
+Cc: All applicable <stable@vger.kernel.org>
+[ rjw: Changelog edits ]
+Link: https://patch.msgid.link/20260408141914.35281-1-nanmu@xiaomi.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/cpufreq.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -1972,6 +1972,7 @@ void cpufreq_suspend(void)
+       if (!cpufreq_driver)
+               return;
++      cpus_read_lock();
+       if (!has_target() && !cpufreq_driver->suspend)
+               goto suspend;
+@@ -1991,6 +1992,7 @@ void cpufreq_suspend(void)
+ suspend:
+       cpufreq_suspended = true;
++      cpus_read_unlock();
+ }
+ /**
diff --git a/queue-7.1/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch b/queue-7.1/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch
new file mode 100644 (file)
index 0000000..608d456
--- /dev/null
@@ -0,0 +1,51 @@
+From bcbdaa1086c25a8a5d48e04e1b82fdfb0682b681 Mon Sep 17 00:00:00 2001
+From: Fushuai Wang <wangfushuai@baidu.com>
+Date: Wed, 20 May 2026 11:21:19 +0800
+Subject: cpufreq: intel_pstate: Sync policy->cur during CPU offline
+
+From: Fushuai Wang <wangfushuai@baidu.com>
+
+commit bcbdaa1086c25a8a5d48e04e1b82fdfb0682b681 upstream.
+
+When a CPU goes offline with HWP disabled, intel_pstate_set_min_pstate()
+sets the MSR_IA32_PERF_CTL to minimum frequency to prevent SMT siblings
+from being restricted. However, the policy->cur value was not updated,
+leaving it at the previous value.
+
+When the CPU comes back online, governor->limits() checks if target_freq
+equals policy->cur and skips the frequency adjustment if they match. Since
+policy->cur still holds the previous value, the governor does not call
+cpufreq_driver->target to update MSR_IA32_PERF_CTL.
+
+Fix this by synchronizing policy->cur with the hardware state when setting
+minimum pstate during CPU offline.
+
+Fixes: bb18008f8086 ("intel_pstate: Set core to min P state during core offline")
+Cc: stable@vger.kernel.org # 3.15+
+Suggested-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Signed-off-by: Fushuai Wang <wangfushuai@baidu.com>
+[ rjw: Subject refinement ]
+Link: https://patch.msgid.link/20260520032119.30615-1-fushuai.wang@linux.dev
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/intel_pstate.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/cpufreq/intel_pstate.c
++++ b/drivers/cpufreq/intel_pstate.c
+@@ -2984,10 +2984,12 @@ static int intel_cpufreq_cpu_offline(str
+        * from getting to lower performance levels, so force the minimum
+        * performance on CPU offline to prevent that from happening.
+        */
+-      if (hwp_active)
++      if (hwp_active) {
+               intel_pstate_hwp_offline(cpu);
+-      else
++      } else {
+               intel_pstate_set_min_pstate(cpu);
++              policy->cur = cpu->pstate.min_freq;
++      }
+       intel_pstate_exit_perf_limits(policy);
diff --git a/queue-7.1/cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch b/queue-7.1/cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch
new file mode 100644 (file)
index 0000000..4b4df0c
--- /dev/null
@@ -0,0 +1,43 @@
+From 266d3dd8b757b48a576e90f018b51f7b7563cc32 Mon Sep 17 00:00:00 2001
+From: Yuho Choi <dbgh9129@gmail.com>
+Date: Thu, 16 Apr 2026 10:46:21 -0400
+Subject: cpufreq: pcc: fix use-after-free and double free in _OSC evaluation
+
+From: Yuho Choi <dbgh9129@gmail.com>
+
+commit 266d3dd8b757b48a576e90f018b51f7b7563cc32 upstream.
+
+pcc_cpufreq_do_osc() calls acpi_evaluate_object() twice for the
+two-phase _OSC negotiation. Between the two calls it freed
+output.pointer but left output.length unchanged. Since
+acpi_evaluate_object() treats a non-zero length with a non-NULL
+pointer as an existing buffer to write into, the second call wrote
+into freed memory (use-after-free). The subsequent kfree(output.pointer)
+at out_free then freed the same pointer a second time (double free).
+
+Reset output.pointer to NULL and output.length to ACPI_ALLOCATE_BUFFER
+after freeing the first result, so ACPICA allocates a fresh buffer for
+each phase independently.
+
+Fixes: 0f1d683fb35d ("[CPUFREQ] Processor Clocking Control interface driver")
+Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
+Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
+Cc: All applicable <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20260416144621.93964-1-dbgh9129@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/pcc-cpufreq.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/cpufreq/pcc-cpufreq.c
++++ b/drivers/cpufreq/pcc-cpufreq.c
+@@ -352,6 +352,8 @@ static int __init pcc_cpufreq_do_osc(acp
+       }
+       kfree(output.pointer);
++      output.pointer = NULL;
++      output.length = ACPI_ALLOCATE_BUFFER;
+       capabilities[0] = 0x0;
+       capabilities[1] = 0x1;
diff --git a/queue-7.1/cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch b/queue-7.1/cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch
new file mode 100644 (file)
index 0000000..5f28bf9
--- /dev/null
@@ -0,0 +1,44 @@
+From bcb8889c4981fdde42d4fd2c29a77d510fe21da2 Mon Sep 17 00:00:00 2001
+From: Guangshuo Li <lgs201920130244@gmail.com>
+Date: Sat, 2 May 2026 03:00:05 +0800
+Subject: cpufreq: qcom-cpufreq-hw: Fix possible double free
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+commit bcb8889c4981fdde42d4fd2c29a77d510fe21da2 upstream.
+
+qcom_cpufreq.data is allocated with devm_kzalloc() in probe() as an
+array of per-domain data. qcom_cpufreq_hw_cpu_init() stores a pointer to
+one element of this array in policy->driver_data.
+
+qcom_cpufreq_hw_cpu_exit() currently calls kfree() on policy->driver_data.
+This is not valid because the memory is devm-managed. For the first
+domain, this can free the devm-managed allocation while the devres entry
+is still active, leading to a possible double free when the platform
+device is later detached. For other domains, the pointer may refer to an
+element inside the array rather than the allocation base.
+
+Remove the kfree(data) call and let devres release qcom_cpufreq.data.
+
+This issue was found by a static analysis tool I am developing.
+
+Fixes: 054a3ef683a1 ("cpufreq: qcom-hw: Allocate qcom_cpufreq_data during probe")
+Cc: stable@vger.kernel.org
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/qcom-cpufreq-hw.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/cpufreq/qcom-cpufreq-hw.c
++++ b/drivers/cpufreq/qcom-cpufreq-hw.c
+@@ -578,7 +578,6 @@ static void qcom_cpufreq_hw_cpu_exit(str
+       dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
+       qcom_cpufreq_hw_lmh_exit(data);
+       kfree(policy->freq_table);
+-      kfree(data);
+ }
+ static void qcom_cpufreq_ready(struct cpufreq_policy *policy)
diff --git a/queue-7.1/firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch b/queue-7.1/firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch
new file mode 100644 (file)
index 0000000..e9658db
--- /dev/null
@@ -0,0 +1,73 @@
+From 896df22ee57648b0c505bd76ddbc6b2341834696 Mon Sep 17 00:00:00 2001
+From: Guangshuo Li <lgs201920130244@gmail.com>
+Date: Tue, 5 May 2026 17:12:31 +0800
+Subject: firmware_loader: fix device reference leak in firmware_upload_register()
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+commit 896df22ee57648b0c505bd76ddbc6b2341834696 upstream.
+
+firmware_upload_register()
+  -> fw_create_instance()
+     -> device_initialize()
+
+After fw_create_instance() succeeds, the lifetime of the embedded struct
+device is expected to be managed through the device core reference
+counting, since fw_create_instance() has already called
+device_initialize().
+
+In firmware_upload_register(), if alloc_lookup_fw_priv() fails after
+fw_create_instance() succeeds, the code reaches free_fw_sysfs and frees
+fw_sysfs directly instead of releasing the device reference with
+put_device(). This may leave the reference count of the embedded struct
+device unbalanced, resulting in a refcount leak.
+
+The issue was identified by a static analysis tool I developed and
+confirmed by manual review. Fix this by using put_device(fw_dev) in the
+failure path and letting fw_dev_release() handle the final cleanup,
+instead of freeing the instance directly from the error path.
+
+Fixes: 97730bbb242c ("firmware_loader: Add firmware-upload support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Link: https://patch.msgid.link/20260505091231.607089-1-lgs201920130244@gmail.com
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/firmware_loader/sysfs_upload.c |    8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/base/firmware_loader/sysfs_upload.c
++++ b/drivers/base/firmware_loader/sysfs_upload.c
+@@ -343,7 +343,6 @@ firmware_upload_register(struct module *
+               goto free_fw_upload_priv;
+       }
+       fw_upload->priv = fw_sysfs;
+-      fw_sysfs->fw_upload_priv = fw_upload_priv;
+       fw_dev = &fw_sysfs->dev;
+       ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv,  NULL, 0, 0,
+@@ -351,10 +350,12 @@ firmware_upload_register(struct module *
+       if (ret != 0) {
+               if (ret > 0)
+                       ret = -EINVAL;
+-              goto free_fw_sysfs;
++              put_device(fw_dev);
++              goto free_fw_upload_priv;
+       }
+       fw_priv->is_paged_buf = true;
+       fw_sysfs->fw_priv = fw_priv;
++      fw_sysfs->fw_upload_priv = fw_upload_priv;
+       ret = device_add(fw_dev);
+       if (ret) {
+@@ -365,9 +366,6 @@ firmware_upload_register(struct module *
+       return fw_upload;
+-free_fw_sysfs:
+-      kfree(fw_sysfs);
+-
+ free_fw_upload_priv:
+       kfree(fw_upload_priv);
diff --git a/queue-7.1/hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch b/queue-7.1/hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch
new file mode 100644 (file)
index 0000000..5b9effd
--- /dev/null
@@ -0,0 +1,146 @@
+From 75fe87e19d8aff81eb2c64d15d244ab8da4de945 Mon Sep 17 00:00:00 2001
+From: Manish Khadka <maskmemanish@gmail.com>
+Date: Fri, 15 May 2026 23:17:52 +0545
+Subject: HID: appleir: fix UAF on pending key_up_timer in remove()
+
+From: Manish Khadka <maskmemanish@gmail.com>
+
+commit 75fe87e19d8aff81eb2c64d15d244ab8da4de945 upstream.
+
+appleir_remove() runs hid_hw_stop() before timer_delete_sync().
+hid_hw_stop() synchronously unregisters the HID input device via
+hid_disconnect() -> hidinput_disconnect() -> input_unregister_device(),
+which drops the last reference and frees the underlying input_dev when
+no userspace handle holds it open.
+
+key_up_tick() reads appleir->input_dev and calls input_report_key() /
+input_sync() on it.  The timer is armed from appleir_raw_event() with
+a HZ/8 (~125 ms) timeout on every keydown and key-repeat report.  If a
+key was pressed shortly before the device is disconnected, the timer
+can fire after hid_hw_stop() has freed input_dev but before the
+teardown drains it.
+
+A simple reorder is not sufficient.  Putting the timer drain first
+still leaves a window where a USB URB completion (raw_event) running
+during hid_hw_stop() can call mod_timer() and re-arm the timer, which
+then fires after hidinput_disconnect() has freed input_dev.  The same
+URB-completion window also lets raw_event() reach key_up(), key_down()
+and battery_flat() directly, all of which dereference
+appleir->input_dev.
+
+Introduce a 'removing' flag on struct appleir, gated by the existing
+spinlock.  appleir_remove() sets the flag under the lock and then
+shuts down the timer with timer_shutdown_sync(), which both drains any
+in-flight callback and permanently disables further mod_timer() calls.
+appleir_raw_event() and key_up_tick() bail out early if the flag is
+set, so no path can arm or run the timer, or dereference
+appleir->input_dev, after remove() has started tearing down.
+
+The keyrepeat and flatbattery branches of appleir_raw_event()
+previously called into the input layer without holding the spinlock;
+take it now so the flag check is well-defined.  This incidentally
+closes a pre-existing read-side race on appleir->current_key in the
+keyrepeat branch.
+
+This bug is structurally a sibling of commit 4db2af929279 ("HID:
+appletb-kbd: fix UAF in inactivity-timer cleanup path") and has been
+present since the driver was introduced.
+
+Fixes: 9a4a5574ce42 ("HID: appleir: add support for Apple ir devices")
+Cc: stable@vger.kernel.org
+Signed-off-by: Manish Khadka <maskmemanish@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-appleir.c |   45 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 35 insertions(+), 10 deletions(-)
+
+--- a/drivers/hid/hid-appleir.c
++++ b/drivers/hid/hid-appleir.c
+@@ -109,9 +109,10 @@ struct appleir {
+       struct hid_device *hid;
+       unsigned short keymap[ARRAY_SIZE(appleir_key_table)];
+       struct timer_list key_up_timer; /* timer for key up */
+-      spinlock_t lock;                /* protects .current_key */
++      spinlock_t lock;                /* protects .current_key, .removing */
+       int current_key;                /* the currently pressed key */
+       int prev_key_idx;               /* key index in a 2 packets message */
++      bool removing;                  /* set during teardown; gates input_dev access */
+ };
+ static int get_key(int data)
+@@ -172,7 +173,7 @@ static void key_up_tick(struct timer_lis
+       unsigned long flags;
+       spin_lock_irqsave(&appleir->lock, flags);
+-      if (appleir->current_key) {
++      if (!appleir->removing && appleir->current_key) {
+               key_up(hid, appleir, appleir->current_key);
+               appleir->current_key = 0;
+       }
+@@ -195,6 +196,10 @@ static int appleir_raw_event(struct hid_
+               int index;
+               spin_lock_irqsave(&appleir->lock, flags);
++              if (appleir->removing) {
++                      spin_unlock_irqrestore(&appleir->lock, flags);
++                      goto out;
++              }
+               /*
+                * If we already have a key down, take it up before marking
+                * this one down
+@@ -229,17 +234,25 @@ static int appleir_raw_event(struct hid_
+       appleir->prev_key_idx = 0;
+       if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) {
+-              key_down(hid, appleir, appleir->current_key);
+-              /*
+-               * Remote doesn't do key up, either pull them up, in the test
+-               * above, or here set a timer which pulls them up after 1/8 s
+-               */
+-              mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
++              spin_lock_irqsave(&appleir->lock, flags);
++              if (!appleir->removing) {
++                      key_down(hid, appleir, appleir->current_key);
++                      /*
++                       * Remote doesn't do key up, either pull them up, in
++                       * the test above, or here set a timer which pulls them
++                       * up after 1/8 s
++                       */
++                      mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
++              }
++              spin_unlock_irqrestore(&appleir->lock, flags);
+               goto out;
+       }
+       if (!memcmp(data, flatbattery, sizeof(flatbattery))) {
+-              battery_flat(appleir);
++              spin_lock_irqsave(&appleir->lock, flags);
++              if (!appleir->removing)
++                      battery_flat(appleir);
++              spin_unlock_irqrestore(&appleir->lock, flags);
+               /* Fall through */
+       }
+@@ -318,8 +331,20 @@ fail:
+ static void appleir_remove(struct hid_device *hid)
+ {
+       struct appleir *appleir = hid_get_drvdata(hid);
++      unsigned long flags;
++
++      /*
++       * Mark the driver as tearing down so that any concurrent raw_event
++       * (e.g. from a USB URB completion that hid_hw_stop() has not yet
++       * killed) and the key_up_timer softirq stop touching input_dev
++       * before hid_hw_stop() frees it via hidinput_disconnect().
++       */
++      spin_lock_irqsave(&appleir->lock, flags);
++      appleir->removing = true;
++      spin_unlock_irqrestore(&appleir->lock, flags);
++
++      timer_shutdown_sync(&appleir->key_up_timer);
+       hid_hw_stop(hid);
+-      timer_delete_sync(&appleir->key_up_timer);
+ }
+ static const struct hid_device_id appleir_devices[] = {
diff --git a/queue-7.1/hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch b/queue-7.1/hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..fa2f93b
--- /dev/null
@@ -0,0 +1,48 @@
+From db0a0768d09273aadadeb76730cd658d720333a4 Mon Sep 17 00:00:00 2001
+From: Tianchu Chen <flynnnchen@tencent.com>
+Date: Fri, 29 May 2026 13:42:47 +0000
+Subject: HID: hid-goodix-spi: validate report size to prevent stack buffer overflow
+
+From: Tianchu Chen <flynnnchen@tencent.com>
+
+commit db0a0768d09273aadadeb76730cd658d720333a4 upstream.
+
+goodix_hid_set_raw_report() builds a protocol frame in a 128-byte stack
+buffer (tmp_buf), writing an 11-12 byte header followed by the
+caller-supplied report data.  The HID core caps report size at
+HID_MAX_BUFFER_SIZE (16384) by default, while the driver does not set
+hid_ll_driver.max_buffer_size and performs no bounds checking before
+copying the payload:
+
+    memcpy(tmp_buf + tx_len, buf, len);
+
+A hidraw SET_REPORT ioctl with a report larger than ~116 bytes
+overflows the stack buffer.
+
+Add a size check after constructing the header, rejecting reports that
+would exceed the buffer capacity.
+
+Discovered by Atuin - Automated Vulnerability Discovery Engine.
+
+Fixes: 75e16c8ce283 ("HID: hid-goodix: Add Goodix HID-over-SPI driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
+Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-goodix-spi.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/hid/hid-goodix-spi.c
++++ b/drivers/hid/hid-goodix-spi.c
+@@ -520,6 +520,9 @@ static int goodix_hid_set_raw_report(str
+       memcpy(tmp_buf + tx_len, args, args_len);
+       tx_len += args_len;
++      if (tx_len + len > sizeof(tmp_buf))
++              return -EINVAL;
++
+       memcpy(tmp_buf + tx_len, buf, len);
+       tx_len += len;
diff --git a/queue-7.1/hid-hid-lenovo-go-cancel-cfg_setup-work-in-hid_go_cfg_remove.patch b/queue-7.1/hid-hid-lenovo-go-cancel-cfg_setup-work-in-hid_go_cfg_remove.patch
new file mode 100644 (file)
index 0000000..637f9c5
--- /dev/null
@@ -0,0 +1,56 @@
+From 73fde0cbff7d9d618591774a12c23434232752c1 Mon Sep 17 00:00:00 2001
+From: Manish Khadka <maskmemanish@gmail.com>
+Date: Fri, 15 May 2026 23:30:11 +0545
+Subject: HID: hid-lenovo-go: cancel cfg_setup work in hid_go_cfg_remove()
+
+From: Manish Khadka <maskmemanish@gmail.com>
+
+commit 73fde0cbff7d9d618591774a12c23434232752c1 upstream.
+
+hid_go_cfg_probe() initialises drvdata.go_cfg_setup and schedules it
+to run 2 ms later:
+
+    INIT_DELAYED_WORK(&drvdata.go_cfg_setup, &cfg_setup);
+    schedule_delayed_work(&drvdata.go_cfg_setup, msecs_to_jiffies(2));
+
+cfg_setup() dereferences drvdata.hdev to issue MCU command requests.
+hid_go_cfg_remove() tears down sysfs and stops the HID device, but
+never drains the delayed work.  If the device is unbound within the
+2 ms scheduling delay (a probe failure rolling back via remove, or a
+fast rmmod after probe), the work fires after hid_destroy_device()
+has dropped its reference and released the underlying hdev struct,
+leaving cfg_setup() with a stale drvdata.hdev pointer.
+
+Mirror the sibling driver hid-lenovo-go-s.c, whose hid_gos_cfg_remove()
+already calls cancel_delayed_work_sync() on its analogous work, and
+drain go_cfg_setup at the top of hid_go_cfg_remove().  The cancel
+must come before guard(mutex)(&drvdata.cfg_mutex) because cfg_setup()
+acquires that mutex; reversing the order would deadlock.
+
+Fixes: d69ccfcbc955 ("HID: hid-lenovo-go: Add Lenovo Legion Go Series HID Driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Manish Khadka <maskmemanish@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-lenovo-go.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/hid/hid-lenovo-go.c
++++ b/drivers/hid/hid-lenovo-go.c
+@@ -2405,6 +2405,15 @@ static int hid_go_cfg_probe(struct hid_d
+ static void hid_go_cfg_remove(struct hid_device *hdev)
+ {
++      /*
++       * cfg_setup is scheduled from hid_go_cfg_probe() with a 2 ms delay
++       * and dereferences drvdata.hdev.  Drain it here before tearing
++       * down so the workqueue cannot run after hid_destroy_device()'s
++       * put_device() has released the underlying hdev and dereference
++       * a stale drvdata.hdev pointer.
++       */
++      cancel_delayed_work_sync(&drvdata.go_cfg_setup);
++
+       guard(mutex)(&drvdata.cfg_mutex);
+       sysfs_remove_groups(&hdev->dev.kobj, top_level_attr_groups);
+       hid_hw_close(hdev);
diff --git a/queue-7.1/hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch b/queue-7.1/hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch
new file mode 100644 (file)
index 0000000..ce443c3
--- /dev/null
@@ -0,0 +1,105 @@
+From 46c8beeccd8ab2c863827254a85ea877654a3534 Mon Sep 17 00:00:00 2001
+From: Manish Khadka <maskmemanish@gmail.com>
+Date: Fri, 15 May 2026 22:27:00 +0545
+Subject: HID: letsketch: fix UAF on inrange_timer at driver unbind
+
+From: Manish Khadka <maskmemanish@gmail.com>
+
+commit 46c8beeccd8ab2c863827254a85ea877654a3534 upstream.
+
+letsketch_driver does not provide a .remove callback, but
+letsketch_probe() arms a per-device timer:
+
+    timer_setup(&data->inrange_timer, letsketch_inrange_timeout, 0);
+
+The timer is re-armed from letsketch_raw_event() with a 100 ms
+timeout on every pen-in-range report, and its callback dereferences
+data->input_tablet to deliver a synthetic BTN_TOOL_PEN release.
+
+letsketch_data is allocated with devm_kzalloc(), and its input_dev
+fields are devm-allocated via letsketch_setup_input_tablet().  On
+device unbind (USB unplug or rmmod), the HID core runs its default
+teardown and devm cleanup frees both letsketch_data and the input
+devices.  Because no .remove callback exists, nothing drains the
+timer first: if raw_event armed it within ~100 ms of the unbind,
+the pending timer fires on freed memory.  This is a UAF read of
+data and of data->input_tablet, followed by input_report_key() /
+input_sync() into the freed input_dev.
+
+The same problem can occur on the probe error path: if
+hid_hw_start() enabled I/O on an always-poll-quirk device and then
+failed, raw_event may have armed the timer before devm releases
+data.
+
+Fix by adding a .remove callback that calls hid_hw_stop() first.
+hid_hw_stop() synchronously kills the URBs that deliver raw_event(),
+so once it returns no path can re-arm the timer.  timer_shutdown_sync()
+then drains any in-flight callback and permanently disables further
+mod_timer() calls.  Apply the same timer_shutdown_sync() in the probe
+error path so the timer is guaranteed not to outlive data.
+
+Fixes: 33a5c2793451 ("HID: Add new Letsketch tablet driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Manish Khadka <maskmemanish@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-letsketch.c |   36 +++++++++++++++++++++++++++++++++---
+ 1 file changed, 33 insertions(+), 3 deletions(-)
+
+--- a/drivers/hid/hid-letsketch.c
++++ b/drivers/hid/hid-letsketch.c
+@@ -296,13 +296,42 @@ static int letsketch_probe(struct hid_de
+       ret = letsketch_setup_input_tablet(data);
+       if (ret)
+-              return ret;
++              goto err_shutdown_timer;
+       ret = letsketch_setup_input_tablet_pad(data);
+       if (ret)
+-              return ret;
++              goto err_shutdown_timer;
+-      return hid_hw_start(hdev, HID_CONNECT_HIDRAW);
++      ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
++      if (ret)
++              goto err_shutdown_timer;
++
++      return 0;
++
++err_shutdown_timer:
++      /*
++       * Drain any pending callback and permanently disable the timer
++       * before devm releases data: if hid_hw_start() enabled I/O on an
++       * always-poll-quirk device and then failed, raw_event may have
++       * armed the timer already.
++       */
++      timer_shutdown_sync(&data->inrange_timer);
++      return ret;
++}
++
++static void letsketch_remove(struct hid_device *hdev)
++{
++      struct letsketch_data *data = hid_get_drvdata(hdev);
++
++      /*
++       * hid_hw_stop() synchronously kills the URBs that deliver
++       * raw_event(), so once it returns no path can re-arm
++       * inrange_timer.  timer_shutdown_sync() then drains any
++       * in-flight callback and permanently disables further
++       * mod_timer() calls before devm releases data.
++       */
++      hid_hw_stop(hdev);
++      timer_shutdown_sync(&data->inrange_timer);
+ }
+ static const struct hid_device_id letsketch_devices[] = {
+@@ -315,6 +344,7 @@ static struct hid_driver letsketch_drive
+       .name = "letsketch",
+       .id_table = letsketch_devices,
+       .probe = letsketch_probe,
++      .remove = letsketch_remove,
+       .raw_event = letsketch_raw_event,
+ };
+ module_hid_driver(letsketch_driver);
diff --git a/queue-7.1/hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch b/queue-7.1/hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch
new file mode 100644 (file)
index 0000000..5fc9624
--- /dev/null
@@ -0,0 +1,68 @@
+From 7705b4140d188ce22656f6e541ae7ef834c7e11a Mon Sep 17 00:00:00 2001
+From: Maoyi Xie <maoyixie.tju@gmail.com>
+Date: Thu, 18 Jun 2026 15:06:35 +0800
+Subject: HID: lg-g15: cancel pending work on remove to fix a use-after-free
+
+From: Maoyi Xie <maoyixie.tju@gmail.com>
+
+commit 7705b4140d188ce22656f6e541ae7ef834c7e11a upstream.
+
+lg_g15_data is allocated with devm and holds a work item. The report
+handlers schedule that work straight from device input.
+lg_g15_event() and lg_g15_v2_event() do it on the backlight cycle key,
+and lg_g510_leds_event() does it too. The worker dereferences the
+lg_g15_data back through container_of.
+
+The driver had no remove callback and never cancelled the work. So if a
+report scheduled the work and the keyboard was then unplugged, devres
+freed lg_g15_data while the work was still pending or running, and the
+worker touched freed memory. This is a use-after-free. It is reachable
+as a race on device unplug.
+
+Add a remove callback that cancels the work before devres frees the
+state. g15->work is only initialized for the models that schedule it
+(G15, G15 v2, G510). The G13 and Z-10 leave it zeroed, so guard the
+cancel on g15->work.func to avoid cancelling a work that was never set
+up. The g15 NULL test mirrors the one already in lg_g15_raw_event().
+
+Fixes: 97b741aba918 ("HID: lg-g15: Add keyboard and LCD backlight control")
+Cc: stable@vger.kernel.org
+Suggested-by: Hans de Goede <hansg@kernel.org>
+Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
+Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-lg-g15.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/hid/hid-lg-g15.c
++++ b/drivers/hid/hid-lg-g15.c
+@@ -1374,11 +1374,27 @@ static const struct hid_device_id lg_g15
+ };
+ MODULE_DEVICE_TABLE(hid, lg_g15_devices);
++static void lg_g15_remove(struct hid_device *hdev)
++{
++      struct lg_g15_data *g15 = hid_get_drvdata(hdev);
++
++      /*
++       * g15->work is only initialized for the models that schedule it
++       * (G15, G15 v2, G510). The G13 and Z-10 leave it zeroed, so only
++       * cancel it when it was set up.
++       */
++      if (g15 && g15->work.func)
++              cancel_work_sync(&g15->work);
++
++      hid_hw_stop(hdev);
++}
++
+ static struct hid_driver lg_g15_driver = {
+       .name                   = "lg-g15",
+       .id_table               = lg_g15_devices,
+       .raw_event              = lg_g15_raw_event,
+       .probe                  = lg_g15_probe,
++      .remove                 = lg_g15_remove,
+ };
+ module_hid_driver(lg_g15_driver);
diff --git a/queue-7.1/hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch b/queue-7.1/hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch
new file mode 100644 (file)
index 0000000..e5c6946
--- /dev/null
@@ -0,0 +1,154 @@
+From 8813b0612275cc61fe9e6603d0ee019247ade6be Mon Sep 17 00:00:00 2001
+From: Trung Nguyen <trungnh@cystack.net>
+Date: Thu, 2 Jul 2026 00:13:19 +0700
+Subject: HID: multitouch: fix out-of-bounds bit access on mt_io_flags
+
+From: Trung Nguyen <trungnh@cystack.net>
+
+commit 8813b0612275cc61fe9e6603d0ee019247ade6be upstream.
+
+mt_io_flags is a single unsigned long, but mt_process_slot(),
+mt_release_pending_palms() and mt_release_contacts() use it as a
+per-slot bitmap indexed by the slot number. That slot number is only
+bounded by td->maxcontacts, which is taken from the device's
+ContactCountMaximum feature report and can be up to 255, not by
+BITS_PER_LONG.
+
+As a result, a multitouch device that advertises a large contact count
+makes set_bit()/clear_bit() operate past the mt_io_flags word and
+corrupt the adjacent members of struct mt_device. The sticky-fingers
+release timer is the easiest way to reach this. mt_release_contacts()
+runs
+
+       for (i = 0; i < mt->num_slots; i++)
+               clear_bit(i, &td->mt_io_flags);
+
+with num_slots == maxcontacts. For maxcontacts around 250 the loop
+clears the bits that overlap td->applications.next, zeroing that list
+head, and the list_for_each_entry() that immediately follows then
+dereferences NULL. The kernel panics from timer (softirq) context. On a
+KASAN build this shows up as a general protection fault in
+mt_release_contacts() with a null-ptr-deref at offset 0x58, which is
+offsetof(struct mt_application, num_received).
+
+The state is reachable from an untrusted USB or Bluetooth HID
+multitouch device; no local privileges are required.
+
+Store the per-slot active state in a separately allocated bitmap sized
+for maxcontacts, the same pattern already used for pending_palm_slots,
+and keep only MT_IO_FLAGS_RUNNING in mt_io_flags. The two
+"mt_io_flags & MT_IO_SLOTS_MASK" arming checks become
+bitmap_empty(td->active_slots, td->maxcontacts).
+
+Move MT_IO_FLAGS_RUNNING back to bit 0. It was bumped to bit 32 by the
+same commit to leave the low byte for the slot bits; with the slot bits
+gone it fits in bit 0 again, which also keeps it within the unsigned
+long on 32-bit.
+
+Fixes: 46f781e0d151 ("HID: multitouch: fix sticky fingers")
+Cc: stable@vger.kernel.org
+Signed-off-by: Trung Nguyen <trungnh@cystack.net>
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-multitouch.c |   32 ++++++++++++++++++++------------
+ 1 file changed, 20 insertions(+), 12 deletions(-)
+
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -31,6 +31,7 @@
+  * [1] https://gitlab.freedesktop.org/libevdev/hid-tools
+  */
++#include <linux/bitmap.h>
+ #include <linux/bits.h>
+ #include <linux/device.h>
+ #include <linux/hid.h>
+@@ -97,8 +98,7 @@ enum report_mode {
+       TOUCHPAD_REPORT_ALL = TOUCHPAD_REPORT_BUTTONS | TOUCHPAD_REPORT_CONTACTS,
+ };
+-#define MT_IO_SLOTS_MASK              GENMASK(7, 0) /* reserve first 8 bits for slot tracking */
+-#define MT_IO_FLAGS_RUNNING           32
++#define MT_IO_FLAGS_RUNNING           0
+ static const bool mtrue = true;               /* default for true */
+ static const bool mfalse;             /* default for false */
+@@ -174,10 +174,9 @@ struct mt_device {
+       struct timer_list release_timer;        /* to release sticky fingers */
+       struct hid_haptic_device *haptic;       /* haptic related configuration */
+       struct hid_device *hdev;        /* hid_device we're attached to */
+-      unsigned long mt_io_flags;      /* mt flags (MT_IO_FLAGS_RUNNING)
+-                                       * first 8 bits are reserved for keeping the slot
+-                                       * states, this is fine because we only support up
+-                                       * to 250 slots (MT_MAX_MAXCONTACT)
++      unsigned long mt_io_flags;      /* mt flags (MT_IO_FLAGS_RUNNING) */
++      unsigned long *active_slots;    /* bitmap of slots with an active
++                                       * contact, sized for maxcontacts
+                                        */
+       __u8 inputmode_value;   /* InputMode HID feature value */
+       __u8 maxcontacts;
+@@ -1033,7 +1032,7 @@ static void mt_release_pending_palms(str
+       for_each_set_bit(slotnum, app->pending_palm_slots, td->maxcontacts) {
+               clear_bit(slotnum, app->pending_palm_slots);
+-              clear_bit(slotnum, &td->mt_io_flags);
++              clear_bit(slotnum, td->active_slots);
+               input_mt_slot(input, slotnum);
+               input_mt_report_slot_inactive(input);
+@@ -1244,9 +1243,9 @@ static int mt_process_slot(struct mt_dev
+               input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+               input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
+-              set_bit(slotnum, &td->mt_io_flags);
++              set_bit(slotnum, td->active_slots);
+       } else {
+-              clear_bit(slotnum, &td->mt_io_flags);
++              clear_bit(slotnum, td->active_slots);
+       }
+       return 0;
+@@ -1381,7 +1380,7 @@ static void mt_touch_report(struct hid_d
+        * defect.
+        */
+       if (app->quirks & MT_QUIRK_STICKY_FINGERS) {
+-              if (td->mt_io_flags & MT_IO_SLOTS_MASK)
++              if (!bitmap_empty(td->active_slots, td->maxcontacts))
+                       mod_timer(&td->release_timer,
+                                 jiffies + msecs_to_jiffies(100));
+               else
+@@ -1440,6 +1439,15 @@ static int mt_touch_input_configured(str
+       if (td->is_pressurepad)
+               __set_bit(INPUT_PROP_PRESSUREPAD, input->propbit);
++      if (!td->active_slots) {
++              td->active_slots = devm_kcalloc(&td->hdev->dev,
++                                              BITS_TO_LONGS(td->maxcontacts),
++                                              sizeof(long),
++                                              GFP_KERNEL);
++              if (!td->active_slots)
++                      return -ENOMEM;
++      }
++
+       app->pending_palm_slots = devm_kcalloc(&hi->input->dev,
+                                              BITS_TO_LONGS(td->maxcontacts),
+                                              sizeof(long),
+@@ -1917,7 +1925,7 @@ static void mt_release_contacts(struct h
+                       for (i = 0; i < mt->num_slots; i++) {
+                               input_mt_slot(input_dev, i);
+                               input_mt_report_slot_inactive(input_dev);
+-                              clear_bit(i, &td->mt_io_flags);
++                              clear_bit(i, td->active_slots);
+                       }
+                       input_mt_sync_frame(input_dev);
+                       input_sync(input_dev);
+@@ -1940,7 +1948,7 @@ static void mt_expired_timeout(struct ti
+        */
+       if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
+               return;
+-      if (td->mt_io_flags & MT_IO_SLOTS_MASK)
++      if (!bitmap_empty(td->active_slots, td->maxcontacts))
+               mt_release_contacts(hdev);
+       clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
+ }
diff --git a/queue-7.1/hid-pidff-use-correct-effect-type-in-effect-update.patch b/queue-7.1/hid-pidff-use-correct-effect-type-in-effect-update.patch
new file mode 100644 (file)
index 0000000..88d821d
--- /dev/null
@@ -0,0 +1,43 @@
+From b251598b8bf37300510868f739a79e07800d41ce Mon Sep 17 00:00:00 2001
+From: Oleg Makarenko <oleg@makarenk.ooo>
+Date: Tue, 9 Jun 2026 19:00:27 +0300
+Subject: HID: pidff: Use correct effect type in effect update
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Oleg Makarenko <oleg@makarenk.ooo>
+
+commit b251598b8bf37300510868f739a79e07800d41ce upstream.
+
+When updating an existing effect, the effect type from the last created
+effect was sent to the device instead of the updated one.
+This caused incorrect reports when a game creates multiple different
+effects and updates only one that is not the last created.
+
+Fixes FFB in multiple games that create multiple simultaneous effects
+(Forza Horizon 5/6).
+
+Fixes: 224ee88fe395 ("Input: add force feedback driver for PID devices")
+Cc: stable@vger.kernel.org
+Tested-by: Oliver Roundtree <oroundtree1@gmail.com>
+Co-developed-by: Ryno Kotzé <lemon.xah@gmail.com>
+Signed-off-by: Ryno Kotzé <lemon.xah@gmail.com>
+Signed-off-by: Oleg Makarenko <oleg@makarenk.ooo>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/usbhid/hid-pidff.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -522,7 +522,7 @@ static void pidff_set_effect_report(stru
+       pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
+               pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
+       pidff->set_effect_type->value[0] =
+-              pidff->create_new_effect_type->value[0];
++              pidff_get_effect_type_id(pidff, effect);
+       pidff_set_duration(&pidff->set_effect[PID_DURATION],
+                          effect->replay.length);
diff --git a/queue-7.1/hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch b/queue-7.1/hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch
new file mode 100644 (file)
index 0000000..8e40a66
--- /dev/null
@@ -0,0 +1,179 @@
+From f784fcea450617055d2d12eec5b2f6e0e38bf878 Mon Sep 17 00:00:00 2001
+From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Date: Wed, 10 Jun 2026 16:29:09 +0800
+Subject: HID: sensor-hub: Add sensor_hub_input_attr_read_values() for multi-byte reads
+
+From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+
+commit f784fcea450617055d2d12eec5b2f6e0e38bf878 upstream.
+
+sensor_hub_input_attr_get_raw_value() is limited to returning a single
+32-bit value, which is insufficient for sensors that report data larger
+than 32 bits, such as a quaternion with four s16 elements.
+
+Add sensor_hub_input_attr_read_values() that accepts a caller-provided
+buffer and accumulates incoming data until the buffer is full. The two
+paths are distinguished in sensor_hub_raw_event() by pending.max_raw_size
+being non-zero, preserving backward compatibility.
+
+Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Co-developed-by: Zhang Lixu <lixu.zhang@intel.com>
+Signed-off-by: Zhang Lixu <lixu.zhang@intel.com>
+Acked-by: Jiri Kosina <jkosina@suse.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-sensor-hub.c   |   77 +++++++++++++++++++++++++++++++++++++----
+ include/linux/hid-sensor-hub.h |   25 +++++++++++++
+ 2 files changed, 96 insertions(+), 6 deletions(-)
+
+--- a/drivers/hid/hid-sensor-hub.c
++++ b/drivers/hid/hid-sensor-hub.c
+@@ -286,6 +286,54 @@ done_proc:
+ }
+ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
++int sensor_hub_input_attr_read_values(struct hid_sensor_hub_device *hsdev,
++                                    u32 usage_id, u32 attr_usage_id,
++                                    u32 report_id,
++                                    enum sensor_hub_read_flags flag,
++                                    u32 buffer_size, u8 *buffer)
++{
++      struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
++      struct hid_report *report;
++      unsigned long flags;
++      long cycles;
++      int ret;
++
++      report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
++      if (!report)
++              return -EINVAL;
++
++      mutex_lock(hsdev->mutex_ptr);
++      if (flag == SENSOR_HUB_SYNC) {
++              memset(&hsdev->pending, 0, sizeof(hsdev->pending));
++              init_completion(&hsdev->pending.ready);
++              hsdev->pending.usage_id = usage_id;
++              hsdev->pending.attr_usage_id = attr_usage_id;
++              hsdev->pending.max_raw_size = buffer_size;
++              hsdev->pending.raw_data = buffer;
++
++              spin_lock_irqsave(&data->lock, flags);
++              hsdev->pending.status = true;
++              spin_unlock_irqrestore(&data->lock, flags);
++      }
++      mutex_lock(&data->mutex);
++      hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
++      mutex_unlock(&data->mutex);
++      ret = 0;
++      if (flag == SENSOR_HUB_SYNC) {
++              cycles = wait_for_completion_interruptible_timeout(&hsdev->pending.ready,
++                                                                 HZ * 5);
++              if (cycles == 0)
++                      ret = -ETIMEDOUT;
++              else if (cycles < 0)
++                      ret = cycles;
++
++              hsdev->pending.status = false;
++      }
++      mutex_unlock(hsdev->mutex_ptr);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(sensor_hub_input_attr_read_values);
+ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
+                                       u32 usage_id,
+@@ -478,6 +526,8 @@ static int sensor_hub_raw_event(struct h
+       struct hid_collection *collection = NULL;
+       void *priv = NULL;
+       struct hid_sensor_hub_device *hsdev = NULL;
++      u32 copy_size;
++      u32 avail;
+       hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n",
+                        report->id, size, report->type);
+@@ -518,12 +568,27 @@ static int sensor_hub_raw_event(struct h
+                                             hsdev->pending.attr_usage_id ==
+                                             report->field[i]->logical)) {
+                       hid_dbg(hdev, "data was pending ...\n");
+-                      hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
+-                      if (hsdev->pending.raw_data)
+-                              hsdev->pending.raw_size = sz;
+-                      else
+-                              hsdev->pending.raw_size = 0;
+-                      complete(&hsdev->pending.ready);
++                      if (hsdev->pending.max_raw_size) {
++                              if (hsdev->pending.index < hsdev->pending.max_raw_size) {
++                                      avail = hsdev->pending.max_raw_size - hsdev->pending.index;
++                                      copy_size = clamp(sz, 0U, avail);
++
++                                      memcpy(hsdev->pending.raw_data + hsdev->pending.index,
++                                             ptr, copy_size);
++                                      hsdev->pending.index += copy_size;
++                                      if (hsdev->pending.index >= hsdev->pending.max_raw_size) {
++                                              hsdev->pending.raw_size = hsdev->pending.index;
++                                              complete(&hsdev->pending.ready);
++                                      }
++                              }
++                      } else {
++                              hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
++                              if (hsdev->pending.raw_data)
++                                      hsdev->pending.raw_size = sz;
++                              else
++                                      hsdev->pending.raw_size = 0;
++                              complete(&hsdev->pending.ready);
++                      }
+               }
+               if (callback->capture_sample) {
+                       if (report->field[i]->logical)
+--- a/include/linux/hid-sensor-hub.h
++++ b/include/linux/hid-sensor-hub.h
+@@ -43,6 +43,8 @@ struct hid_sensor_hub_attribute_info {
+  * @attr_usage_id:    Usage Id of a field, e.g. X-axis for a gyro.
+  * @raw_size:         Response size for a read request.
+  * @raw_data:         Place holder for received response.
++ * @index:            Current write index into raw_data for multi-byte reads.
++ * @max_raw_size:     Total buffer size for multi-byte reads; 0 for single-value reads.
+  */
+ struct sensor_hub_pending {
+       bool status;
+@@ -51,6 +53,8 @@ struct sensor_hub_pending {
+       u32 attr_usage_id;
+       int raw_size;
+       u8  *raw_data;
++      u32 index;
++      u32 max_raw_size;
+ };
+ /**
+@@ -184,6 +188,27 @@ int sensor_hub_input_attr_get_raw_value(
+ );
+ /**
++ * sensor_hub_input_attr_read_values() - Synchronous multi-byte read request
++ * @hsdev:            Hub device instance.
++ * @usage_id:         Attribute usage id of parent physical device as per spec
++ * @attr_usage_id:    Attribute usage id as per spec
++ * @report_id:                Report id to look for
++ * @flag:             Synchronous or asynchronous read
++ * @buffer_size:      Size of the buffer in bytes
++ * @buffer:           Buffer to store the read data
++ *
++ * Issues a synchronous or asynchronous read request for an input attribute,
++ * accumulating data into the provided buffer until it is full.
++ * Return: 0 on success, -ETIMEDOUT if the device did not respond, or a
++ * negative error code.
++ */
++int sensor_hub_input_attr_read_values(struct hid_sensor_hub_device *hsdev,
++                                    u32 usage_id, u32 attr_usage_id,
++                                    u32 report_id,
++                                    enum sensor_hub_read_flags flag,
++                                    u32 buffer_size, u8 *buffer);
++
++/**
+ * sensor_hub_set_feature() - Feature set request
+ * @hsdev:     Hub device instance.
+ * @report_id: Report id to look for
diff --git a/queue-7.1/hid-uhid-convert-to-hid_safe_input_report.patch b/queue-7.1/hid-uhid-convert-to-hid_safe_input_report.patch
new file mode 100644 (file)
index 0000000..cc87842
--- /dev/null
@@ -0,0 +1,64 @@
+From 63a694c51bf120a37550890b8e7736b4888985e9 Mon Sep 17 00:00:00 2001
+From: Carlos Llamas <cmllamas@google.com>
+Date: Sat, 6 Jun 2026 18:15:52 +0000
+Subject: HID: uhid: convert to hid_safe_input_report()
+
+From: Carlos Llamas <cmllamas@google.com>
+
+commit 63a694c51bf120a37550890b8e7736b4888985e9 upstream.
+
+Commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing
+bogus memset()"), added a check in hid_report_raw_event() to reject
+reports if the received data size is smaller than expected. This was
+intended to prevent OOB errors by no longer allowing zeroing-out of
+shorter reports due to the lack of buffer size information.
+
+However, this leads to regressions in hid_report_raw_event(), where
+shorter than expected reports are rejected, even though their buffers
+are sufficiently large to be zero-padded.
+
+To solve this issue, Benjamin introduced a safer alternative in commit
+206342541fc8 ("HID: core: introduce hid_safe_input_report()"), which
+forwards the buffer size and allows hid_report_raw_event() to safely
+zero-pad the data.
+
+Convert uhid to use hid_safe_input_report() and pass UHID_DATA_MAX as
+the buffer size. This prevents the reported regressions [1], allowing
+hid core to zero-pad the shorter reports safely as expected.
+
+Cc: stable@vger.kernel.org
+Fixes: 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()")
+Closes: https://lore.kernel.org/all/ahsh0UtTX6e0ZeHa@google.com/ [1]
+Signed-off-by: Carlos Llamas <cmllamas@google.com>
+Reviewed-by: Lee Jones <lee@kernel.org>
+Closes: https://lore.kernel.org/all/ahsh0UtTX6e0ZeHa@google.com/
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/uhid.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/hid/uhid.c
++++ b/drivers/hid/uhid.c
+@@ -595,8 +595,8 @@ static int uhid_dev_input(struct uhid_de
+       if (!READ_ONCE(uhid->running))
+               return -EINVAL;
+-      hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data,
+-                       min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0);
++      hid_safe_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data, UHID_DATA_MAX,
++                            min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0);
+       return 0;
+ }
+@@ -606,8 +606,8 @@ static int uhid_dev_input2(struct uhid_d
+       if (!READ_ONCE(uhid->running))
+               return -EINVAL;
+-      hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data,
+-                       min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0);
++      hid_safe_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data, UHID_DATA_MAX,
++                            min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0);
+       return 0;
+ }
diff --git a/queue-7.1/hid-wacom-fix-slab-out-of-bounds-write-in-wacom_wac_queue_insert.patch b/queue-7.1/hid-wacom-fix-slab-out-of-bounds-write-in-wacom_wac_queue_insert.patch
new file mode 100644 (file)
index 0000000..219439f
--- /dev/null
@@ -0,0 +1,60 @@
+From 6b3014ec0e9a390ca563030b2d7689921f0daef5 Mon Sep 17 00:00:00 2001
+From: Jinmo Yang <jinmo44.yang@gmail.com>
+Date: Fri, 29 May 2026 02:59:45 +0900
+Subject: HID: wacom: fix slab-out-of-bounds write in wacom_wac_queue_insert
+
+From: Jinmo Yang <jinmo44.yang@gmail.com>
+
+commit 6b3014ec0e9a390ca563030b2d7689921f0daef5 upstream.
+
+wacom_wac_queue_insert() calls kfifo_skip() in a loop when the kfifo
+doesn't have enough space for the incoming report. If the kfifo is
+empty, kfifo_skip() reads stale data left in the kmalloc'd buffer
+via __kfifo_peek_n() and interprets it as a record length, advancing
+fifo->out by that garbage value. This corrupts the internal kfifo
+state, causing kfifo_unused() to return a value much larger than the
+actual buffer size, which bypasses __kfifo_in_r()'s guard:
+
+  if (len + recsize > kfifo_unused(fifo))
+      return 0;
+
+kfifo_copy_in() then performs an out-of-bounds memcpy, writing up to
+3842 bytes past the 256-byte buffer.
+
+Add a !kfifo_is_empty() condition to the while loop so kfifo_skip()
+is never called on an empty fifo, and check the return value of
+kfifo_in() to reject reports that are too large for the fifo.
+
+Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Fixes: 5e013ad20689 ("HID: wacom: Remove static WACOM_PKGLEN_MAX limit")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com>
+Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/wacom_sys.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/hid/wacom_sys.c
++++ b/drivers/hid/wacom_sys.c
+@@ -54,7 +54,7 @@ static void wacom_wac_queue_insert(struc
+ {
+       bool warned = false;
+-      while (kfifo_avail(fifo) < size) {
++      while (kfifo_avail(fifo) < size && !kfifo_is_empty(fifo)) {
+               if (!warned)
+                       hid_warn(hdev, "%s: kfifo has filled, starting to drop events\n", __func__);
+               warned = true;
+@@ -62,7 +62,9 @@ static void wacom_wac_queue_insert(struc
+               kfifo_skip(fifo);
+       }
+-      kfifo_in(fifo, raw_data, size);
++      if (!kfifo_in(fifo, raw_data, size))
++              hid_warn_ratelimited(hdev, "%s: report is too large (%d)\n",
++                                   __func__, size);
+ }
+ static void wacom_wac_queue_flush(struct hid_device *hdev,
diff --git a/queue-7.1/hid-wacom-stop-hardware-after-post-start-probe-failures.patch b/queue-7.1/hid-wacom-stop-hardware-after-post-start-probe-failures.patch
new file mode 100644 (file)
index 0000000..0bf50bc
--- /dev/null
@@ -0,0 +1,80 @@
+From ec2612b8ad9e642596db011dd8b6568ef1edeaa1 Mon Sep 17 00:00:00 2001
+From: Myeonghun Pak <mhun512@gmail.com>
+Date: Thu, 4 Jun 2026 13:56:58 +0900
+Subject: HID: wacom: stop hardware after post-start probe failures
+
+From: Myeonghun Pak <mhun512@gmail.com>
+
+commit ec2612b8ad9e642596db011dd8b6568ef1edeaa1 upstream.
+
+wacom_parse_and_register() starts HID hardware before registering inputs
+and initializing pad LEDs/remotes. Those later steps can fail, but their
+error paths currently release Wacom resources without stopping the HID
+hardware.
+
+Route post-hid_hw_start() failures through hid_hw_stop() before
+releasing driver resources.
+
+This issue was identified during our ongoing static-analysis research while
+reviewing kernel code.
+
+Fixes: c1d6708bf0d3 ("HID: wacom: Do not register input devices until after hid_hw_start")
+Cc: stable@vger.kernel.org
+Co-developed-by: Ijae Kim <ae878000@gmail.com>
+Signed-off-by: Ijae Kim <ae878000@gmail.com>
+Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
+Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/wacom_sys.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/hid/wacom_sys.c
++++ b/drivers/hid/wacom_sys.c
+@@ -2462,16 +2462,16 @@ static int wacom_parse_and_register(stru
+       error = wacom_register_inputs(wacom);
+       if (error)
+-              goto fail;
++              goto fail_hw_stop;
+       if (wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PAD) {
+               error = wacom_initialize_leds(wacom);
+               if (error)
+-                      goto fail;
++                      goto fail_hw_stop;
+               error = wacom_initialize_remotes(wacom);
+               if (error)
+-                      goto fail;
++                      goto fail_hw_stop;
+       }
+       if (!wireless) {
+@@ -2485,14 +2485,14 @@ static int wacom_parse_and_register(stru
+               cancel_delayed_work_sync(&wacom->init_work);
+               _wacom_query_tablet_data(wacom);
+               error = -ENODEV;
+-              goto fail_quirks;
++              goto fail_hw_stop;
+       }
+       if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) {
+               error = hid_hw_open(hdev);
+               if (error) {
+                       hid_err(hdev, "hw open failed\n");
+-                      goto fail_quirks;
++                      goto fail_hw_stop;
+               }
+       }
+@@ -2501,7 +2501,7 @@ static int wacom_parse_and_register(stru
+       return 0;
+-fail_quirks:
++fail_hw_stop:
+       hid_hw_stop(hdev);
+ fail:
+       wacom_release_resources(wacom);
diff --git a/queue-7.1/hid-wacom-use-gfp_atomic-in-wacom_wac_queue_flush.patch b/queue-7.1/hid-wacom-use-gfp_atomic-in-wacom_wac_queue_flush.patch
new file mode 100644 (file)
index 0000000..d13c778
--- /dev/null
@@ -0,0 +1,43 @@
+From 55f1ad573e34abf9a0443c34bc5a63d74edba7d7 Mon Sep 17 00:00:00 2001
+From: Jinmo Yang <jinmo44.yang@gmail.com>
+Date: Mon, 1 Jun 2026 22:41:23 +0900
+Subject: HID: wacom: use GFP_ATOMIC in wacom_wac_queue_flush()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jinmo Yang <jinmo44.yang@gmail.com>
+
+commit 55f1ad573e34abf9a0443c34bc5a63d74edba7d7 upstream.
+
+wacom_wac_queue_flush() is called via the .raw_event callback
+(wacom_raw_event â†’ wacom_wac_pen_serial_enforce â†’ wacom_wac_queue_flush).
+For USB HID devices, this callback is invoked from hid_irq_in(), which
+is a URB completion handler running in atomic context. Using GFP_KERNEL
+in this path can sleep, leading to a "scheduling while atomic" bug.
+
+Use GFP_ATOMIC instead. The existing code already handles allocation
+failure by skipping the fifo entry and continuing.
+
+Reported-by: Sashiko-bot <sashiko-bot@kernel.org>
+Fixes: 5e013ad20689 ("HID: wacom: Remove static WACOM_PKGLEN_MAX limit")
+Cc: stable@vger.kernel.org
+Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com>
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/wacom_sys.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/hid/wacom_sys.c
++++ b/drivers/hid/wacom_sys.c
+@@ -76,7 +76,7 @@ static void wacom_wac_queue_flush(struct
+               unsigned int count;
+               int err;
+-              buf = kzalloc(size, GFP_KERNEL);
++              buf = kzalloc(size, GFP_ATOMIC);
+               if (!buf) {
+                       kfifo_skip(fifo);
+                       continue;
diff --git a/queue-7.1/libfs-set-sb_i_noexec-and-sb_i_nodev-by-default-in-init_pseudo.patch b/queue-7.1/libfs-set-sb_i_noexec-and-sb_i_nodev-by-default-in-init_pseudo.patch
new file mode 100644 (file)
index 0000000..d2709b8
--- /dev/null
@@ -0,0 +1,56 @@
+From 6de2aeffabaafaeda819e60ec8d04f199711e11a Mon Sep 17 00:00:00 2001
+From: John Hubbard <jhubbard@nvidia.com>
+Date: Wed, 3 Jun 2026 19:53:14 -0700
+Subject: libfs: set SB_I_NOEXEC and SB_I_NODEV by default in init_pseudo()
+
+From: John Hubbard <jhubbard@nvidia.com>
+
+commit 6de2aeffabaafaeda819e60ec8d04f199711e11a upstream.
+
+Since commit 1e7ab6f67824 ("anon_inode: rework assertions"),
+path_noexec() warns when an anonymous-inode file is mmap'd from a
+superblock that has not set SB_I_NOEXEC. dma-buf backs its files this
+way and never set the flag, so mmap of any exported buffer trips the
+warning on a CONFIG_DEBUG_VFS=y kernel:
+
+  WARNING: CPU: 11 PID: 121813 at fs/exec.c:118 path_noexec+0x47/0x50
+   do_mmap+0x2b5/0x680
+   vm_mmap_pgoff+0x129/0x210
+   ksys_mmap_pgoff+0x177/0x240
+   __x64_sys_mmap+0x33/0x70
+
+init_pseudo() sets up internal SB_NOUSER mounts that are never
+path-reachable. Set both flags here so every pseudo filesystem gets
+them by default instead of each caller setting them.
+
+SB_I_NODEV is inert for unreachable mounts. SB_I_NOEXEC has one
+visible effect: an executable mapping of a pseudo-fs fd, such as a
+dma-buf, now fails with -EPERM, which is the invariant the assertion
+enforces. No in-tree caller maps these executable.
+
+Reproduce on CONFIG_DEBUG_VFS=y:
+
+  make -C tools/testing/selftests/dmabuf-heaps
+  sudo ./tools/testing/selftests/dmabuf-heaps/dmabuf-heap -t system
+
+Fixes: 1e7ab6f67824 ("anon_inode: rework assertions")
+Suggested-by: Christoph Hellwig <hch@infradead.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: John Hubbard <jhubbard@nvidia.com>
+Link: https://patch.msgid.link/20260604025315.245910-2-jhubbard@nvidia.com
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/libfs.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -736,6 +736,7 @@ struct pseudo_fs_context *init_pseudo(st
+               fc->fs_private = ctx;
+               fc->ops = &pseudo_fs_context_ops;
+               fc->sb_flags |= SB_NOUSER;
++              fc->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
+               fc->global = true;
+       }
+       return ctx;
diff --git a/queue-7.1/mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch b/queue-7.1/mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch
new file mode 100644 (file)
index 0000000..21a7846
--- /dev/null
@@ -0,0 +1,67 @@
+From 648927ceb84021a25a0fbd5673740956f318d534 Mon Sep 17 00:00:00 2001
+From: "Vlastimil Babka (SUSE)" <vbabka@kernel.org>
+Date: Wed, 10 Jun 2026 17:40:03 +0200
+Subject: mm/slab: do not limit zeroing to orig_size when only red zoning is enabled
+
+From: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+
+commit 648927ceb84021a25a0fbd5673740956f318d534 upstream.
+
+When init (zeroing) on allocation is requested, for kmalloc() we
+generally have to zero the full object size even if a smaller size is
+requested, in order to provide krealloc()'s __GFP_ZERO guarantees.
+
+But if we track the requested size, krealloc() uses that information to
+do the right thing, so we can zero only the requested size. With red
+zoning also enabled, any extra size became part of the red zone, so it
+must not be zeroed and thus we must zero only the requested size.
+
+However the current check is imprecise, and will trigger also when only
+SLAB_RED_ZONE is enabled without SLAB_STORE_USER (which enables tracking
+the requested size). This means enabling red zoning alone can compromise
+krealloc()'s __GFP_ZERO contract.
+
+Fix this by using slub_debug_orig_size() instead, which is the exact
+check for whether the requested size is tracked. We don't need to care
+if red zoning is also enabled or not. Also update and expand the
+comment accordingly.
+
+Fixes: 9ce67395f5a0 ("mm/slub: only zero requested size of buffer for kzalloc when debug enabled")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260610-slab_alloc_flags-v2-1-7190909db118@kernel.org
+Reviewed-by: Harry Yoo (Oracle) <harry@kernel.org>
+Reviewed-by: Hao Li <hao.li@linux.dev>
+Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/slub.c |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -4537,15 +4537,17 @@ bool slab_post_alloc_hook(struct kmem_ca
+       gfp_t init_flags = flags & gfp_allowed_mask;
+       /*
+-       * For kmalloc object, the allocated memory size(object_size) is likely
+-       * larger than the requested size(orig_size). If redzone check is
+-       * enabled for the extra space, don't zero it, as it will be redzoned
+-       * soon. The redzone operation for this extra space could be seen as a
+-       * replacement of current poisoning under certain debug option, and
+-       * won't break other sanity checks.
++       * For kmalloc object, the allocated size (object_size) can be larger
++       * than the requested size (orig_size). We however need to zero the
++       * whole object_size to handle possible later krealloc() with
++       *__GFP_ZERO properly.
++       *
++       * But if we keep track of the requested size, krealloc() uses that
++       * information. Additionally if red zoning is enabled, the extra space
++       * is also red zone, so we should not overwrite it. So limit zeroing to
++       * orig_size if we track it.
+        */
+-      if (kmem_cache_debug_flags(s, SLAB_STORE_USER | SLAB_RED_ZONE) &&
+-          (s->flags & SLAB_KMALLOC))
++      if (slub_debug_orig_size(s))
+               zero_size = orig_size;
+       /*
diff --git a/queue-7.1/opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch b/queue-7.1/opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch
new file mode 100644 (file)
index 0000000..5fc61ad
--- /dev/null
@@ -0,0 +1,41 @@
+From 69f888381d2ecbe18ed9f112c096f8fd3623db98 Mon Sep 17 00:00:00 2001
+From: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+Date: Mon, 11 May 2026 12:12:11 +0530
+Subject: OPP: of: Fix potential memory leak in opp_parse_supplies()
+
+From: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+
+commit 69f888381d2ecbe18ed9f112c096f8fd3623db98 upstream.
+
+The memory allocated for microvolt, microamp and microwatt is not freed
+in one of the paths in opp_parse_supplies() which returns directly.
+Fix that by adding a goto to the error unwind ladder.
+
+Fixes: 2eedf62e66c2 ("OPP: decouple dt properties in opp_parse_supplies()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/opp/of.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/opp/of.c
++++ b/drivers/opp/of.c
+@@ -673,7 +673,7 @@ static int opp_parse_supplies(struct dev
+        */
+       if (unlikely(opp_table->regulator_count == -1)) {
+               opp_table->regulator_count = 0;
+-              return 0;
++              goto free_microwatt;
+       }
+       for (i = 0, j = 0; i < opp_table->regulator_count; i++) {
+@@ -696,6 +696,7 @@ static int opp_parse_supplies(struct dev
+                       opp->supplies[i].u_watt = microwatt[i];
+       }
++free_microwatt:
+       kfree(microwatt);
+ free_microamp:
+       kfree(microamp);
diff --git a/queue-7.1/perf-arm-cmn-fix-dvm-node-events.patch b/queue-7.1/perf-arm-cmn-fix-dvm-node-events.patch
new file mode 100644 (file)
index 0000000..de4df95
--- /dev/null
@@ -0,0 +1,65 @@
+From 5936245125f78d896fdb1bbc2ae79213e28a6579 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 29 May 2026 15:33:45 +0100
+Subject: perf/arm-cmn: Fix DVM node events
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+commit 5936245125f78d896fdb1bbc2ae79213e28a6579 upstream.
+
+The new DVM node events added in CMN-700 also apply to CMN S3; fix
+the model encoding so that we can expose the aliases and handle
+occupancy filtering on newer CMNs too.
+
+Cc: stable@vger.kernel.org
+Fixes: 0dc2f4963f7e ("perf/arm-cmn: Support CMN S3")
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/perf/arm-cmn.c |   23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -197,13 +197,14 @@
+ enum cmn_model {
+       CMN600 = 1,
+       CMN650 = 2,
+-      CMN700 = 4,
+-      CI700 = 8,
++      CI700 = 4,
++      CMN700 = 8,
+       CMNS3 = 16,
+       /* ...and then we can use bitmap tricks for commonality */
+       CMN_ANY = -1,
+       NOT_CMN600 = -2,
+-      CMN_650ON = CMN650 | CMN700 | CMNS3,
++      CMN_700ON = ~(CMN700 - 1),
++      CMN_650ON = CMN_700ON | CMN650,
+ };
+ /* Actual part numbers and revision IDs defined by the hardware */
+@@ -919,14 +920,14 @@ static struct attribute *arm_cmn_event_a
+       CMN_EVENT_DVM(NOT_CMN600, txsnp_stall,          0x0a),
+       CMN_EVENT_DVM(NOT_CMN600, trkfull,              0x0b),
+       CMN_EVENT_DVM_OCC(NOT_CMN600, trk_occupancy,    0x0c),
+-      CMN_EVENT_DVM_OCC(CMN700, trk_occupancy_cxha,   0x0d),
+-      CMN_EVENT_DVM_OCC(CMN700, trk_occupancy_pdn,    0x0e),
+-      CMN_EVENT_DVM(CMN700, trk_alloc,                0x0f),
+-      CMN_EVENT_DVM(CMN700, trk_cxha_alloc,           0x10),
+-      CMN_EVENT_DVM(CMN700, trk_pdn_alloc,            0x11),
+-      CMN_EVENT_DVM(CMN700, txsnp_stall_limit,        0x12),
+-      CMN_EVENT_DVM(CMN700, rxsnp_stall_starv,        0x13),
+-      CMN_EVENT_DVM(CMN700, txsnp_sync_stall_op,      0x14),
++      CMN_EVENT_DVM_OCC(CMN_700ON, trk_occupancy_cxha, 0x0d),
++      CMN_EVENT_DVM_OCC(CMN_700ON, trk_occupancy_pdn, 0x0e),
++      CMN_EVENT_DVM(CMN_700ON, trk_alloc,             0x0f),
++      CMN_EVENT_DVM(CMN_700ON, trk_cxha_alloc,        0x10),
++      CMN_EVENT_DVM(CMN_700ON, trk_pdn_alloc,         0x11),
++      CMN_EVENT_DVM(CMN_700ON, txsnp_stall_limit,     0x12),
++      CMN_EVENT_DVM(CMN_700ON, rxsnp_stall_starv,     0x13),
++      CMN_EVENT_DVM(CMN_700ON, txsnp_sync_stall_op,   0x14),
+       CMN_EVENT_HNF(CMN_ANY, cache_miss,              0x01),
+       CMN_EVENT_HNF(CMN_ANY, slc_sf_cache_access,     0x02),
diff --git a/queue-7.1/perf-x86-intel-uncore-defer-adl-global-pmon-enable-to-enable_box.patch b/queue-7.1/perf-x86-intel-uncore-defer-adl-global-pmon-enable-to-enable_box.patch
new file mode 100644 (file)
index 0000000..cd77b9a
--- /dev/null
@@ -0,0 +1,52 @@
+From 9a0bb848a37150aeccc10088e141339917d995dc Mon Sep 17 00:00:00 2001
+From: Zide Chen <zide.chen@intel.com>
+Date: Tue, 2 Jun 2026 07:49:05 -0700
+Subject: perf/x86/intel/uncore: Defer ADL global PMON enable to enable_box()
+
+From: Zide Chen <zide.chen@intel.com>
+
+commit 9a0bb848a37150aeccc10088e141339917d995dc upstream.
+
+On some Raptor Cove CPUs, enabling uncore PMON globally at driver init
+may increase power consumption even when no perf events are in use.
+
+Drop adl_uncore_msr_init_box() and defer programming the global control
+register to enable_box(), so it is only set when a box is actually used.
+
+IMC and IMC freerunning counters use a separate control path and are
+unaffected.
+
+Fixes: 772ed05f3c5c ("perf/x86/intel/uncore: Add Alder Lake support")
+Signed-off-by: Zide Chen <zide.chen@intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260602144908.263680-5-zide.chen@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/events/intel/uncore_snb.c |    7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/arch/x86/events/intel/uncore_snb.c
++++ b/arch/x86/events/intel/uncore_snb.c
+@@ -563,12 +563,6 @@ void tgl_uncore_cpu_init(void)
+       skl_uncore_msr_ops.init_box = rkl_uncore_msr_init_box;
+ }
+-static void adl_uncore_msr_init_box(struct intel_uncore_box *box)
+-{
+-      if (box->pmu->pmu_idx == 0)
+-              wrmsrq(ADL_UNC_PERF_GLOBAL_CTL, SNB_UNC_GLOBAL_CTL_EN);
+-}
+-
+ static void adl_uncore_msr_enable_box(struct intel_uncore_box *box)
+ {
+       wrmsrq(ADL_UNC_PERF_GLOBAL_CTL, SNB_UNC_GLOBAL_CTL_EN);
+@@ -587,7 +581,6 @@ static void adl_uncore_msr_exit_box(stru
+ }
+ static struct intel_uncore_ops adl_uncore_msr_ops = {
+-      .init_box       = adl_uncore_msr_init_box,
+       .enable_box     = adl_uncore_msr_enable_box,
+       .disable_box    = adl_uncore_msr_disable_box,
+       .exit_box       = adl_uncore_msr_exit_box,
diff --git a/queue-7.1/posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch b/queue-7.1/posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch
new file mode 100644 (file)
index 0000000..9476d5a
--- /dev/null
@@ -0,0 +1,40 @@
+From 87bd2ad568e15b90d5f7d4bcd70342d05dad649c Mon Sep 17 00:00:00 2001
+From: WenTao Liang <vulab@iscas.ac.cn>
+Date: Fri, 12 Jun 2026 00:17:38 +0800
+Subject: posix-cpu-timers: Fix pid refcount leak in do_cpu_nanosleep() error path
+
+From: WenTao Liang <vulab@iscas.ac.cn>
+
+commit 87bd2ad568e15b90d5f7d4bcd70342d05dad649c upstream.
+
+In do_cpu_nanosleep(), posix_cpu_timer_create() takes a pid reference
+via get_pid() and stores it in timer.it.cpu.pid. If the subsequent
+posix_cpu_timer_set() call fails, the function returns immediately
+without calling posix_cpu_timer_del() to release the pid reference,
+causing a leak.
+
+Fix it by calling posix_cpu_timer_del() before the unlock-and-return
+on the error path, consistent with the other exit paths in the same
+function.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260611161738.97043-1-vulab@iscas.ac.cn
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/time/posix-cpu-timers.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/kernel/time/posix-cpu-timers.c
++++ b/kernel/time/posix-cpu-timers.c
+@@ -1504,6 +1504,7 @@ static int do_cpu_nanosleep(const clocki
+               spin_lock_irq(&timer.it_lock);
+               error = posix_cpu_timer_set(&timer, flags, &it, NULL);
+               if (error) {
++                      posix_cpu_timer_del(&timer);
+                       spin_unlock_irq(&timer.it_lock);
+                       return error;
+               }
diff --git a/queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch b/queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch
new file mode 100644 (file)
index 0000000..cac7ac8
--- /dev/null
@@ -0,0 +1,270 @@
+From 6255da28d4bb5349fe18e84cb043ccd394eba75d Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Mon, 18 May 2026 18:35:16 +0200
+Subject: proc: protect ptrace_may_access() with exec_update_lock (FD links)
+
+From: Jann Horn <jannh@google.com>
+
+commit 6255da28d4bb5349fe18e84cb043ccd394eba75d upstream.
+
+proc_pid_get_link() and proc_pid_readlink() currently look up the task from
+the pid once, then do the ptrace access check on that task, then look up
+the task from the pid a second time to do the actual access.
+That's racy in several ways.
+
+To fix it, pass the task to the ->proc_get_link() handler, and instead of
+proc_fd_access_allowed(), introduce a new helper call_proc_get_link() that
+looks up and locks the task, does the access check, and calls
+->proc_get_link().
+
+Fixes: 778c1144771f ("[PATCH] proc: Use sane permission checks on the /proc/<pid>/fd/ symlinks")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jann Horn <jannh@google.com>
+Link: https://patch.msgid.link/20260518-procfs-lockfix-part1-v1-2-5c3d20e0ac33@google.com
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/proc/base.c     |  119 ++++++++++++++++++++---------------------------------
+ fs/proc/fd.c       |   25 ++++-------
+ fs/proc/internal.h |    2 
+ 3 files changed, 58 insertions(+), 88 deletions(-)
+
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -218,33 +218,24 @@ static int get_task_root(struct task_str
+       return result;
+ }
+-static int proc_cwd_link(struct dentry *dentry, struct path *path)
++static int proc_cwd_link(struct dentry *dentry, struct path *path,
++                       struct task_struct *task)
+ {
+-      struct task_struct *task = get_proc_task(d_inode(dentry));
+       int result = -ENOENT;
+-      if (task) {
+-              task_lock(task);
+-              if (task->fs) {
+-                      get_fs_pwd(task->fs, path);
+-                      result = 0;
+-              }
+-              task_unlock(task);
+-              put_task_struct(task);
++      task_lock(task);
++      if (task->fs) {
++              get_fs_pwd(task->fs, path);
++              result = 0;
+       }
++      task_unlock(task);
+       return result;
+ }
+-static int proc_root_link(struct dentry *dentry, struct path *path)
++static int proc_root_link(struct dentry *dentry, struct path *path,
++                        struct task_struct *task)
+ {
+-      struct task_struct *task = get_proc_task(d_inode(dentry));
+-      int result = -ENOENT;
+-
+-      if (task) {
+-              result = get_task_root(task, path);
+-              put_task_struct(task);
+-      }
+-      return result;
++      return get_task_root(task, path);
+ }
+ /*
+@@ -704,23 +695,6 @@ static int proc_pid_syscall(struct seq_f
+ /*                       Here the fs part begins                        */
+ /************************************************************************/
+-/* permission checks */
+-static bool proc_fd_access_allowed(struct inode *inode)
+-{
+-      struct task_struct *task;
+-      bool allowed = false;
+-      /* Allow access to a task's file descriptors if it is us or we
+-       * may use ptrace attach to the process and find out that
+-       * information.
+-       */
+-      task = get_proc_task(inode);
+-      if (task) {
+-              allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
+-              put_task_struct(task);
+-      }
+-      return allowed;
+-}
+-
+ int proc_nochmod_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                struct iattr *attr)
+ {
+@@ -1777,16 +1751,12 @@ static const struct file_operations proc
+       .release        = single_release,
+ };
+-static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
++static int proc_exe_link(struct dentry *dentry, struct path *exe_path,
++                       struct task_struct *task)
+ {
+-      struct task_struct *task;
+       struct file *exe_file;
+-      task = get_proc_task(d_inode(dentry));
+-      if (!task)
+-              return -ENOENT;
+       exe_file = get_task_exe_file(task);
+-      put_task_struct(task);
+       if (exe_file) {
+               *exe_path = exe_file->f_path;
+               path_get(&exe_file->f_path);
+@@ -1796,26 +1766,42 @@ static int proc_exe_link(struct dentry *
+               return -ENOENT;
+ }
++static int call_proc_get_link(struct dentry *dentry, struct inode *inode, struct path *path_out)
++{
++      struct task_struct *task;
++      int ret;
++
++      task = get_proc_task(inode);
++      if (!task)
++              return -ENOENT;
++      ret = down_read_killable(&task->signal->exec_update_lock);
++      if (ret)
++              goto out_put_task;
++      if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
++              ret = -EACCES;
++              goto out;
++      }
++      ret = PROC_I(inode)->op.proc_get_link(dentry, path_out, task);
++
++out:
++      up_read(&task->signal->exec_update_lock);
++out_put_task:
++      put_task_struct(task);
++      return ret;
++}
++
+ static const char *proc_pid_get_link(struct dentry *dentry,
+                                    struct inode *inode,
+                                    struct delayed_call *done)
+ {
+       struct path path;
+-      int error = -EACCES;
++      int error;
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+-
+-      /* Are we allowed to snoop on the tasks file descriptors? */
+-      if (!proc_fd_access_allowed(inode))
+-              goto out;
+-
+-      error = PROC_I(inode)->op.proc_get_link(dentry, &path);
+-      if (error)
+-              goto out;
+-
+-      error = nd_jump_link(&path);
+-out:
++      error = call_proc_get_link(dentry, inode, &path);
++      if (!error)
++              error = nd_jump_link(&path);
+       return ERR_PTR(error);
+ }
+@@ -1849,17 +1835,11 @@ static int proc_pid_readlink(struct dent
+       struct inode *inode = d_inode(dentry);
+       struct path path;
+-      /* Are we allowed to snoop on the tasks file descriptors? */
+-      if (!proc_fd_access_allowed(inode))
+-              goto out;
+-
+-      error = PROC_I(inode)->op.proc_get_link(dentry, &path);
+-      if (error)
+-              goto out;
+-
+-      error = do_proc_readlink(&path, buffer, buflen);
+-      path_put(&path);
+-out:
++      error = call_proc_get_link(dentry, inode, &path);
++      if (!error) {
++              error = do_proc_readlink(&path, buffer, buflen);
++              path_put(&path);
++      }
+       return error;
+ }
+@@ -2250,21 +2230,16 @@ static const struct dentry_operations ti
+       .d_delete       = pid_delete_dentry,
+ };
+-static int map_files_get_link(struct dentry *dentry, struct path *path)
++static int map_files_get_link(struct dentry *dentry, struct path *path,
++                            struct task_struct *task)
+ {
+       unsigned long vm_start, vm_end;
+       struct vm_area_struct *vma;
+-      struct task_struct *task;
+       struct mm_struct *mm;
+       int rc;
+       rc = -ENOENT;
+-      task = get_proc_task(d_inode(dentry));
+-      if (!task)
+-              goto out;
+-
+       mm = get_task_mm(task);
+-      put_task_struct(task);
+       if (!mm)
+               goto out;
+--- a/fs/proc/fd.c
++++ b/fs/proc/fd.c
+@@ -171,24 +171,19 @@ static const struct dentry_operations ti
+       .d_delete       = pid_delete_dentry,
+ };
+-static int proc_fd_link(struct dentry *dentry, struct path *path)
++static int proc_fd_link(struct dentry *dentry, struct path *path,
++                      struct task_struct *task)
+ {
+-      struct task_struct *task;
+       int ret = -ENOENT;
++      unsigned int fd = proc_fd(d_inode(dentry));
++      struct file *fd_file;
+-      task = get_proc_task(d_inode(dentry));
+-      if (task) {
+-              unsigned int fd = proc_fd(d_inode(dentry));
+-              struct file *fd_file;
+-
+-              fd_file = fget_task(task, fd);
+-              if (fd_file) {
+-                      *path = fd_file->f_path;
+-                      path_get(&fd_file->f_path);
+-                      ret = 0;
+-                      fput(fd_file);
+-              }
+-              put_task_struct(task);
++      fd_file = fget_task(task, fd);
++      if (fd_file) {
++              *path = fd_file->f_path;
++              path_get(&fd_file->f_path);
++              ret = 0;
++              fput(fd_file);
+       }
+       return ret;
+--- a/fs/proc/internal.h
++++ b/fs/proc/internal.h
+@@ -107,7 +107,7 @@ extern struct kmem_cache *proc_dir_entry
+ void pde_free(struct proc_dir_entry *pde);
+ union proc_op {
+-      int (*proc_get_link)(struct dentry *, struct path *);
++      int (*proc_get_link)(struct dentry *, struct path *, struct task_struct *);
+       int (*proc_show)(struct seq_file *m,
+               struct pid_namespace *ns, struct pid *pid,
+               struct task_struct *task);
diff --git a/queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch b/queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch
new file mode 100644 (file)
index 0000000..821fb07
--- /dev/null
@@ -0,0 +1,203 @@
+From 6650527444dadc63d84aa939d14ecba4fadb2f69 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Mon, 18 May 2026 18:35:15 +0200
+Subject: proc: protect ptrace_may_access() with exec_update_lock (part 1)
+
+From: Jann Horn <jannh@google.com>
+
+commit 6650527444dadc63d84aa939d14ecba4fadb2f69 upstream.
+
+Fix the easy cases where procfs currently calls ptrace_may_access() without
+exec_update_lock protection, where the fix is to simply add the extra lock
+or use mm_access():
+
+ - do_task_stat(): grab exec_update_lock
+ - proc_pid_wchan(): grab exec_update_lock
+ - proc_map_files_lookup(): use mm_access() instead of get_task_mm()
+ - proc_map_files_readdir(): use mm_access() instead of get_task_mm()
+ - proc_ns_get_link(): grab exec_update_lock
+ - proc_ns_readlink(): grab exec_update_lock
+
+Fixes: f83ce3e6b02d ("proc: avoid information leaks to non-privileged processes")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jann Horn <jannh@google.com>
+Link: https://patch.msgid.link/20260518-procfs-lockfix-part1-v1-1-5c3d20e0ac33@google.com
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/proc/array.c      |    6 ++++++
+ fs/proc/base.c       |   41 ++++++++++++++++++++++-------------------
+ fs/proc/namespaces.c |   12 ++++++++++++
+ 3 files changed, 40 insertions(+), 19 deletions(-)
+
+--- a/fs/proc/array.c
++++ b/fs/proc/array.c
+@@ -482,6 +482,11 @@ static int do_task_stat(struct seq_file
+       unsigned long flags;
+       int exit_code = task->exit_code;
+       struct signal_struct *sig = task->signal;
++      int ret;
++
++      ret = down_read_killable(&task->signal->exec_update_lock);
++      if (ret)
++              return ret;
+       state = *get_task_state(task);
+       vsize = eip = esp = 0;
+@@ -657,6 +662,7 @@ static int do_task_stat(struct seq_file
+               seq_puts(m, " 0");
+       seq_putc(m, '\n');
++      up_read(&task->signal->exec_update_lock);
+       if (mm)
+               mmput(mm);
+       return 0;
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -414,18 +414,24 @@ static int proc_pid_wchan(struct seq_fil
+ {
+       unsigned long wchan;
+       char symname[KSYM_NAME_LEN];
++      int err;
++      err = down_read_killable(&task->signal->exec_update_lock);
++      if (err)
++              return err;
+       if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+               goto print0;
+       wchan = get_wchan(task);
+       if (wchan && !lookup_symbol_name(wchan, symname)) {
+               seq_puts(m, symname);
++              up_read(&task->signal->exec_update_lock);
+               return 0;
+       }
+ print0:
+       seq_putc(m, '0');
++      up_read(&task->signal->exec_update_lock);
+       return 0;
+ }
+ #endif /* CONFIG_KALLSYMS */
+@@ -2335,17 +2341,15 @@ static struct dentry *proc_map_files_loo
+       if (!task)
+               goto out;
+-      result = ERR_PTR(-EACCES);
+-      if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+-              goto out_put_task;
+-
+       result = ERR_PTR(-ENOENT);
+       if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
+               goto out_put_task;
+-      mm = get_task_mm(task);
+-      if (!mm)
++      mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
++      if (IS_ERR(mm)) {
++              result = ERR_CAST(mm);
+               goto out_put_task;
++      }
+       result = ERR_PTR(-EINTR);
+       if (mmap_read_lock_killable(mm))
+@@ -2395,23 +2399,22 @@ proc_map_files_readdir(struct file *file
+       if (!task)
+               goto out;
+-      ret = -EACCES;
+-      if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+-              goto out_put_task;
+-
+       ret = 0;
+       if (!dir_emit_dots(file, ctx))
+               goto out_put_task;
+-      mm = get_task_mm(task);
+-      if (!mm)
++      mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
++      if (IS_ERR(mm)) {
++              ret = PTR_ERR(mm);
++              /* if the task has no mm, the directory should just be empty */
++              if (ret == -ESRCH)
++                      ret = 0;
+               goto out_put_task;
++      }
+       ret = mmap_read_lock_killable(mm);
+-      if (ret) {
+-              mmput(mm);
+-              goto out_put_task;
+-      }
++      if (ret)
++              goto out_put_mm;
+       nr_files = 0;
+@@ -2437,8 +2440,7 @@ proc_map_files_readdir(struct file *file
+               if (!p) {
+                       ret = -ENOMEM;
+                       mmap_read_unlock(mm);
+-                      mmput(mm);
+-                      goto out_put_task;
++                      goto out_put_mm;
+               }
+               p->start = vma->vm_start;
+@@ -2446,7 +2448,6 @@ proc_map_files_readdir(struct file *file
+               p->mode = vma->vm_file->f_mode;
+       }
+       mmap_read_unlock(mm);
+-      mmput(mm);
+       for (i = 0; i < nr_files; i++) {
+               char buf[4 * sizeof(long) + 2]; /* max: %lx-%lx\0 */
+@@ -2463,6 +2464,8 @@ proc_map_files_readdir(struct file *file
+               ctx->pos++;
+       }
++out_put_mm:
++      mmput(mm);
+ out_put_task:
+       put_task_struct(task);
+ out:
+--- a/fs/proc/namespaces.c
++++ b/fs/proc/namespaces.c
+@@ -55,6 +55,10 @@ static const char *proc_ns_get_link(stru
+       if (!task)
+               return ERR_PTR(-EACCES);
++      error = down_read_killable(&task->signal->exec_update_lock);
++      if (error)
++              goto out_put_task;
++
+       if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+               goto out;
+@@ -64,6 +68,8 @@ static const char *proc_ns_get_link(stru
+       error = nd_jump_link(&ns_path);
+ out:
++      up_read(&task->signal->exec_update_lock);
++out_put_task:
+       put_task_struct(task);
+       return ERR_PTR(error);
+ }
+@@ -80,11 +86,17 @@ static int proc_ns_readlink(struct dentr
+       if (!task)
+               return res;
++      res = down_read_killable(&task->signal->exec_update_lock);
++      if (res)
++              goto out_put_task;
++
+       if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
+               res = ns_get_name(name, sizeof(name), task, ns_ops);
+               if (res >= 0)
+                       res = readlink_copy(buffer, buflen, name, strlen(name));
+       }
++      up_read(&task->signal->exec_update_lock);
++out_put_task:
+       put_task_struct(task);
+       return res;
+ }
diff --git a/queue-7.1/s390-revert-support-for-dcache_word_access.patch b/queue-7.1/s390-revert-support-for-dcache_word_access.patch
new file mode 100644 (file)
index 0000000..66ab107
--- /dev/null
@@ -0,0 +1,141 @@
+From 37540b8c287fc817bdbd0c62bb75ad6eab0e5d03 Mon Sep 17 00:00:00 2001
+From: Heiko Carstens <hca@linux.ibm.com>
+Date: Thu, 11 Jun 2026 17:37:46 +0200
+Subject: s390: Revert support for DCACHE_WORD_ACCESS
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+commit 37540b8c287fc817bdbd0c62bb75ad6eab0e5d03 upstream.
+
+load_unaligned_zeropad() reads eight bytes from unaligned addresses and may
+cross page boundaries. It handles exceptions which may happen if reading
+from the second page results in an exception.
+
+For pages which are donated to the Ultravisor for secure execution purposes
+the do_secure_storage_access() exception handler however does not handle
+such exceptions correctly. Such an exception may result in an endless
+exception loop which will never be resolved.
+
+An attempt to fix this [1] turned out to be not sufficient. For now revert
+load_unaligned_zeropad() until this problem has been resolved in a proper
+way.
+
+Note that the implementation of load_unaligned_zeropad() itself is
+correct. The revert is just a temporary workaround until there is complete
+fix for secure storage access exceptions.
+
+[1] commit b00be77302d7 ("s390/mm: Add missing secure storage access fixups for donated memory")
+
+Fixes: 802ba53eefc5 ("s390: add support for DCACHE_WORD_ACCESS")
+Cc: stable@vger.kernel.org
+Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/Kconfig                      |    1 -
+ arch/s390/include/asm/asm-extable.h    |    4 ----
+ arch/s390/include/asm/word-at-a-time.h |   22 ----------------------
+ arch/s390/mm/extable.c                 |   18 ------------------
+ 4 files changed, 45 deletions(-)
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -163,7 +163,6 @@ config S390
+       select ARCH_WANTS_THP_SWAP
+       select BUILDTIME_TABLE_SORT
+       select CLONE_BACKWARDS2
+-      select DCACHE_WORD_ACCESS if !KMSAN
+       select DYNAMIC_FTRACE if FUNCTION_TRACER
+       select FUNCTION_ALIGNMENT_8B if CC_IS_GCC
+       select FUNCTION_ALIGNMENT_16B if !CC_IS_GCC
+--- a/arch/s390/include/asm/asm-extable.h
++++ b/arch/s390/include/asm/asm-extable.h
+@@ -12,7 +12,6 @@
+ #define EX_TYPE_UA_FAULT      3
+ #define EX_TYPE_UA_LOAD_REG   5
+ #define EX_TYPE_UA_LOAD_REGPAIR       6
+-#define EX_TYPE_ZEROPAD               7
+ #define EX_TYPE_FPC           8
+ #define EX_TYPE_UA_MVCOS_TO   9
+ #define EX_TYPE_UA_MVCOS_FROM 10
+@@ -80,9 +79,6 @@
+ #define EX_TABLE_UA_LOAD_REGPAIR(_fault, _target, _regerr, _regzero)  \
+       __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0)
+-#define EX_TABLE_ZEROPAD(_fault, _target, _regdata, _regaddr)         \
+-      __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_ZEROPAD, _regdata, _regaddr, 0)
+-
+ #define EX_TABLE_FPC(_fault, _target)                                 \
+       __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FPC, __stringify(%%r0), __stringify(%%r0), 0)
+--- a/arch/s390/include/asm/word-at-a-time.h
++++ b/arch/s390/include/asm/word-at-a-time.h
+@@ -4,7 +4,6 @@
+ #include <linux/bitops.h>
+ #include <linux/wordpart.h>
+-#include <asm/asm-extable.h>
+ #include <asm/bitsperlong.h>
+ struct word_at_a_time {
+@@ -41,25 +40,4 @@ static inline unsigned long zero_bytemas
+       return ~1UL << data;
+ }
+-/*
+- * Load an unaligned word from kernel space.
+- *
+- * In the (very unlikely) case of the word being a page-crosser
+- * and the next page not being mapped, take the exception and
+- * return zeroes in the non-existing part.
+- */
+-static inline unsigned long load_unaligned_zeropad(const void *addr)
+-{
+-      unsigned long data;
+-
+-      asm_inline volatile(
+-              "0:     lg      %[data],0(%[addr])\n"
+-              "1:     nopr    %%r7\n"
+-              EX_TABLE_ZEROPAD(0b, 1b, %[data], %[addr])
+-              EX_TABLE_ZEROPAD(1b, 1b, %[data], %[addr])
+-              : [data] "=d" (data)
+-              : [addr] "a" (addr), "m" (*(unsigned long *)addr));
+-      return data;
+-}
+-
+ #endif /* _ASM_WORD_AT_A_TIME_H */
+--- a/arch/s390/mm/extable.c
++++ b/arch/s390/mm/extable.c
+@@ -50,22 +50,6 @@ static bool ex_handler_ua_load_reg(const
+       return true;
+ }
+-static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs)
+-{
+-      unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
+-      unsigned int reg_data = FIELD_GET(EX_DATA_REG_ERR, ex->data);
+-      unsigned long data, addr, offset;
+-
+-      addr = regs->gprs[reg_addr];
+-      offset = addr & (sizeof(unsigned long) - 1);
+-      addr &= ~(sizeof(unsigned long) - 1);
+-      data = *(unsigned long *)addr;
+-      data <<= BITS_PER_BYTE * offset;
+-      regs->gprs[reg_data] = data;
+-      regs->psw.addr = extable_fixup(ex);
+-      return true;
+-}
+-
+ static bool ex_handler_fpc(const struct exception_table_entry *ex, struct pt_regs *regs)
+ {
+       fpu_sfpc(0);
+@@ -134,8 +118,6 @@ bool fixup_exception(struct pt_regs *reg
+               return ex_handler_ua_load_reg(ex, false, regs);
+       case EX_TYPE_UA_LOAD_REGPAIR:
+               return ex_handler_ua_load_reg(ex, true, regs);
+-      case EX_TYPE_ZEROPAD:
+-              return ex_handler_zeropad(ex, regs);
+       case EX_TYPE_FPC:
+               return ex_handler_fpc(ex, regs);
+       case EX_TYPE_UA_MVCOS_TO:
diff --git a/queue-7.1/sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch b/queue-7.1/sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch
new file mode 100644 (file)
index 0000000..92747b1
--- /dev/null
@@ -0,0 +1,100 @@
+From dd29c017aed628076e915fe4cdfb5392fd4c5cab Mon Sep 17 00:00:00 2001
+From: Steven Rostedt <rostedt@goodmis.org>
+Date: Fri, 15 May 2026 10:37:40 -0400
+Subject: sched/rt: Have RT_PUSH_IPI be default off for non PREEMPT_RT
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+commit dd29c017aed628076e915fe4cdfb5392fd4c5cab upstream.
+
+RT migration is done aggressively. When a CPU schedules out a high
+priority RT task for a lower priority task, it will look to see if there's
+any RT tasks that are waiting to run on another CPU that is of higher
+priority than the task this CPU is about to run. If it finds one, it will
+pull that task over to the CPU and allow it to run there instead.
+
+Normally, this pulling is done by looking at the RT overloaded mask (rto)
+which contains all the CPUs in the scheduler domain with RT tasks that are
+waiting to run due to a higher priority RT task currently running on their
+CPU. The CPU that is about to schedule a lower priority task will grab the
+rq lock of the overloaded CPU and move the RT task from that CPU's runqueue
+to the local one and schedule the higher priority RT task.
+
+This caused issues when a lot of CPUs would schedule a lower priority task
+at the same time. They would all try to grab the same runqueue lock of
+the CPU with the overloaded RT tasks. Only the first CPU that got in will
+get that task. All the others would wait until they got the runqueue lock
+and see there's nothing to pull and do nothing. On systems with lots of
+CPUs, this caused a large latency (up to 500us) which is beyond what
+PREEMPT_RT is to allow.
+
+The solution to that was to create an RT_PUSH_IPI logic. When any CPU
+wanted to pull a task, instead of grabbing the runqueue lock of the
+overloaded CPU, it would start by sending an IPI to the overloaded CPU,
+and that IPI handler would have the CPU with the waiting RT task do a push
+instead. Then that handler would send an IPI to the next CPU with
+overloaded RT tasks, and so on. Note, after the first CPU starts this
+process, if another CPU wanted to do a pull, it would see that the process
+has already begun and would only increment a counter to have the IPIs
+continue again.
+
+The RT_PUSH_IPI solved the latency problem with PREEMPT_RT but could cause
+a new issue with non PREEMPT_RT. Namely, softirqs run in a threaded
+context on PREEMPT_RT but they can run in an interrupt context in non-RT.
+
+If an IPI lands on a CPU that has just woken up multiple RT tasks and the
+current CPU is running a non RT or a low priority RT task, instead of
+doing a push, it would simply do a schedule on that CPU. But if a softirq
+was also executing on this CPU, the schedule would need to wait until the
+softirq finished. Until then, the CPU would still be considered overloaded
+as there are RT tasks still waiting to run on it.
+
+A live lock occurred on a workload that was doing heavy networking traffic
+on a large machine where the softirqs would run 500us out of 750us. And it
+would also be waking up RT tasks, causing the RT pull logic to be
+constantly executed.
+
+When a softirq triggered on a CPU with RT tasks queued but not running
+yet, and the other CPUs would see this CPU as being overloaded, they would
+send an IPI over to it. The CPU would notice that the waiting RT tasks are
+of higher priority than the currently running task and simply schedule
+that CPU instead. But because the softirq was executing, before it could
+schedule, it would receive another IPI to do the same. The amount of IPIs
+would slow down the currently running softirq so much that before it could
+return back to task context, it would execute another softirq never
+allowing the CPU to schedule. This live locked that CPU.
+
+As RT_PUSH_IPI was created to help PREEMPT_RT, make it default off if
+PREEMPT_RT is not enabled.
+
+Fixes: b6366f048e0c ("sched/rt: Use IPI to trigger RT task push migration instead of pulling")
+Closes: https://lore.kernel.org/all/20260506235716.2530720-1-tj@kernel.org/
+Reported-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260515103740.25ccbed8@gandalf.local.home
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/features.h |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/kernel/sched/features.h
++++ b/kernel/sched/features.h
+@@ -110,8 +110,16 @@ SCHED_FEAT(WARN_DOUBLE_CLOCK, false)
+  * rq lock and possibly create a large contention, sending an
+  * IPI to that CPU and let that CPU push the RT task to where
+  * it should go may be a better scenario.
++ *
++ * This is best for PREEMPT_RT, but for non-RT it can cause issues
++ * when preemption is disabled for long periods of time. Have
++ * it only default enabled for PREEMPT_RT.
+  */
++# ifdef CONFIG_PREEMPT_RT
+ SCHED_FEAT(RT_PUSH_IPI, true)
++# else
++SCHED_FEAT(RT_PUSH_IPI, false)
++# endif
+ #endif
+ SCHED_FEAT(RT_RUNTIME_SHARE, false)
index d96ca80e9d13d061ffbf603b272815e49d1315f3..4699ca1b79f71330ed3974a19efa3c712c88a481 100644 (file)
@@ -240,3 +240,37 @@ smb-client-use-unaligned-reads-in-parse_posix_ctxt.patch
 smb-client-harden-posix-sid-length-parsing.patch
 smb-client-fix-atime-clamp-check-in-read-completion.patch
 smb-client-mask-server-provided-mode-to-07777-in-modefromsid.patch
+smb-server-do-not-require-delete-access-for-non-replacing-links.patch
+writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch
+opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch
+cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch
+firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch
+libfs-set-sb_i_noexec-and-sb_i_nodev-by-default-in-init_pseudo.patch
+proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch
+perf-x86-intel-uncore-defer-adl-global-pmon-enable-to-enable_box.patch
+cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch
+sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch
+cpufreq-fix-hotplug-suspend-race-during-reboot.patch
+cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch
+proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch
+posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch
+time-jiffies-register-jiffies-clocksource-before-usage.patch
+clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch
+s390-revert-support-for-dcache_word_access.patch
+perf-arm-cmn-fix-dvm-node-events.patch
+x.509-fix-validation-of-asn.1-certificate-header.patch
+mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch
+tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch
+tools-mm-slabinfo-fix-total_objects-attribute-name.patch
+hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch
+hid-uhid-convert-to-hid_safe_input_report.patch
+hid-wacom-stop-hardware-after-post-start-probe-failures.patch
+hid-pidff-use-correct-effect-type-in-effect-update.patch
+hid-hid-lenovo-go-cancel-cfg_setup-work-in-hid_go_cfg_remove.patch
+hid-wacom-fix-slab-out-of-bounds-write-in-wacom_wac_queue_insert.patch
+hid-wacom-use-gfp_atomic-in-wacom_wac_queue_flush.patch
+hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch
+hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch
+hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch
+hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch
+hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch
diff --git a/queue-7.1/smb-server-do-not-require-delete-access-for-non-replacing-links.patch b/queue-7.1/smb-server-do-not-require-delete-access-for-non-replacing-links.patch
new file mode 100644 (file)
index 0000000..9872af7
--- /dev/null
@@ -0,0 +1,56 @@
+From 851ed9e09639e0daf79a506ce26097b296ed5518 Mon Sep 17 00:00:00 2001
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Date: Sun, 28 Jun 2026 07:42:43 +0000
+Subject: smb/server: do not require delete access for non-replacing links
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+commit 851ed9e09639e0daf79a506ce26097b296ed5518 upstream.
+
+Reproducer:
+
+  1. server: systemctl start ksmbd
+  2. client: mount -t cifs //${server_ip}/export /mnt
+  3. client: touch /mnt/file; ln /mnt/file /mnt/hardlink
+  4. client err log: ln: failed to create hard link 'hardlink' =>
+     'file': Permission denied
+  5. server err log: ksmbd: no right to delete : 0x80
+
+Fixes: 13f3942f2bf4 ("ksmbd: add per-handle permission check to FILE_LINK_INFORMATION")
+Cc: stable@vger.kernel.org
+Reported-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smb2pdu.c |   14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -6564,16 +6564,18 @@ static int smb2_set_info_file(struct ksm
+       }
+       case FILE_LINK_INFORMATION:
+       {
+-              if (!(fp->daccess & FILE_DELETE_LE)) {
+-                      pr_err("no right to delete : 0x%x\n", fp->daccess);
+-                      return -EACCES;
+-              }
++              struct smb2_file_link_info *file_info;
+               if (buf_len < sizeof(struct smb2_file_link_info))
+                       return -EMSGSIZE;
+-              return smb2_create_link(work, work->tcon->share_conf,
+-                                      (struct smb2_file_link_info *)buffer,
++              file_info = (struct smb2_file_link_info *)buffer;
++              if (file_info->ReplaceIfExists && !(fp->daccess & FILE_DELETE_LE)) {
++                      pr_err("no right to delete : 0x%x\n", fp->daccess);
++                      return -EACCES;
++              }
++
++              return smb2_create_link(work, work->tcon->share_conf, file_info,
+                                       buf_len, fp->filp,
+                                       work->conn->local_nls);
+       }
diff --git a/queue-7.1/time-jiffies-register-jiffies-clocksource-before-usage.patch b/queue-7.1/time-jiffies-register-jiffies-clocksource-before-usage.patch
new file mode 100644 (file)
index 0000000..0acc7b6
--- /dev/null
@@ -0,0 +1,53 @@
+From f24df84cbe05e4471c04ac4b921fc0340bbc7752 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@kernel.org>
+Date: Tue, 9 Jun 2026 17:14:45 +0200
+Subject: time/jiffies: Register jiffies clocksource before usage
+
+From: Thomas Gleixner <tglx@kernel.org>
+
+commit f24df84cbe05e4471c04ac4b921fc0340bbc7752 upstream.
+
+Teddy reported that a XEN HVM has a long boot delay, which was bisected to
+the recent enhancements to the negative motion detection. It turned out
+that the jiffies clocksource is used in early boot before it is registered,
+which leaves the max_delta_raw field at zero. That causes the read out to
+be clamped to the max delta of 0, which means time is not making progress.
+
+Cure it by ensuring that it is initialized before its first usage in
+timekeeping_init().
+
+Fixes: 76031d9536a0 ("clocksource: Make negative motion detection more robust")
+Reported-by: Teddy Astie <teddy.astie@vates.tech>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Tested-by: Teddy Astie <teddy.astie@vates.tech>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/87y0gn3fve.ffs@fw13
+Closes: https://lore.kernel.org/all/1780914594.8631fc262581453bbf619ec5b2062170.19ea6c8227b000701b@vates.tech
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/time/jiffies.c |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/kernel/time/jiffies.c
++++ b/kernel/time/jiffies.c
+@@ -60,15 +60,14 @@ EXPORT_SYMBOL(get_jiffies_64);
+ EXPORT_SYMBOL(jiffies);
+-static int __init init_jiffies_clocksource(void)
+-{
+-      return __clocksource_register(&clocksource_jiffies);
+-}
+-
+-core_initcall(init_jiffies_clocksource);
++static bool cs_jiffies_registered __initdata;
+ struct clocksource * __init __weak clocksource_default_clock(void)
+ {
++      if (!cs_jiffies_registered) {
++              __clocksource_register(&clocksource_jiffies);
++              cs_jiffies_registered = true;
++      }
+       return &clocksource_jiffies;
+ }
diff --git a/queue-7.1/tools-mm-slabinfo-fix-total_objects-attribute-name.patch b/queue-7.1/tools-mm-slabinfo-fix-total_objects-attribute-name.patch
new file mode 100644 (file)
index 0000000..865c425
--- /dev/null
@@ -0,0 +1,46 @@
+From 892a7864730775c3dbee2a39e9ead4fa8d4256e7 Mon Sep 17 00:00:00 2001
+From: Yichong Chen <chenyichong@uniontech.com>
+Date: Fri, 12 Jun 2026 15:13:59 +0800
+Subject: tools/mm/slabinfo: fix total_objects attribute name
+
+From: Yichong Chen <chenyichong@uniontech.com>
+
+commit 892a7864730775c3dbee2a39e9ead4fa8d4256e7 upstream.
+
+SLUB exports the total_objects sysfs attribute, but slabinfo tries to read
+objects_total. As a result, the lookup fails and the field remains zero.
+
+Use the correct attribute name and rename the corresponding structure
+member to match.
+
+Fixes: 205ab99dd103 ("slub: Update statistics handling for variable order slabs")
+Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
+Cc: <stable@vger.kernel.org>
+Reviewed-by: SeongJae Park <sj@kernel.org>
+Link: https://patch.msgid.link/96556748872BB47E+20260612071359.649946-1-chenyichong@uniontech.com
+Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/mm/slabinfo.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/tools/mm/slabinfo.c
++++ b/tools/mm/slabinfo.c
+@@ -33,7 +33,7 @@ struct slabinfo {
+       unsigned int hwcache_align, object_size, objs_per_slab;
+       unsigned int sanity_checks, slab_size, store_user, trace;
+       int order, poison, reclaim_account, red_zone;
+-      unsigned long partial, objects, slabs, objects_partial, objects_total;
++      unsigned long partial, objects, slabs, objects_partial, total_objects;
+       unsigned long alloc_fastpath, alloc_slowpath;
+       unsigned long free_fastpath, free_slowpath;
+       unsigned long free_frozen, free_add_partial, free_remove_partial;
+@@ -1263,7 +1263,7 @@ static void read_slab_dir(void)
+                       slab->object_size = get_obj("object_size");
+                       slab->objects = get_obj("objects");
+                       slab->objects_partial = get_obj("objects_partial");
+-                      slab->objects_total = get_obj("objects_total");
++                      slab->total_objects = get_obj("total_objects");
+                       slab->objs_per_slab = get_obj("objs_per_slab");
+                       slab->order = get_obj("order");
+                       slab->partial = get_obj("partial");
diff --git a/queue-7.1/tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch b/queue-7.1/tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch
new file mode 100644 (file)
index 0000000..77d3d84
--- /dev/null
@@ -0,0 +1,36 @@
+From 235ab68d67eadbef1fdbfb771f21f5bacc77a2ae Mon Sep 17 00:00:00 2001
+From: Xuewen Wang <wangxuewen@kylinos.cn>
+Date: Mon, 18 May 2026 14:21:57 +0800
+Subject: tools/mm/slabinfo: Fix trace disable logic inversion
+
+From: Xuewen Wang <wangxuewen@kylinos.cn>
+
+commit 235ab68d67eadbef1fdbfb771f21f5bacc77a2ae upstream.
+
+The disable trace path in slab_debug() had a logic error where it would
+set trace=1 instead of trace=0. This made trace functionality permanently
+enabled once turned on for any slab cache.
+
+Fixes: a87615b8f9e2 ("SLUB: slabinfo upgrade")
+Cc: stable@vger.kernel.org
+Reviewed-by: SeongJae Park <sj@kernel.org>
+Signed-off-by: Xuewen Wang <wangxuewen@kylinos.cn>
+WARNING: From:/Signed-off-by: email address mismatch: 'From: wangxuewen <18810879172@163.com>' != 'Signed-off-by: wangxuewen <wangxuewen@kylinos.cn>'
+Link: https://patch.msgid.link/20260518062159.80664-2-wangxuewen@kylinos.cn
+Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/mm/slabinfo.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/mm/slabinfo.c
++++ b/tools/mm/slabinfo.c
+@@ -798,7 +798,7 @@ static void slab_debug(struct slabinfo *
+                       fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
+       }
+       if (!tracing && s->trace)
+-              set_obj(s, "trace", 1);
++              set_obj(s, "trace", 0);
+ }
+ static void totals(void)
diff --git a/queue-7.1/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch b/queue-7.1/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch
new file mode 100644 (file)
index 0000000..79c4e0e
--- /dev/null
@@ -0,0 +1,177 @@
+From cba38ec4cbd3a7b8b942a8d52531a05be8a9ff0d Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun@linux.alibaba.com>
+Date: Thu, 21 May 2026 17:50:14 +0800
+Subject: writeback: fix race between cgroup_writeback_umount() and inode_switch_wbs()
+
+From: Baokun Li <libaokun@linux.alibaba.com>
+
+commit cba38ec4cbd3a7b8b942a8d52531a05be8a9ff0d upstream.
+
+When a container exits, the following BUG_ON() is occasionally triggered:
+
+==================================================================
+ VFS: Busy inodes after unmount of sdb (ext4)
+ ------------[ cut here ]------------
+ kernel BUG at fs/super.c:695!
+ CPU: 3 PID: 6 Comm: containerd-shim Tainted: G OE K 6.6 #1
+ pstate: 63400009 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+ pc : generic_shutdown_super+0xf0/0x100
+ lr : generic_shutdown_super+0xf0/0x100
+ Call trace:
+  generic_shutdown_super+0xf0/0x100
+  kill_block_super+0x20/0x48
+  ext4_kill_sb+0x28/0x60
+  deactivate_locked_super+0x54/0x130
+  deactivate_super+0x84/0xa0
+  cleanup_mnt+0xa4/0x140
+  __cleanup_mnt+0x18/0x28
+  task_work_run+0x78/0xe0
+  do_notify_resume+0x204/0x240
+==================================================================
+
+The root cause is a race between cgroup_writeback_umount() and
+inode_switch_wbs()/cleanup_offline_cgwb(). There is a window between
+inode_prepare_wbs_switch() returning true and the subsequent
+wb_queue_isw() call. Following is the process that triggers the issue:
+
+      CPU A (umount)           |          CPU B (writeback)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                                 inode_switch_wbs/cleanup_offline_cgwb
+                                  atomic_inc(&isw_nr_in_flight)
+                                  inode_prepare_wbs_switch
+                                   -> passes SB_ACTIVE check
+                                   __iget(inode)
+ generic_shutdown_super
+  sb->s_flags &= ~SB_ACTIVE
+  cgroup_writeback_umount(sb)
+   smp_mb()
+   atomic_read(&isw_nr_in_flight)
+   rcu_barrier()
+    -> no pending RCU callbacks
+   flush_workqueue(isw_wq)
+    -> nothing queued, returns
+  evict_inodes(sb)
+   -> Inode skipped as isw still holds a ref.
+  sop->put_super(sb)
+   /* destroys percpu counters */
+  -> VFS: Busy inodes after unmount!
+                                  wb_queue_isw()
+                                   queue_work(isw_wq, ...)
+                                  /* later in work function */
+                                  inode_switch_wbs_work_fn
+                                   process_inode_switch_wbs
+                                    iput() -> evict
+                                     percpu_counter_dec() // UAF!
+
+Fix this by extending the RCU read-side critical section in
+inode_switch_wbs() and cleanup_offline_cgwb() to cover from
+inode_prepare_wbs_switch() through wb_queue_isw().  Since there is
+no sleep in this window, rcu_read_lock() can be used.  Then add a
+synchronize_rcu() in cgroup_writeback_umount() before the existing
+rcu_barrier(), so that all in-flight switchers that have passed the
+SB_ACTIVE check have completed queue_work() before flush_workqueue()
+is called.
+
+The existing rcu_barrier() is intentionally retained so this fix can
+be backported unchanged to stable kernels (5.10.y, 6.6.y, ...) that
+still queue switches via queue_rcu_work(). It is a no-op on current
+mainline (since commit e1b849cfa6b6 ("writeback: Avoid contention on
+wb->list_lock when switching inodes")) and is removed in a follow-up
+patch.
+
+Fixes: a1a0e23e4903 ("writeback: flush inode cgroup wb switches instead of pinning super_block")
+Cc: stable@vger.kernel.org
+Suggested-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/all/mxnjq2l6guusfchvauxr3v7c4bwjasybxlleqbbh4efloeqspz@iqylk76ohufz
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Baokun Li <libaokun@linux.alibaba.com>
+Link: https://patch.msgid.link/20260521095016.2791354-2-libaokun@linux.alibaba.com
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fs-writeback.c |   31 +++++++++++++++++++++++++++++--
+ 1 file changed, 29 insertions(+), 2 deletions(-)
+
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -660,12 +660,19 @@ static void inode_switch_wbs(struct inod
+       atomic_inc(&isw_nr_in_flight);
+-      /* find and pin the new wb */
++      /*
++       * Paired with synchronize_rcu() in cgroup_writeback_umount():
++       * holding rcu_read_lock across inode_prepare_wbs_switch()
++       * (covering the SB_ACTIVE check and the inode grab) and
++       * wb_queue_isw() ensures synchronize_rcu() cannot return until
++       * the work is queued, so the subsequent flush_workqueue() will
++       * wait for the switch.
++       */
+       rcu_read_lock();
++      /* find and pin the new wb */
+       memcg_css = css_from_id(new_wb_id, &memory_cgrp_subsys);
+       if (memcg_css && !css_tryget(memcg_css))
+               memcg_css = NULL;
+-      rcu_read_unlock();
+       if (!memcg_css)
+               goto out_free;
+@@ -681,9 +688,11 @@ static void inode_switch_wbs(struct inod
+       trace_inode_switch_wbs_queue(inode->i_wb, new_wb, 1);
+       wb_queue_isw(new_wb, isw);
++      rcu_read_unlock();
+       return;
+ out_free:
++      rcu_read_unlock();
+       atomic_dec(&isw_nr_in_flight);
+       if (new_wb)
+               wb_put(new_wb);
+@@ -741,6 +750,14 @@ bool cleanup_offline_cgwb(struct bdi_wri
+               new_wb = &wb->bdi->wb; /* wb_get() is noop for bdi's wb */
+       nr = 0;
++      /*
++       * Paired with synchronize_rcu() in cgroup_writeback_umount().
++       * Holding rcu_read_lock across the SB_ACTIVE check, the inode grab
++       * and wb_queue_isw() ensures synchronize_rcu() cannot return until
++       * the work is queued, so the subsequent flush_workqueue() will wait
++       * for the switch.
++       */
++      rcu_read_lock();
+       spin_lock(&wb->list_lock);
+       /*
+        * In addition to the inodes that have completed writeback, also switch
+@@ -758,6 +775,7 @@ bool cleanup_offline_cgwb(struct bdi_wri
+       /* no attached inodes? bail out */
+       if (nr == 0) {
++              rcu_read_unlock();
+               atomic_dec(&isw_nr_in_flight);
+               wb_put(new_wb);
+               kfree(isw);
+@@ -766,6 +784,7 @@ bool cleanup_offline_cgwb(struct bdi_wri
+       trace_inode_switch_wbs_queue(wb, new_wb, nr);
+       wb_queue_isw(new_wb, isw);
++      rcu_read_unlock();
+       return restart;
+ }
+@@ -1222,6 +1241,14 @@ void cgroup_writeback_umount(struct supe
+       if (atomic_read(&isw_nr_in_flight)) {
+               /*
++               * Paired with rcu_read_lock() in inode_switch_wbs() and
++               * cleanup_offline_cgwb().  synchronize_rcu() waits for any
++               * in-flight switcher that already passed the SB_ACTIVE check
++               * to finish queueing its work, so flush_workqueue() below
++               * will then drain it.
++               */
++              synchronize_rcu();
++              /*
+                * Use rcu_barrier() to wait for all pending callbacks to
+                * ensure that all in-flight wb switches are in the workqueue.
+                */
diff --git a/queue-7.1/x.509-fix-validation-of-asn.1-certificate-header.patch b/queue-7.1/x.509-fix-validation-of-asn.1-certificate-header.patch
new file mode 100644 (file)
index 0000000..ec56166
--- /dev/null
@@ -0,0 +1,40 @@
+From 3b626ba431c4501512ad07549310685e07fe4706 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Thu, 14 May 2026 08:55:58 +0200
+Subject: X.509: Fix validation of ASN.1 certificate header
+
+From: Lukas Wunner <lukas@wunner.de>
+
+commit 3b626ba431c4501512ad07549310685e07fe4706 upstream.
+
+x509_load_certificate_list() seeks to enforce that a certificate starts
+with 0x30 0x82 (ASN.1 SEQUENCE tag followed by a length of more than 256
+and less than 65535 bytes).
+
+But it only enforces that *either* of those two byte values are present,
+instead of checking for the *conjunction* of the two values.  Fix it.
+
+Fixes: 631cc66eb9ea ("MODSIGN: Provide module signing public keys to the kernel")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Closes: https://lore.kernel.org/r/20260508033917.B5873C2BCB0@smtp.kernel.org/
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: stable@vger.kernel.org # v3.7+
+Reviewed-by: Ignat Korchagin <ignat@linux.win>
+Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ crypto/asymmetric_keys/x509_loader.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/crypto/asymmetric_keys/x509_loader.c
++++ b/crypto/asymmetric_keys/x509_loader.c
+@@ -20,7 +20,7 @@ int x509_load_certificate_list(const u8
+                */
+               if (end - p < 4)
+                       goto dodgy_cert;
+-              if (p[0] != 0x30 &&
++              if (p[0] != 0x30 ||
+                   p[1] != 0x82)
+                       goto dodgy_cert;
+               plen = (p[2] << 8) | p[3];