CVE-2026-98369: xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject()
In the Linux kernel, the following vulnerability has been resolved:
xfrm: add missing rcureadlock(), skbdstforce() and devhold() for xfrmtransreinject()
syzbot reported a suspicious RCU usage warning in ip6pktdrop():
WARNING: suspicious RCU usage in ip6pktdrop include/net/addrconf.h:389 suspicious rcudereferencecheck() usage!
Call Trace: in6devgetsafely include/net/addrconf.h:389 [inline] ip6pktdrop+0x596/0x610 net/ipv6/route.c:4620 ip6pktdiscard+0x1c/0x30 net/ipv6/route.c:4651 xfrmtransreinject+0x324/0x630 net/xfrm/xfrminput.c:806 processonework kernel/workqueue.c:3322 [inline] processscheduledworks+0xa8e/0x14e0 kernel/workqueue.c:3405 workerthread+0xa47/0xfb0 kernel/workqueue.c:3486
When commit 4f4920669d21 ("xfrm: Reinject transport-mode packets through workqueue") converted xfrmtransreinject from a tasklet to a workqueue, the reinjection loop ceased running in softirq context. Workqueue workers run in process context where localbhdisable() does not enter an RCU read-side critical section under CONFIGPREEMPTRCU.
Because finish callbacks (such as ip6rcvfinish) expect to run under an RCU read lock (performing route lookups, l3mdev lookups, and accessing RCU-protected data structures), invoking them in workqueue context without rcureadlock() triggers RCU lockdep warnings.
Furthermore, packets queued to the workqueue via xfrmtransqueuenet() may carry non-refcounted (noref) dst entries (e.g. from iprouteinputnoref). Additionally, on netdevice unregistration, dstdevput() replaces dst->dev with blackholenetdev, so dst entries do not keep skb->dev alive while queued in the workqueue.
Fix these issues by: 1. Calling skbdstforce(skb) in xfrmtransqueuenet() while still in the caller's RCU section to ensure dst is reference-counted before queuing. 2. Holding a reference on skb->dev via devhold()/devput() across workqueue deferral so skb->dev remains valid during finish() callback processing. 3. Acquiring rcureadlock() around the finish callback invocation loop in xfrmtransreinject().
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 6.6.158.1-1 - Upgrade
Upgrade
debian/linuxto a version that resolves this vulnerability.Fixed in 6.1.190-1Fixed in 6.12.115-2Fixed in 7.2.12-1Fixed in 7.2.15-1 - Upgrade
Upgrade
debian/linux-6.12to a version that resolves this vulnerability.Fixed in 6.12.113-1~deb12u1 - Upgrade
Upgrade
ubuntu/linux-aws-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1119.126~20.04.1 - Upgrade
Upgrade
ubuntu/linux-azure-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1125.134~20.04.1 - Upgrade
Upgrade
ubuntu/linux-azure-fde-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1124.133~20.04.1 - Upgrade
Upgrade
ubuntu/linux-gcp-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1120.130~20.04.1 - Upgrade
Upgrade
ubuntu/linux-hwe-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-202.212~20.04.1 - Upgrade
Upgrade
ubuntu/linux-ibm-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1113.117~20.04.1 - Upgrade
Upgrade
ubuntu/linux-intel-iotg-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1114.120~20.04.1 - Upgrade
Upgrade
ubuntu/linux-lowlatency-hwe-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-197.207~20.04.1 - Upgrade
Upgrade
ubuntu/linux-nvidia-tegra-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1070.72~20.04.1 - Upgrade
Upgrade
ubuntu/linux-oracle-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1116.122~20.04.1 - Upgrade
Upgrade
ubuntu/linux-riscv-5.15to a version that resolves this vulnerability.Fixed in 5.15.0-1113.117~20.04.2 - Upgrade
Upgrade
ubuntu/linuxto a version that resolves this vulnerability.Fixed in 5.15.0-202.212 - Upgrade
Upgrade
ubuntu/linux-awsto a version that resolves this vulnerability.Fixed in 5.15.0-1119.126 - Upgrade
Upgrade
ubuntu/linux-azureto a version that resolves this vulnerability.Fixed in 5.15.0-1125.134 - Upgrade
Upgrade
ubuntu/linux-gcpto a version that resolves this vulnerability.Fixed in 5.15.0-1120.130 - Upgrade
Upgrade
ubuntu/linux-gketo a version that resolves this vulnerability.Fixed in 5.15.0-1115.121 - Upgrade
Upgrade
ubuntu/linux-gkeopto a version that resolves this vulnerability.Fixed in 5.15.0-1102.110 - Upgrade
Upgrade
ubuntu/linux-ibmto a version that resolves this vulnerability.Fixed in 5.15.0-1113.117 - Upgrade
Upgrade
ubuntu/linux-intel-iotgto a version that resolves this vulnerability.Fixed in 5.15.0-1114.120 - Upgrade
Upgrade
ubuntu/linux-kvmto a version that resolves this vulnerability.Fixed in 5.15.0-1111.116 - Upgrade
Upgrade
ubuntu/linux-lowlatencyto a version that resolves this vulnerability.Fixed in 5.15.0-197.207 - Upgrade
Upgrade
ubuntu/linux-nvidiato a version that resolves this vulnerability.Fixed in 5.15.0-1114.115 - Upgrade
Upgrade
ubuntu/linux-nvidia-tegrato a version that resolves this vulnerability.Fixed in 5.15.0-1070.72 - Upgrade
Upgrade
ubuntu/linux-nvidia-tegra-igxto a version that resolves this vulnerability.Fixed in 5.15.0-1059.59 - Upgrade
Upgrade
ubuntu/linux-oracleto a version that resolves this vulnerability.Fixed in 5.15.0-1116.122 - Upgrade
Upgrade
ubuntu/linux-bluefieldto a version that resolves this vulnerability.Fixed in 5.15.0-1103.105 - Upgrade
Upgrade
ubuntu/linux-intel-iot-realtimeto a version that resolves this vulnerability.Fixed in 5.15.0-1111.115 - Upgrade
Upgrade
ubuntu/linux-realtimeto a version that resolves this vulnerability.Fixed in 5.15.0-1118.127 - Upgrade
Upgrade
ubuntu/linux-aws-fipsto a version that resolves this vulnerability.Fixed in 5.15.0-1119.126+fips1 - Upgrade
Upgrade
ubuntu/linux-azure-fipsto a version that resolves this vulnerability.Fixed in 5.15.0-1125.134+fips1 - Upgrade
Upgrade
ubuntu/linux-fipsto a version that resolves this vulnerability.Fixed in 5.15.0-202.212+fips1 - Upgrade
Upgrade
ubuntu/linux-gcp-fipsto a version that resolves this vulnerability.Fixed in 5.15.0-1120.130+fips1 - Upgrade
Upgrade
ubuntu/linux-hwe-7.0to a version that resolves this vulnerability.Fixed in 7.0.0-42.42~24.04.1 - Upgrade
Upgrade
ubuntu/linux-riscv-7.0to a version that resolves this vulnerability.Fixed in 7.0.0-42.42.1~24.04.1 - Upgrade
Upgrade
ubuntu/linuxto a version that resolves this vulnerability.Fixed in 7.0.0-42.42 - Upgrade
Upgrade
ubuntu/linux-awsto a version that resolves this vulnerability.Fixed in 7.0.0-1016.17 - Upgrade
Upgrade
ubuntu/linux-gcpto a version that resolves this vulnerability.Fixed in 7.0.0-1016.18 - Upgrade
Upgrade
ubuntu/linux-ibmto a version that resolves this vulnerability.Fixed in 7.0.0-1017.17 - Upgrade
Upgrade
ubuntu/linux-oem-7.0to a version that resolves this vulnerability.Fixed in 7.0.0-1017.17 - Upgrade
Upgrade
ubuntu/linux-oracleto a version that resolves this vulnerability.Fixed in 7.0.0-1015.16 - Upgrade
Upgrade
ubuntu/linux-riscvto a version that resolves this vulnerability.Fixed in 7.0.0-42.42.1 - Compensating control
Wrap the finish callback invocation loop in xfrm_trans_reinject() with rcu_read_lock() and the corresponding unlock so callbacks such as ip6_rcv_finish run under an RCU read-side critical section in workqueue context.
- Compensating control
Call skb_dst_force(skb) in xfrm_trans_queue_net() while still in the caller's RCU section, before queuing, so the skb destination is reference-counted.
- Compensating control
Hold a reference to skb->dev with dev_hold() before workqueue deferral and release it with dev_put() after processing, so the device remains valid while finish callbacks run.
Event History
Frequently Asked Questions
Is CONFIG_PREEMPT_RCU relevant to this issue?
Yes. The reported condition occurs because workqueue workers run in process context, where local_bh_disable() does not enter an RCU read-side critical section under CONFIG_PREEMPT_RCU.
What code path is involved in the reported warning?
The warning was reported during transport-mode packet reinjection through xfrm_trans_reinject(), with the call trace reaching ip6_pkt_drop() and ip6_pkt_discard(). The affected reinjection loop was moved from tasklet context to a workqueue.