From: Greg Kroah-Hartman Date: Tue, 14 Jul 2026 14:57:52 +0000 (+0200) Subject: 6.12-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=956955651e1cbe7703924885391288843733bb2f;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-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-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.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-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch hid-wacom-stop-hardware-after-post-start-probe-failures.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 posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.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-6.12/clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch b/queue-6.12/clocksource-drivers-timer-tegra186-fix-support-for-multiple-watchdog-instances.patch new file mode 100644 index 0000000000..095cee2ca4 --- /dev/null +++ b/queue-6.12/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 +@@ -144,7 +144,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-6.12/cpufreq-fix-hotplug-suspend-race-during-reboot.patch b/queue-6.12/cpufreq-fix-hotplug-suspend-race-during-reboot.patch new file mode 100644 index 0000000000..bad99ac745 --- /dev/null +++ b/queue-6.12/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 +@@ -1958,6 +1958,7 @@ void cpufreq_suspend(void) + if (!cpufreq_driver) + return; + ++ cpus_read_lock(); + if (!has_target() && !cpufreq_driver->suspend) + goto suspend; + +@@ -1977,6 +1978,7 @@ void cpufreq_suspend(void) + + suspend: + cpufreq_suspended = true; ++ cpus_read_unlock(); + } + + /** diff --git a/queue-6.12/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch b/queue-6.12/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch new file mode 100644 index 0000000000..e72a86ee1a --- /dev/null +++ b/queue-6.12/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 +@@ -2926,10 +2926,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-6.12/cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch b/queue-6.12/cpufreq-pcc-fix-use-after-free-and-double-free-in-_osc-evaluation.patch new file mode 100644 index 0000000000..4b4df0cb99 --- /dev/null +++ b/queue-6.12/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-6.12/cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch b/queue-6.12/cpufreq-qcom-cpufreq-hw-fix-possible-double-free.patch new file mode 100644 index 0000000000..483d5e2101 --- /dev/null +++ b/queue-6.12/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 +@@ -584,7 +584,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-6.12/firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch b/queue-6.12/firmware_loader-fix-device-reference-leak-in-firmware_upload_register.patch new file mode 100644 index 0000000000..ae9ee22c5a --- /dev/null +++ b/queue-6.12/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 +@@ -341,7 +341,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, +@@ -349,10 +348,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) { +@@ -363,9 +364,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-6.12/hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch b/queue-6.12/hid-hid-goodix-spi-validate-report-size-to-prevent-stack-buffer-overflow.patch new file mode 100644 index 0000000000..561662b40d --- /dev/null +++ b/queue-6.12/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 +@@ -515,6 +515,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-6.12/hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch b/queue-6.12/hid-letsketch-fix-uaf-on-inrange_timer-at-driver-unbind.patch new file mode 100644 index 0000000000..f6303d003f --- /dev/null +++ b/queue-6.12/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 +@@ -295,13 +295,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[] = { +@@ -314,6 +343,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-6.12/hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch b/queue-6.12/hid-lg-g15-cancel-pending-work-on-remove-to-fix-a-use-after-free.patch new file mode 100644 index 0000000000..36c69c534a --- /dev/null +++ b/queue-6.12/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 +@@ -945,11 +945,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-6.12/hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch b/queue-6.12/hid-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch new file mode 100644 index 0000000000..a61a6e8a03 --- /dev/null +++ b/queue-6.12/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, +@@ -480,6 +528,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); +@@ -520,12 +570,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; + }; + + /** +@@ -183,6 +187,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-6.12/hid-wacom-stop-hardware-after-post-start-probe-failures.patch b/queue-6.12/hid-wacom-stop-hardware-after-post-start-probe-failures.patch new file mode 100644 index 0000000000..8c5f031f84 --- /dev/null +++ b/queue-6.12/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 +@@ -2431,16 +2431,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) { +@@ -2454,14 +2454,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; + } + } + +@@ -2470,7 +2470,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-6.12/mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch b/queue-6.12/mm-slab-do-not-limit-zeroing-to-orig_size-when-only-red-zoning-is-enabled.patch new file mode 100644 index 0000000000..372607c631 --- /dev/null +++ b/queue-6.12/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 +@@ -4115,15 +4115,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-6.12/opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch b/queue-6.12/opp-of-fix-potential-memory-leak-in-opp_parse_supplies.patch new file mode 100644 index 0000000000..142a997ded --- /dev/null +++ b/queue-6.12/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 +@@ -737,7 +737,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++) { +@@ -760,6 +760,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-6.12/perf-arm-cmn-fix-dvm-node-events.patch b/queue-6.12/perf-arm-cmn-fix-dvm-node-events.patch new file mode 100644 index 0000000000..1d05409615 --- /dev/null +++ b/queue-6.12/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 */ +@@ -921,14 +922,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-6.12/posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch b/queue-6.12/posix-cpu-timers-fix-pid-refcount-leak-in-do_cpu_nanosleep-error-path.patch new file mode 100644 index 0000000000..6effd99da2 --- /dev/null +++ b/queue-6.12/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 +@@ -1498,6 +1498,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-6.12/sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch b/queue-6.12/sched-rt-have-rt_push_ipi-be-default-off-for-non-preempt_rt.patch new file mode 100644 index 0000000000..a9c5dcfccb --- /dev/null +++ b/queue-6.12/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 +@@ -104,8 +104,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-6.12/series b/queue-6.12/series index 73899e0469..615a55be3e 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -183,3 +183,24 @@ 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 +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 +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 +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 +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-wacom-stop-hardware-after-post-start-probe-failures.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-sensor-hub-add-sensor_hub_input_attr_read_values-for-multi-byte-reads.patch diff --git a/queue-6.12/time-jiffies-register-jiffies-clocksource-before-usage.patch b/queue-6.12/time-jiffies-register-jiffies-clocksource-before-usage.patch new file mode 100644 index 0000000000..d9cd14e49d --- /dev/null +++ b/queue-6.12/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 +@@ -61,15 +61,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-6.12/tools-mm-slabinfo-fix-total_objects-attribute-name.patch b/queue-6.12/tools-mm-slabinfo-fix-total_objects-attribute-name.patch new file mode 100644 index 0000000000..9a4d8d77b8 --- /dev/null +++ b/queue-6.12/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; +@@ -1256,7 +1256,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-6.12/tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch b/queue-6.12/tools-mm-slabinfo-fix-trace-disable-logic-inversion.patch new file mode 100644 index 0000000000..0e2e275bf5 --- /dev/null +++ b/queue-6.12/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 +@@ -795,7 +795,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-6.12/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch b/queue-6.12/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch new file mode 100644 index 0000000000..81ad641e5d --- /dev/null +++ b/queue-6.12/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 +@@ -651,12 +651,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; + +@@ -671,9 +678,11 @@ static void inode_switch_wbs(struct inod + isw->inodes[0] = inode; + + 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); +@@ -732,6 +741,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 +@@ -749,6 +766,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); +@@ -756,6 +774,7 @@ bool cleanup_offline_cgwb(struct bdi_wri + } + + wb_queue_isw(new_wb, isw); ++ rcu_read_unlock(); + + return restart; + } +@@ -1192,6 +1211,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-6.12/x.509-fix-validation-of-asn.1-certificate-header.patch b/queue-6.12/x.509-fix-validation-of-asn.1-certificate-header.patch new file mode 100644 index 0000000000..ec56166c9a --- /dev/null +++ b/queue-6.12/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];