From: Greg Kroah-Hartman Date: Tue, 14 Jul 2026 14:55:18 +0000 (+0200) Subject: 7.1-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a4031b62d787190c172fb86770a217248c970e4;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches 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 --- 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 index 0000000000..c3b1425100 --- /dev/null +++ b/queue-7.1/clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch @@ -0,0 +1,41 @@ +From ca57bf46e7a94f8c53d05c376df9fcfdcb482100 Mon Sep 17 00:00:00 2001 +From: Kartik Rajput +Date: Thu, 7 May 2026 21:15:54 +0530 +Subject: clocksource/drivers/timer-tegra186: Fix support for multiple watchdog instances + +From: Kartik Rajput + +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 +Signed-off-by: Daniel Lezcano +Reviewed-by: Jon Hunter +Link: https://patch.msgid.link/20260507154557.2082697-2-kkartik@nvidia.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..3db6817932 --- /dev/null +++ b/queue-7.1/cpufreq-fix-hotplug-suspend-race-during-reboot.patch @@ -0,0 +1,62 @@ +From a9029dd55696c651ee46912afa2a166fa456bb3e Mon Sep 17 00:00:00 2001 +From: Tianxiang Chen +Date: Wed, 8 Apr 2026 22:19:14 +0800 +Subject: cpufreq: Fix hotplug-suspend race during reboot + +From: Tianxiang Chen + +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 +Reviewed-by: Zhongqiu Han +Cc: All applicable +[ rjw: Changelog edits ] +Link: https://patch.msgid.link/20260408141914.35281-1-nanmu@xiaomi.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..608d456106 --- /dev/null +++ b/queue-7.1/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch @@ -0,0 +1,51 @@ +From bcbdaa1086c25a8a5d48e04e1b82fdfb0682b681 Mon Sep 17 00:00:00 2001 +From: Fushuai Wang +Date: Wed, 20 May 2026 11:21:19 +0800 +Subject: cpufreq: intel_pstate: Sync policy->cur during CPU offline + +From: Fushuai Wang + +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 +Signed-off-by: Fushuai Wang +[ rjw: Subject refinement ] +Link: https://patch.msgid.link/20260520032119.30615-1-fushuai.wang@linux.dev +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..4b4df0cb99 --- /dev/null +++ b/queue-7.1/cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch @@ -0,0 +1,43 @@ +From 266d3dd8b757b48a576e90f018b51f7b7563cc32 Mon Sep 17 00:00:00 2001 +From: Yuho Choi +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 + +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 +Reviewed-by: Zhongqiu Han +Cc: All applicable +Link: https://patch.msgid.link/20260416144621.93964-1-dbgh9129@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..5f28bf9bf9 --- /dev/null +++ b/queue-7.1/cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch @@ -0,0 +1,44 @@ +From bcb8889c4981fdde42d4fd2c29a77d510fe21da2 Mon Sep 17 00:00:00 2001 +From: Guangshuo Li +Date: Sat, 2 May 2026 03:00:05 +0800 +Subject: cpufreq: qcom-cpufreq-hw: Fix possible double free + +From: Guangshuo Li + +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 +Reviewed-by: Zhongqiu Han +Signed-off-by: Viresh Kumar +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e9658dbe04 --- /dev/null +++ b/queue-7.1/firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch @@ -0,0 +1,73 @@ +From 896df22ee57648b0c505bd76ddbc6b2341834696 Mon Sep 17 00:00:00 2001 +From: Guangshuo Li +Date: Tue, 5 May 2026 17:12:31 +0800 +Subject: firmware_loader: fix device reference leak in firmware_upload_register() + +From: Guangshuo Li + +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 +Link: https://patch.msgid.link/20260505091231.607089-1-lgs201920130244@gmail.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..5b9effd36a --- /dev/null +++ b/queue-7.1/hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch @@ -0,0 +1,146 @@ +From 75fe87e19d8aff81eb2c64d15d244ab8da4de945 Mon Sep 17 00:00:00 2001 +From: Manish Khadka +Date: Fri, 15 May 2026 23:17:52 +0545 +Subject: HID: appleir: fix UAF on pending key_up_timer in remove() + +From: Manish Khadka + +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 +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..fa2f93b3e9 --- /dev/null +++ b/queue-7.1/hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch @@ -0,0 +1,48 @@ +From db0a0768d09273aadadeb76730cd658d720333a4 Mon Sep 17 00:00:00 2001 +From: Tianchu Chen +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 + +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 +Reviewed-by: Dmitry Torokhov +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..637f9c510f --- /dev/null +++ b/queue-7.1/hid-hid-lenovo-go-cancel-cfg_setup-work-in-hid_go_cfg_remove.patch @@ -0,0 +1,56 @@ +From 73fde0cbff7d9d618591774a12c23434232752c1 Mon Sep 17 00:00:00 2001 +From: Manish Khadka +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 + +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 +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ce443c3a95 --- /dev/null +++ b/queue-7.1/hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch @@ -0,0 +1,105 @@ +From 46c8beeccd8ab2c863827254a85ea877654a3534 Mon Sep 17 00:00:00 2001 +From: Manish Khadka +Date: Fri, 15 May 2026 22:27:00 +0545 +Subject: HID: letsketch: fix UAF on inrange_timer at driver unbind + +From: Manish Khadka + +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 +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..5fc962426d --- /dev/null +++ b/queue-7.1/hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch @@ -0,0 +1,68 @@ +From 7705b4140d188ce22656f6e541ae7ef834c7e11a Mon Sep 17 00:00:00 2001 +From: Maoyi Xie +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 + +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 +Signed-off-by: Maoyi Xie +Reviewed-by: Hans de Goede +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e5c69466df --- /dev/null +++ b/queue-7.1/hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch @@ -0,0 +1,154 @@ +From 8813b0612275cc61fe9e6603d0ee019247ade6be Mon Sep 17 00:00:00 2001 +From: Trung Nguyen +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 + +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 +Signed-off-by: Benjamin Tissoires +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include + #include +@@ -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 index 0000000000..88d821d85e --- /dev/null +++ b/queue-7.1/hid-pidff-use-correct-effect-type-in-effect-update.patch @@ -0,0 +1,43 @@ +From b251598b8bf37300510868f739a79e07800d41ce Mon Sep 17 00:00:00 2001 +From: Oleg Makarenko +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 + +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 +Co-developed-by: Ryno Kotzé +Signed-off-by: Ryno Kotzé +Signed-off-by: Oleg Makarenko +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..8e40a665f5 --- /dev/null +++ b/queue-7.1/hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch @@ -0,0 +1,179 @@ +From f784fcea450617055d2d12eec5b2f6e0e38bf878 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +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 + +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 +Co-developed-by: Zhang Lixu +Signed-off-by: Zhang Lixu +Acked-by: Jiri Kosina +Reviewed-by: Andy Shevchenko +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..cc87842ecf --- /dev/null +++ b/queue-7.1/hid-uhid-convert-to-hid_safe_input_report.patch @@ -0,0 +1,64 @@ +From 63a694c51bf120a37550890b8e7736b4888985e9 Mon Sep 17 00:00:00 2001 +From: Carlos Llamas +Date: Sat, 6 Jun 2026 18:15:52 +0000 +Subject: HID: uhid: convert to hid_safe_input_report() + +From: Carlos Llamas + +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 +Reviewed-by: Lee Jones +Closes: https://lore.kernel.org/all/ahsh0UtTX6e0ZeHa@google.com/ +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..219439f4aa --- /dev/null +++ b/queue-7.1/hid-wacom-fix-slab-out-of-bounds-write-in-wacom_wac_queue_insert.patch @@ -0,0 +1,60 @@ +From 6b3014ec0e9a390ca563030b2d7689921f0daef5 Mon Sep 17 00:00:00 2001 +From: Jinmo Yang +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 + +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 +Fixes: 5e013ad20689 ("HID: wacom: Remove static WACOM_PKGLEN_MAX limit") +Cc: stable@vger.kernel.org +Signed-off-by: Jinmo Yang +Reviewed-by: Dmitry Torokhov +Signed-off-by: Benjamin Tissoires +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..0bf50bce87 --- /dev/null +++ b/queue-7.1/hid-wacom-stop-hardware-after-post-start-probe-failures.patch @@ -0,0 +1,80 @@ +From ec2612b8ad9e642596db011dd8b6568ef1edeaa1 Mon Sep 17 00:00:00 2001 +From: Myeonghun Pak +Date: Thu, 4 Jun 2026 13:56:58 +0900 +Subject: HID: wacom: stop hardware after post-start probe failures + +From: Myeonghun Pak + +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 +Signed-off-by: Ijae Kim +Signed-off-by: Myeonghun Pak +Reviewed-by: Dmitry Torokhov +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..d13c778e68 --- /dev/null +++ b/queue-7.1/hid-wacom-use-gfp_atomic-in-wacom_wac_queue_flush.patch @@ -0,0 +1,43 @@ +From 55f1ad573e34abf9a0443c34bc5a63d74edba7d7 Mon Sep 17 00:00:00 2001 +From: Jinmo Yang +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 + +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 +Fixes: 5e013ad20689 ("HID: wacom: Remove static WACOM_PKGLEN_MAX limit") +Cc: stable@vger.kernel.org +Reviewed-by: Dmitry Torokhov +Signed-off-by: Jinmo Yang +Signed-off-by: Benjamin Tissoires +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..d2709b8f05 --- /dev/null +++ b/queue-7.1/libfs-set-sb_i_noexec-and-sb_i_nodev-by-default-in-init_pseudo.patch @@ -0,0 +1,56 @@ +From 6de2aeffabaafaeda819e60ec8d04f199711e11a Mon Sep 17 00:00:00 2001 +From: John Hubbard +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 + +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 +Cc: stable@vger.kernel.org +Signed-off-by: John Hubbard +Link: https://patch.msgid.link/20260604025315.245910-2-jhubbard@nvidia.com +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..21a7846f27 --- /dev/null +++ b/queue-7.1/mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch @@ -0,0 +1,67 @@ +From 648927ceb84021a25a0fbd5673740956f318d534 Mon Sep 17 00:00:00 2001 +From: "Vlastimil Babka (SUSE)" +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) + +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) +Reviewed-by: Hao Li +Signed-off-by: Vlastimil Babka (SUSE) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..5fc61ad29d --- /dev/null +++ b/queue-7.1/opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch @@ -0,0 +1,41 @@ +From 69f888381d2ecbe18ed9f112c096f8fd3623db98 Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Mon, 11 May 2026 12:12:11 +0530 +Subject: OPP: of: Fix potential memory leak in opp_parse_supplies() + +From: Abdun Nihaal + +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 +Signed-off-by: Viresh Kumar +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..de4df9532e --- /dev/null +++ b/queue-7.1/perf-arm-cmn-fix-dvm-node-events.patch @@ -0,0 +1,65 @@ +From 5936245125f78d896fdb1bbc2ae79213e28a6579 Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Fri, 29 May 2026 15:33:45 +0100 +Subject: perf/arm-cmn: Fix DVM node events + +From: Robin Murphy + +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 +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..cd77b9a1ca --- /dev/null +++ b/queue-7.1/perf-x86-intel-uncore-defer-adl-global-pmon-enable-to-enable_box.patch @@ -0,0 +1,52 @@ +From 9a0bb848a37150aeccc10088e141339917d995dc Mon Sep 17 00:00:00 2001 +From: Zide Chen +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 + +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 +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Dapeng Mi +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260602144908.263680-5-zide.chen@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..9476d5a91d --- /dev/null +++ b/queue-7.1/posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch @@ -0,0 +1,40 @@ +From 87bd2ad568e15b90d5f7d4bcd70342d05dad649c Mon Sep 17 00:00:00 2001 +From: WenTao Liang +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 + +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 +Signed-off-by: Thomas Gleixner +Reviewed-by: Frederic Weisbecker +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260611161738.97043-1-vulab@iscas.ac.cn +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..cac7ac83d4 --- /dev/null +++ b/queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch @@ -0,0 +1,270 @@ +From 6255da28d4bb5349fe18e84cb043ccd394eba75d Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Mon, 18 May 2026 18:35:16 +0200 +Subject: proc: protect ptrace_may_access() with exec_update_lock (FD links) + +From: Jann Horn + +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//fd/ symlinks") +Cc: stable@vger.kernel.org +Signed-off-by: Jann Horn +Link: https://patch.msgid.link/20260518-procfs-lockfix-part1-v1-2-5c3d20e0ac33@google.com +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..821fb07e12 --- /dev/null +++ b/queue-7.1/proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch @@ -0,0 +1,203 @@ +From 6650527444dadc63d84aa939d14ecba4fadb2f69 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Mon, 18 May 2026 18:35:15 +0200 +Subject: proc: protect ptrace_may_access() with exec_update_lock (part 1) + +From: Jann Horn + +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 +Link: https://patch.msgid.link/20260518-procfs-lockfix-part1-v1-1-5c3d20e0ac33@google.com +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..66ab107a75 --- /dev/null +++ b/queue-7.1/s390-revert-support-for-dcache_word_access.patch @@ -0,0 +1,141 @@ +From 37540b8c287fc817bdbd0c62bb75ad6eab0e5d03 Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Thu, 11 Jun 2026 17:37:46 +0200 +Subject: s390: Revert support for DCACHE_WORD_ACCESS + +From: Heiko Carstens + +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 +Signed-off-by: Heiko Carstens +Signed-off-by: Alexander Gordeev +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include +-#include + #include + + 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 index 0000000000..92747b1526 --- /dev/null +++ b/queue-7.1/sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch @@ -0,0 +1,100 @@ +From dd29c017aed628076e915fe4cdfb5392fd4c5cab Mon Sep 17 00:00:00 2001 +From: Steven Rostedt +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 + +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 +Signed-off-by: Steven Rostedt +Signed-off-by: Peter Zijlstra (Intel) +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260515103740.25ccbed8@gandalf.local.home +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-7.1/series b/queue-7.1/series index d96ca80e9d..4699ca1b79 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -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 index 0000000000..9872af7ec3 --- /dev/null +++ b/queue-7.1/smb-server-do-not-require-delete-access-for-non-replacing-links.patch @@ -0,0 +1,56 @@ +From 851ed9e09639e0daf79a506ce26097b296ed5518 Mon Sep 17 00:00:00 2001 +From: ChenXiaoSong +Date: Sun, 28 Jun 2026 07:42:43 +0000 +Subject: smb/server: do not require delete access for non-replacing links + +From: ChenXiaoSong + +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 +Signed-off-by: ChenXiaoSong +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..0acc7b6fba --- /dev/null +++ b/queue-7.1/time-jiffies-register-jiffies-clocksource-before-usage.patch @@ -0,0 +1,53 @@ +From f24df84cbe05e4471c04ac4b921fc0340bbc7752 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Tue, 9 Jun 2026 17:14:45 +0200 +Subject: time/jiffies: Register jiffies clocksource before usage + +From: Thomas Gleixner + +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 +Signed-off-by: Thomas Gleixner +Tested-by: Teddy Astie +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 +--- + 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 index 0000000000..865c425977 --- /dev/null +++ b/queue-7.1/tools-mm-slabinfo-fix-total_objects-attribute-name.patch @@ -0,0 +1,46 @@ +From 892a7864730775c3dbee2a39e9ead4fa8d4256e7 Mon Sep 17 00:00:00 2001 +From: Yichong Chen +Date: Fri, 12 Jun 2026 15:13:59 +0800 +Subject: tools/mm/slabinfo: fix total_objects attribute name + +From: Yichong Chen + +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 +Cc: +Reviewed-by: SeongJae Park +Link: https://patch.msgid.link/96556748872BB47E+20260612071359.649946-1-chenyichong@uniontech.com +Signed-off-by: Vlastimil Babka (SUSE) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..77d3d84ed8 --- /dev/null +++ b/queue-7.1/tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch @@ -0,0 +1,36 @@ +From 235ab68d67eadbef1fdbfb771f21f5bacc77a2ae Mon Sep 17 00:00:00 2001 +From: Xuewen Wang +Date: Mon, 18 May 2026 14:21:57 +0800 +Subject: tools/mm/slabinfo: Fix trace disable logic inversion + +From: Xuewen Wang + +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 +Signed-off-by: Xuewen Wang +WARNING: From:/Signed-off-by: email address mismatch: 'From: wangxuewen <18810879172@163.com>' != 'Signed-off-by: wangxuewen ' +Link: https://patch.msgid.link/20260518062159.80664-2-wangxuewen@kylinos.cn +Signed-off-by: Vlastimil Babka (SUSE) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..79c4e0e089 --- /dev/null +++ b/queue-7.1/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch @@ -0,0 +1,177 @@ +From cba38ec4cbd3a7b8b942a8d52531a05be8a9ff0d Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Thu, 21 May 2026 17:50:14 +0800 +Subject: writeback: fix race between cgroup_writeback_umount() and inode_switch_wbs() + +From: Baokun Li + +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 +Link: https://lore.kernel.org/all/mxnjq2l6guusfchvauxr3v7c4bwjasybxlleqbbh4efloeqspz@iqylk76ohufz +Reviewed-by: Jan Kara +Signed-off-by: Baokun Li +Link: https://patch.msgid.link/20260521095016.2791354-2-libaokun@linux.alibaba.com +Acked-by: Tejun Heo +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ec56166c9a --- /dev/null +++ b/queue-7.1/x.509-fix-validation-of-asn.1-certificate-header.patch @@ -0,0 +1,40 @@ +From 3b626ba431c4501512ad07549310685e07fe4706 Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Thu, 14 May 2026 08:55:58 +0200 +Subject: X.509: Fix validation of ASN.1 certificate header + +From: Lukas Wunner + +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 +Closes: https://lore.kernel.org/r/20260508033917.B5873C2BCB0@smtp.kernel.org/ +Signed-off-by: Lukas Wunner +Cc: stable@vger.kernel.org # v3.7+ +Reviewed-by: Ignat Korchagin +Reviewed-by: Alistair Francis +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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];