From 5d926be341089c94af7def1ae66ba7215a36158c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 4 Aug 2026 09:33:28 +0000 Subject: [PATCH] netfilter: nf_flow_table: drop existing skb dst before skb_dst_set_noref() ANBZ: #44387 commit 8aecf0bbcc72605592134c917c222207d8f63ab0 upstream. Incoming skbs passing through netfilter flowtable offload hooks (or XFRM offload path) might already carry a ref-counted dst_entry assigned during earlier RX or routing steps. Calling skb_dst_set_noref() when skb already holds a ref-counted dst overwrites skb->_skb_refdst, leaking the previous dst_entry reference count and triggering a DEBUG_NET_WARN_ON_ONCE assertion in skb_dst_check_unset(): WARNING: at skb_dst_check_unset include/linux/skbuff.h:1170 WARNING: at skb_dst_set_noref include/linux/skbuff.h:1234 WARNING: at nf_flow_offload_ip_hook+0xf6c/0x2b60 net/netfilter/nf_flow_table_ip.c:864 Drop any existing dst_entry reference with skb_dst_drop(skb) before setting the non-referenced flowtable destination. [backport-note] PatchPilot-Conflict-Type: context_drift PatchPilot-Conflict-Files: net/netfilter/nf_flow_table_ip.c PatchPilot-Resolution: net/netfilter/nf_flow_table_ip.c: Insert skb_dst_drop() before skb_dst_set_noref() in NEIGH cases using... Fixes: 2a79fd3908ac ("netfilter: nf_flow_table: attach dst to skbs") Reported-by: syzbot+76d4e3a055aec3b007ec@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/6a71b141.9511d2ce.1fc5b9.033b.GAE@google.com/T/#u Signed-off-by: Eric Dumazet Reviewed-by: Pablo Neira Ayuso Link: https://patch.msgid.link/20260804093328.1831847-1-edumazet@google.com Signed-off-by: Jakub Kicinski Fixes: CVE-2026-74695 Assisted-by: PatchPilot Signed-off-by: D. Wythe --- net/netfilter/nf_flow_table_ip.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c index 20dd4eeac78b..6e6d036fe139 100644 --- a/net/netfilter/nf_flow_table_ip.c +++ b/net/netfilter/nf_flow_table_ip.c @@ -268,6 +268,7 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb, struct dst_entry *dst) { skb_orphan(skb); + skb_dst_drop(skb); skb_dst_set_noref(skb, dst); dst_output(state->net, state->sk, skb); return NF_STOLEN; @@ -453,6 +454,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, outdev = rt->dst.dev; skb->dev = outdev; nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); + skb_dst_drop(skb); skb_dst_set_noref(skb, &rt->dst); neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ret = NF_STOLEN; @@ -748,6 +750,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, outdev = rt->dst.dev; skb->dev = outdev; nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); + skb_dst_drop(skb); skb_dst_set_noref(skb, &rt->dst); neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ret = NF_STOLEN; -- Gitee