Add an ether_type field to struct net_device_path_ctx to reject IPv4 over IPv6 and vice-versa, this is currently not support. Otherwise, incorrect dst_entry family can be reached from datapath. Signed-off-by: Pablo Neira Ayuso --- include/linux/netdevice.h | 1 + net/ipv4/ipip.c | 3 +++ net/ipv6/ip6_tunnel.c | 3 +++ net/netfilter/nf_flow_table_path.c | 6 ++++-- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4319b949f405..d9962c50bd60 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -939,6 +939,7 @@ struct net_device_path_stack { struct net_device_path_ctx { const struct net_device *dev; u8 daddr[ETH_ALEN]; + __be16 ether_type; int num_vlans; struct { diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index fb7d96f99b06..62a374079bfc 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -360,6 +360,9 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx, const struct iphdr *tiph = &tunnel->parms.iph; struct rtable *rt; + if (ctx->ether_type != cpu_to_be16(ETH_P_IP)) + return -EOPNOTSUPP; + if (tunnel->collect_md) return -EOPNOTSUPP; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index d80020bc2620..3bfaa98e7f33 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1849,6 +1849,9 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx, struct flowi6 fl6; int err; + if (ctx->ether_type != cpu_to_be16(ETH_P_IPV6)) + return -EOPNOTSUPP; + if (t->parms.flags & (IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FLOWLABEL | IP6_TNL_F_USE_ORIG_FWMARK)) diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c index 0cbde535b8ba..5f166da3b09b 100644 --- a/net/netfilter/nf_flow_table_path.c +++ b/net/netfilter/nf_flow_table_path.c @@ -44,13 +44,15 @@ static bool nft_is_valid_ether_device(const struct net_device *dev) static int nft_dev_fill_forward_path(const struct dst_entry *dst_cache, const struct nf_conn *ct, - enum ip_conntrack_dir dir, u8 *ha, + enum ip_conntrack_dir dir, + u8 *ha, __be16 ether_type, struct net_device_path_stack *stack) { const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; struct net_device *dev = dst_cache->dev; struct net_device_path_ctx ctx = { .dev = dev, + .ether_type = ether_type, }; struct neighbour *n; u8 nud_state; @@ -228,7 +230,7 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt, unsigned char ha[ETH_ALEN]; int i; - if (nft_dev_fill_forward_path(dst, ct, dir, ha, &stack) < 0 || + if (nft_dev_fill_forward_path(dst, ct, dir, ha, pkt->ethertype, &stack) < 0 || nft_dev_path_info(&stack, &info, ha, ft) < 0) return -ENOENT; -- 2.47.3