In the Linux kernel, the following vulnerability has been resolved:
xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject()
syzbot reported a suspicious RCU usage warning in ip6_pkt_drop():
WARNING: suspicious RCU usage in ip6_pkt_drop
include/net/addrconf.h:389 suspicious rcu_dereference_check() usage!
Call Trace:
__in6_dev_get_safely include/net/addrconf.h:389 [inline]
ip6_pkt_drop+0x596/0x610 net/ipv6/route.c:4620
ip6_pkt_discard+0x1c/0x30 net/ipv6/route.c:4651
xfrm_trans_reinject+0x324/0x630 net/xfrm/xfrm_input.c:806
process_one_work kernel/workqueue.c:3322 [inline]
process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
When commit 4f4920669d21 ("xfrm: Reinject transport-mode packets through
workqueue") converted xfrm_trans_reinject from a tasklet to a workqueue,
the reinjection loop ceased running in softirq context. Workqueue workers
run in process context where local_bh_disable() does not enter an RCU
read-side critical section under CONFIG_PREEMPT_RCU.
Because finish callbacks (such as ip6_rcv_finish) 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
rcu_read_lock() triggers RCU lockdep warnings.
Furthermore, packets queued to the workqueue via xfrm_trans_queue_net()
may carry non-refcounted (noref) dst entries (e.g. from ip_route_input_noref).
Additionally, on netdevice unregistration, dst_dev_put() replaces dst->dev
with blackhole_netdev, so dst entries do not keep skb->dev alive while
queued in the workqueue.
Fix these issues by:
1. Calling skb_dst_force(skb) in xfrm_trans_queue_net() while still in the
caller's RCU section to ensure dst is reference-counted before queuing.
2. Holding a reference on skb->dev via dev_hold()/dev_put() across workqueue
deferral so skb->dev remains valid during finish() callback processing.
3. Acquiring rcu_read_lock() around the finish callback invocation loop in
xfrm_trans_reinject().
xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject()
syzbot reported a suspicious RCU usage warning in ip6_pkt_drop():
WARNING: suspicious RCU usage in ip6_pkt_drop
include/net/addrconf.h:389 suspicious rcu_dereference_check() usage!
Call Trace:
__in6_dev_get_safely include/net/addrconf.h:389 [inline]
ip6_pkt_drop+0x596/0x610 net/ipv6/route.c:4620
ip6_pkt_discard+0x1c/0x30 net/ipv6/route.c:4651
xfrm_trans_reinject+0x324/0x630 net/xfrm/xfrm_input.c:806
process_one_work kernel/workqueue.c:3322 [inline]
process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
When commit 4f4920669d21 ("xfrm: Reinject transport-mode packets through
workqueue") converted xfrm_trans_reinject from a tasklet to a workqueue,
the reinjection loop ceased running in softirq context. Workqueue workers
run in process context where local_bh_disable() does not enter an RCU
read-side critical section under CONFIG_PREEMPT_RCU.
Because finish callbacks (such as ip6_rcv_finish) 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
rcu_read_lock() triggers RCU lockdep warnings.
Furthermore, packets queued to the workqueue via xfrm_trans_queue_net()
may carry non-refcounted (noref) dst entries (e.g. from ip_route_input_noref).
Additionally, on netdevice unregistration, dst_dev_put() replaces dst->dev
with blackhole_netdev, so dst entries do not keep skb->dev alive while
queued in the workqueue.
Fix these issues by:
1. Calling skb_dst_force(skb) in xfrm_trans_queue_net() while still in the
caller's RCU section to ensure dst is reference-counted before queuing.
2. Holding a reference on skb->dev via dev_hold()/dev_put() across workqueue
deferral so skb->dev remains valid during finish() callback processing.
3. Acquiring rcu_read_lock() around the finish callback invocation loop in
xfrm_trans_reinject().
Advisories
No advisories yet.
Fixes
Solution
No solution given by the vendor.
Workaround
No workaround given by the vendor.
References
History
Tue, 06 Oct 2026 09:00:00 +0000
| Type | Values Removed | Values Added |
|---|---|---|
| Description | In the Linux kernel, the following vulnerability has been resolved: xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject() syzbot reported a suspicious RCU usage warning in ip6_pkt_drop(): WARNING: suspicious RCU usage in ip6_pkt_drop include/net/addrconf.h:389 suspicious rcu_dereference_check() usage! Call Trace: __in6_dev_get_safely include/net/addrconf.h:389 [inline] ip6_pkt_drop+0x596/0x610 net/ipv6/route.c:4620 ip6_pkt_discard+0x1c/0x30 net/ipv6/route.c:4651 xfrm_trans_reinject+0x324/0x630 net/xfrm/xfrm_input.c:806 process_one_work kernel/workqueue.c:3322 [inline] process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486 When commit 4f4920669d21 ("xfrm: Reinject transport-mode packets through workqueue") converted xfrm_trans_reinject from a tasklet to a workqueue, the reinjection loop ceased running in softirq context. Workqueue workers run in process context where local_bh_disable() does not enter an RCU read-side critical section under CONFIG_PREEMPT_RCU. Because finish callbacks (such as ip6_rcv_finish) 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 rcu_read_lock() triggers RCU lockdep warnings. Furthermore, packets queued to the workqueue via xfrm_trans_queue_net() may carry non-refcounted (noref) dst entries (e.g. from ip_route_input_noref). Additionally, on netdevice unregistration, dst_dev_put() replaces dst->dev with blackhole_netdev, so dst entries do not keep skb->dev alive while queued in the workqueue. Fix these issues by: 1. Calling skb_dst_force(skb) in xfrm_trans_queue_net() while still in the caller's RCU section to ensure dst is reference-counted before queuing. 2. Holding a reference on skb->dev via dev_hold()/dev_put() across workqueue deferral so skb->dev remains valid during finish() callback processing. 3. Acquiring rcu_read_lock() around the finish callback invocation loop in xfrm_trans_reinject(). | |
| Title | xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject() | |
| First Time appeared |
Linux
Linux linux Kernel |
|
| CPEs | cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | |
| Vendors & Products |
Linux
Linux linux Kernel |
|
| References |
|
|
Projects
Sign in to view the affected projects.
Status: PUBLISHED
Assigner: Linux
Published:
Updated: 2026-10-06T08:46:54.188Z
Reserved: 2026-09-25T10:25:14.344Z
Link: CVE-2026-98369
No data.
Status : Received
Published: 2026-10-06T09:18:31.280
Modified: 2026-10-06T09:18:31.280
Link: CVE-2026-98369
No data.
OpenCVE Enrichment
No data.
Weaknesses
No weakness.