]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees master
authorSasha Levin <sashal@kernel.org>
Sat, 11 Jul 2026 10:20:26 +0000 (06:20 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 11 Jul 2026 10:20:26 +0000 (06:20 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/series
queue-5.10/xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_s.patch [new file with mode: 0644]
queue-6.1/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch [new file with mode: 0644]
queue-6.1/series
queue-6.6/mips-smp-report-dying-cpu-to-rcu-in-stop_this_cpu.patch [new file with mode: 0644]
queue-6.6/series

index 05695438659fe367585c7eb314acdf090591fcad..472aded08b26600e1e2fb1dfc17f81137be75263 100644 (file)
@@ -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 (file)
index 0000000..f89d8e7
--- /dev/null
@@ -0,0 +1,123 @@
+From 3da63545018349871fce2f979ffabaa4419a0b00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jul 2026 22:30:15 +0000
+Subject: xfrm: defensively unhash xfrm_state lists in __xfrm_state_delete
+
+From: Michal Kosiorek <mkosiorek121@gmail.com>
+
+[ 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 <mkosiorek121@gmail.com>
+Tested-by: Michal Kosiorek <mkosiorek121@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Michal Kosiorek <mkosiorek121@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+[ 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 <mkbund@amazon.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..ec088e8
--- /dev/null
@@ -0,0 +1,81 @@
+From f4fc229c232f6d4ea55c43c2d7e72bd3a6875544 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jul 2026 22:51:47 +0000
+Subject: MIPS: smp: report dying CPU to RCU in stop_this_cpu()
+
+From: Jonas Jelonek <jelonek.jonas@gmail.com>
+
+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 <jelonek.jonas@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <linux/sched/mm.h>
+ #include <linux/cpumask.h>
+ #include <linux/cpu.h>
++#include <linux/rcupdate.h>
+ #include <linux/err.h>
+ #include <linux/ftrace.h>
+ #include <linux/irqdomain.h>
+@@ -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
+
index 42fbeb8e3309932f898840eb3cc95b04242f5ee1..858f132f6794018dc90e3da145938d6b4c5ddf34 100644 (file)
@@ -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 (file)
index 0000000..2ef1cbe
--- /dev/null
@@ -0,0 +1,81 @@
+From edee3985d8e72f7c366f2f8565011a4ae82780ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jul 2026 22:36:27 +0000
+Subject: MIPS: smp: report dying CPU to RCU in stop_this_cpu()
+
+From: Jonas Jelonek <jelonek.jonas@gmail.com>
+
+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 <jelonek.jonas@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <linux/sched/mm.h>
+ #include <linux/cpumask.h>
+ #include <linux/cpu.h>
++#include <linux/rcupdate.h>
+ #include <linux/err.h>
+ #include <linux/ftrace.h>
+ #include <linux/irqdomain.h>
+@@ -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
+
index c932cd28648e7d5940200eed0351d980d6a1e2cc..72dc82f1913fcb2efb87002dd2f6001c2c662546 100644 (file)
@@ -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