Re: [PATCH nf-next] netfilter: nf_tables: call skb_valid_dst() before skb_dst()
Fernando Fernandez Mancera <[email protected]> Wed, 29 Jul 2026 11:33:24 +0200
| Newsgroups | gmane.comp.security.firewalls.netfilter.devel |
|---|---|
| Message-ID | <[email protected]> |
On 7/28/26 10:40 AM, Pablo Neira Ayuso wrote: > When fetching the dst_entry from the skb, check if it valid, ie. this is > not a template dst. > > Signed-off-by: Pablo Neira Ayuso <[email protected]> Hi Pablo, I used a coccinelle script to see if this pattern is present in other places. So far in Netfilter I have found this in net/ipv6/netfilter/nf_reject_ipv6.c:nf_send_reset6() if (!skb_dst(oldskb)) { nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false); if (!dst) return; skb_dst_set(oldskb, dst); } If I am not wrong the same problem happens here too. > --- > net/netfilter/nft_meta.c | 6 ++++-- > net/netfilter/nft_rt.c | 6 ++++-- > net/netfilter/nft_xfrm.c | 9 ++++++++- > 3 files changed, 16 insertions(+), 5 deletions(-) > > diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c > index 0a43e0787a68..01cfbaa36525 100644 > --- a/net/netfilter/nft_meta.c > +++ b/net/netfilter/nft_meta.c > @@ -20,6 +20,7 @@ > #include <net/dst.h> > #include <net/ip.h> > #include <net/sock.h> > +#include <net/dst_metadata.h> > #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ > #include <net/netfilter/nf_tables.h> > #include <net/netfilter/nf_tables_core.h> > @@ -279,11 +280,12 @@ static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest, > static noinline bool > nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest) > { > - const struct dst_entry *dst = skb_dst(skb); > + const struct dst_entry *dst; > > - if (!dst) > + if (!skb_valid_dst(skb)) > return false; > > + dst = skb_dst(skb); > *dest = dst->tclassid; > return true; > } > diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c > index aeb0094eafd8..841c863a08db 100644 > --- a/net/netfilter/nft_rt.c > +++ b/net/netfilter/nft_rt.c > @@ -8,6 +8,7 @@ > #include <linux/netfilter.h> > #include <linux/netfilter/nf_tables.h> > #include <net/dst.h> > +#include <net/dst_metadata.h> > #include <net/ip6_route.h> > #include <net/route.h> > #include <net/netfilter/nf_tables.h> > @@ -59,10 +60,11 @@ void nft_rt_get_eval(const struct nft_expr *expr, > u32 *dest = ®s->data[priv->dreg]; > const struct dst_entry *dst; > > - dst = skb_dst(skb); > - if (!dst) > + if (!skb_valid_dst(skb)) > goto err; > > + dst = skb_dst(skb); > + > switch (priv->key) { > #ifdef CONFIG_IP_ROUTE_CLASSID > case NFT_RT_CLASSID: > diff --git a/net/netfilter/nft_xfrm.c b/net/netfilter/nft_xfrm.c > index 8cec43064319..c8bba697f993 100644 > --- a/net/netfilter/nft_xfrm.c > +++ b/net/netfilter/nft_xfrm.c > @@ -12,6 +12,7 @@ > #include <linux/netfilter/nf_tables.h> > #include <net/netfilter/nf_tables_core.h> > #include <net/netfilter/nf_tables.h> > +#include <net/dst_metadata.h> > #include <linux/in.h> > #include <net/xfrm.h> > > @@ -177,9 +178,15 @@ static void nft_xfrm_get_eval_out(const struct nft_xfrm *priv, > struct nft_regs *regs, > const struct nft_pktinfo *pkt) > { > - const struct dst_entry *dst = skb_dst(pkt->skb); > + const struct dst_entry *dst; > int i; > > + if (!skb_valid_dst(pkt->skb)) { > + regs->verdict.code = NFT_BREAK; > + return; > + } > + > + dst = skb_dst(pkt->skb); > for (i = 0; dst && dst->xfrm; > dst = ((const struct xfrm_dst *)dst)->child, i++) { > if (i < priv->spnum)