From: Sasha Levin Date: Sat, 11 Jul 2026 10:20:26 +0000 (-0400) Subject: Fixes for all trees X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6e72ea996fe2dc6bcd8cb5028fc5d696221c21ec;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/series b/queue-5.10/series index 0569543865..472aded08b 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -29,3 +29,4 @@ i2c-core-fix-null-deref-on-adapter-registration-failure.patch i2c-core-fix-adapter-debugfs-creation.patch i2c-core-fix-adapter-registration-race.patch hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch +xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_s.patch diff --git a/queue-5.10/xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_s.patch b/queue-5.10/xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_s.patch new file mode 100644 index 0000000000..f89d8e7ffa --- /dev/null +++ b/queue-5.10/xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_s.patch @@ -0,0 +1,123 @@ +From 3da63545018349871fce2f979ffabaa4419a0b00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 22:30:15 +0000 +Subject: xfrm: defensively unhash xfrm_state lists in __xfrm_state_delete + +From: Michal Kosiorek + +[ Upstream commit 14acf9652e5690de3c7486c6db5fb8dafd0a32a3 ] + +KASAN reproduces a slab-use-after-free in __xfrm_state_delete()'s +hlist_del_rcu calls under syzkaller load on linux-6.12.y stable +(reproduced on 6.12.47, also reachable via the same code path on +torvalds/master and on the ipsec tree). Nine unique signatures cluster +in the xfrm_state lifecycle, the load-bearing one being: + + BUG: KASAN: slab-use-after-free in __hlist_del include/linux/list.h:990 [inline] + BUG: KASAN: slab-use-after-free in hlist_del_rcu include/linux/rculist.h:516 [inline] + BUG: KASAN: slab-use-after-free in __xfrm_state_delete net/xfrm/xfrm_state.c + Write of size 8 at addr ffff8881198bcb70 by task kworker/u8:9/435 + + Workqueue: netns cleanup_net + Call Trace: + __hlist_del / hlist_del_rcu + __xfrm_state_delete + xfrm_state_delete + xfrm_state_flush + xfrm_state_fini + ops_exit_list + cleanup_net + +The other observed signatures hit the same slab object from +__xfrm_state_lookup, xfrm_alloc_spi, __xfrm_state_insert and an OOB +write variant of __xfrm_state_delete, all on the byseq/byspi +hash chains. + +__xfrm_state_delete() guards its byseq and byspi unhashes with +value-based predicates: + + if (x->km.seq) + hlist_del_rcu(&x->byseq); + if (x->id.spi) + hlist_del_rcu(&x->byspi); + +while everywhere else in the file (e.g. state_cache, state_cache_input) +the safer hlist_unhashed() check is used. xfrm_alloc_spi() sets +x->id.spi = newspi inside xfrm_state_lock and then immediately inserts +into byspi, but a path that observes x->id.spi != 0 outside of +xfrm_state_lock can still skip-or-hit the byspi unhash inconsistently +with whether x is actually on the list. The same holds for x->km.seq +versus byseq, and the bydst/bysrc unhashes have no predicate at all, +so a second __xfrm_state_delete() on the same object writes through +LIST_POISON pprev. + +The defensive change here: + + - Use hlist_del_init_rcu() instead of hlist_del_rcu() on bydst, + bysrc, byseq and byspi so a second deletion is a no-op rather + than a write through LIST_POISON pprev. The byseq/byspi nodes + are already initialised in xfrm_state_alloc(). + - Test hlist_unhashed() rather than the value predicate for + byseq/byspi, so the unhash decision tracks list state rather than + mutable scalar fields. + +Empirical verification: applied this patch on top of v6.12.47, rebuilt, +and re-ran the same syzkaller harness for 1h16m on a previously-crashy +configuration that produced ~100 hits each of slab-use-after-free +Read in xfrm_alloc_spi / Read in __xfrm_state_lookup / Write in +__xfrm_state_delete. After the patch, 7.1M execs across 32 VMs at +~1550 exec/sec produced zero xfrm_state UAF/OOB hits. /proc/slabinfo +confirms the xfrm_state slab is actively allocated and freed during +the run (~143 KiB resident), so the fuzzer is still exercising those +code paths -- they just no longer crash. + +Reproduction: + + - Linux 6.12.47 x86_64 + KASAN_GENERIC + KASAN_INLINE + KCOV + - syzkaller @ 746545b8b1e4c3a128db8652b340d3df90ce61db + - 32 QEMU/KVM VMs x 2 vCPU on AWS c5.metal bare metal + - 9 unique signatures collected in ~9h, all within xfrm_state + lifecycle + +Fixes: fe9f1d8779cb ("xfrm: add state hashtable keyed by seq") +Fixes: 7b4dc3600e48 ("[XFRM]: Do not add a state whose SPI is zero to the SPI hash.") +Reported-by: Michal Kosiorek +Tested-by: Michal Kosiorek +Cc: stable@vger.kernel.org +Signed-off-by: Michal Kosiorek +Signed-off-by: Steffen Klassert +[ 5.10: drop state_cache{,_input} lines from context because 81a331a +("xfrm: Add an inbound percpu state cache.") does not exist yet, drop +xfrm_nat_keepalive_state_updated line from context because f531d13 +("xfrm: support sending NAT keepalives in ESP in UDP states") does not +exist yet, and remove byseq since that optimization in fe9f1d8 ("xfrm: +add state hashtable keyed by seq") does not exist yet ] +Signed-off-by: Mark Bundschuh +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 61a0a5b843d9e7..8c742258952b8a 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -659,10 +659,11 @@ int __xfrm_state_delete(struct xfrm_state *x) + x->km.state = XFRM_STATE_DEAD; + spin_lock(&net->xfrm.xfrm_state_lock); + list_del(&x->km.all); +- hlist_del_rcu(&x->bydst); +- hlist_del_rcu(&x->bysrc); +- if (x->id.spi) +- hlist_del_rcu(&x->byspi); ++ hlist_del_init_rcu(&x->bydst); ++ hlist_del_init_rcu(&x->bysrc); ++ ++ if (!hlist_unhashed(&x->byspi)) ++ hlist_del_init_rcu(&x->byspi); + net->xfrm.state_num--; + spin_unlock(&net->xfrm.xfrm_state_lock); + +-- +2.53.0 + diff --git a/queue-6.1/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch b/queue-6.1/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch new file mode 100644 index 0000000000..ec088e8677 --- /dev/null +++ b/queue-6.1/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch @@ -0,0 +1,81 @@ +From f4fc229c232f6d4ea55c43c2d7e72bd3a6875544 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 22:51:47 +0000 +Subject: MIPS: smp: report dying CPU to RCU in stop_this_cpu() + +From: Jonas Jelonek + +commit 9f3f3bdc6d9dac1a5a8262ee7ad0f2ff1527a7e7 upstream. + +smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function +marks the CPU offline for the scheduler via set_cpu_online(false) but +never informs RCU, so RCU keeps expecting a quiescent state from CPUs +that are now spinning forever with interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. Since commit +91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +however, irq_work_sync() calls synchronize_rcu() on architectures without +an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns +false. That is the asm-generic default used by MIPS. Any irq_work_sync() +issued in the reboot/shutdown path after smp_send_stop() then blocks on +a grace period that can never complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue was noticed on several Realtek MIPS switch SoCs (MIPS +interAptiv) and came up during kernel bump downstream in OpenWrt from +6.18.33 to 6.18.34, after the backport of the patch to the 6.18 stable +branch. The patch also has been backported all the way back to 6.1. + +Call rcu_report_dead() once interrupts are disabled, mirroring the +generic CPU-hotplug offline path, so RCU stops waiting on the parked CPUs +and grace periods can still complete. MIPS shuts down all CPUs here +without going through the CPU-hotplug mechanism, so this report is not +otherwise issued. Reporting a dying CPU to RCU outside the regular hotplug +offline path is not unprecedented: arm64 does the same in cpu_die_early(). +There it is an exception for a CPU that was coming online and is aborting +bringup, rather than the default shutdown action as on MIPS. + +Note: this differs from the upstream commit in that it calls +rcu_report_dead(smp_processor_id()) instead of rcutree_report_cpu_dead(). +The latter, along with the rcutree_report_cpu_dead() name, was introduced +by commit 448e9f34d91d ("rcu: Standardize explicit CPU-hotplug calls") +in v6.7; on this kernel the equivalent function is still named +rcu_report_dead() and takes an explicit CPU argument. + +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +Signed-off-by: Jonas Jelonek +Signed-off-by: Sasha Levin +--- + arch/mips/kernel/smp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c +index 002c91fcb842ec..06030533bcfacd 100644 +--- a/arch/mips/kernel/smp.c ++++ b/arch/mips/kernel/smp.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -392,6 +393,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcu_report_dead(smp_processor_id()); + while (1); + } + +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 42fbeb8e33..858f132f67 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -48,3 +48,4 @@ acpi-cppc-suppress-ubsan-warning-caused-by-field-misuse.patch rust-kbuild-set-frame-pointer-llvm-module-flag-for-config_frame_pointer.patch perf-core-detach-event-groups-during-remove_on_exec.patch virtio_net-support-dynamic-rss-indirection-table-siz.patch +mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch diff --git a/queue-6.6/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch b/queue-6.6/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch new file mode 100644 index 0000000000..2ef1cbe353 --- /dev/null +++ b/queue-6.6/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch @@ -0,0 +1,81 @@ +From edee3985d8e72f7c366f2f8565011a4ae82780ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 22:36:27 +0000 +Subject: MIPS: smp: report dying CPU to RCU in stop_this_cpu() + +From: Jonas Jelonek + +commit 9f3f3bdc6d9dac1a5a8262ee7ad0f2ff1527a7e7 upstream. + +smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function +marks the CPU offline for the scheduler via set_cpu_online(false) but +never informs RCU, so RCU keeps expecting a quiescent state from CPUs +that are now spinning forever with interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. Since commit +91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +however, irq_work_sync() calls synchronize_rcu() on architectures without +an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns +false. That is the asm-generic default used by MIPS. Any irq_work_sync() +issued in the reboot/shutdown path after smp_send_stop() then blocks on +a grace period that can never complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue was noticed on several Realtek MIPS switch SoCs (MIPS +interAptiv) and came up during kernel bump downstream in OpenWrt from +6.18.33 to 6.18.34, after the backport of the patch to the 6.18 stable +branch. The patch also has been backported all the way back to 6.1. + +Call rcu_report_dead() once interrupts are disabled, mirroring the +generic CPU-hotplug offline path, so RCU stops waiting on the parked CPUs +and grace periods can still complete. MIPS shuts down all CPUs here +without going through the CPU-hotplug mechanism, so this report is not +otherwise issued. Reporting a dying CPU to RCU outside the regular hotplug +offline path is not unprecedented: arm64 does the same in cpu_die_early(). +There it is an exception for a CPU that was coming online and is aborting +bringup, rather than the default shutdown action as on MIPS. + +Note: this differs from the upstream commit in that it calls +rcu_report_dead(smp_processor_id()) instead of rcutree_report_cpu_dead(). +The latter, along with the rcutree_report_cpu_dead() name, was introduced +by commit 448e9f34d91d ("rcu: Standardize explicit CPU-hotplug calls") +in v6.7; on this kernel the equivalent function is still named +rcu_report_dead() and takes an explicit CPU argument. + +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +Signed-off-by: Jonas Jelonek +Signed-off-by: Sasha Levin +--- + arch/mips/kernel/smp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c +index 81f6c4f8fbc154..1a3eb4820eb702 100644 +--- a/arch/mips/kernel/smp.c ++++ b/arch/mips/kernel/smp.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -410,6 +411,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcu_report_dead(smp_processor_id()); + while (1); + } + +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index c932cd2864..72dc82f191 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -79,3 +79,4 @@ virtio_net-support-dynamic-rss-indirection-table-siz.patch revert-loongarch-add-pio-for-early-access-before-acp.patch loongarch-add-pio-for-early-access-before-acpi-pci-r.patch net-drop-the-lock-in-skb_may_tx_timestamp.patch +mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch