]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netfilter: nf_flow_table: drop existing skb dst before skb_dst_set_noref()
authorEric Dumazet <edumazet@google.com>
Tue, 4 Aug 2026 09:33:28 +0000 (09:33 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 6 Aug 2026 00:11:18 +0000 (17:11 -0700)
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.

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 <edumazet@google.com>
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
Link: https://patch.msgid.link/20260804093328.1831847-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/netfilter/nf_flow_table_ip.c

index 0b78decce8a9bdc3ed404f9913384335408b00d3..c9e332fafcb5c22559f68858b36f3207822c4423 100644 (file)
@@ -310,6 +310,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;
@@ -861,6 +862,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
                        return NF_DROP;
                }
                xmit.dest = neigh->ha;
+               skb_dst_drop(skb);
                skb_dst_set_noref(skb, &rt->dst);
                break;
        case FLOW_OFFLOAD_XMIT_DIRECT:
@@ -1178,6 +1180,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
                        return NF_DROP;
                }
                xmit.dest = neigh->ha;
+               skb_dst_drop(skb);
                skb_dst_set_noref(skb, &rt->dst);
                break;
        case FLOW_OFFLOAD_XMIT_DIRECT: