mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-27 23:25:13 -04:00
netfilter: nf_tables: call skb_valid_dst() before skb_dst()
When fetching the dst_entry from the skb, check if it valid, ie. this is not a template dst, for extensions that can be used from the netdev ingress and egress chains. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <net/tcp.h>
|
||||
#include <net/route.h>
|
||||
#include <net/dst.h>
|
||||
#include <net/dst_metadata.h>
|
||||
#include <net/netfilter/ipv4/nf_reject.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter_bridge.h>
|
||||
@@ -263,6 +264,7 @@ static int nf_reject_fill_skb_dst(struct sk_buff *skb_in)
|
||||
if (!dst)
|
||||
return -1;
|
||||
|
||||
skb_dst_drop(skb_in);
|
||||
skb_dst_set(skb_in, dst);
|
||||
return 0;
|
||||
}
|
||||
@@ -279,7 +281,7 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
|
||||
if (!oth)
|
||||
return;
|
||||
|
||||
if (!skb_dst(oldskb) && nf_reject_fill_skb_dst(oldskb) < 0)
|
||||
if (!skb_valid_dst(oldskb) && nf_reject_fill_skb_dst(oldskb) < 0)
|
||||
return;
|
||||
|
||||
if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
|
||||
@@ -352,7 +354,7 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
|
||||
if (iph->frag_off & htons(IP_OFFSET))
|
||||
return;
|
||||
|
||||
if (!skb_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0)
|
||||
if (!skb_valid_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0)
|
||||
return;
|
||||
|
||||
if (skb_csum_unnecessary(skb_in) ||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/ip6_fib.h>
|
||||
#include <net/ip6_checksum.h>
|
||||
#include <net/dst_metadata.h>
|
||||
#include <net/netfilter/ipv6/nf_reject.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter_bridge.h>
|
||||
@@ -304,6 +305,7 @@ static int nf_reject6_fill_skb_dst(struct sk_buff *skb_in)
|
||||
if (!dst)
|
||||
return -1;
|
||||
|
||||
skb_dst_drop(skb_in);
|
||||
skb_dst_set(skb_in, dst);
|
||||
return 0;
|
||||
}
|
||||
@@ -336,10 +338,12 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
|
||||
fl6.fl6_sport = otcph->dest;
|
||||
fl6.fl6_dport = otcph->source;
|
||||
|
||||
if (!skb_dst(oldskb)) {
|
||||
if (!skb_valid_dst(oldskb)) {
|
||||
nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
|
||||
if (!dst)
|
||||
return;
|
||||
|
||||
skb_dst_drop(oldskb);
|
||||
skb_dst_set(oldskb, dst);
|
||||
}
|
||||
|
||||
@@ -440,7 +444,7 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
|
||||
if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
|
||||
skb_in->dev = net->loopback_dev;
|
||||
|
||||
if (!skb_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0)
|
||||
if (!skb_valid_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0)
|
||||
return;
|
||||
|
||||
icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user