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 = &regs->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)