]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
netfilter: Fix rpfilter dropping vrf packets by mistake
authorMiaohe Lin <linmiaohe@huawei.com>
Tue, 2 Jul 2019 03:59:36 +0000 (03:59 +0000)
committerKhalid Elmously <khalid.elmously@canonical.com>
Wed, 4 Sep 2019 06:16:38 +0000 (02:16 -0400)
BugLink: https://bugs.launchpad.net/bugs/1840520
[ Upstream commit b575b24b8eee37f10484e951b62ce2a31c579775 ]

When firewalld is enabled with ipv4/ipv6 rpfilter, vrf
ipv4/ipv6 packets will be dropped. Vrf device will pass
through netfilter hook twice. One with enslaved device
and another one with l3 master device. So in device may
dismatch witch out device because out device is always
enslaved device.So failed with the check of the rpfilter
and drop the packets by mistake.

Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv6/netfilter/ip6t_rpfilter.c

index 37fb9552e85898d0ee9b311f22af31563c621de7..341d1bd637af2bd93113a169ddff71243496851b 100644 (file)
@@ -96,6 +96,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
        flow.flowi4_tos = RT_TOS(iph->tos);
        flow.flowi4_scope = RT_SCOPE_UNIVERSE;
+       flow.flowi4_oif = l3mdev_master_ifindex_rcu(xt_in(par));
 
        return rpfilter_lookup_reverse(xt_net(par), &flow, xt_in(par), info->flags) ^ invert;
 }
index 40eb16bd97860b6a52ea5019b17e2e7c0f8bce03..d535768bea0fda3aab413902b0267aa3c37b0391 100644 (file)
@@ -58,7 +58,9 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
        if (rpfilter_addr_linklocal(&iph->saddr)) {
                lookup_flags |= RT6_LOOKUP_F_IFACE;
                fl6.flowi6_oif = dev->ifindex;
-       } else if ((flags & XT_RPFILTER_LOOSE) == 0)
+       /* Set flowi6_oif for vrf devices to lookup route in l3mdev domain. */
+       } else if (netif_is_l3_master(dev) || netif_is_l3_slave(dev) ||
+                 (flags & XT_RPFILTER_LOOSE) == 0)
                fl6.flowi6_oif = dev->ifindex;
 
        rt = (void *) ip6_route_lookup(net, &fl6, lookup_flags);
@@ -73,7 +75,9 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
                goto out;
        }
 
-       if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
+       if (rt->rt6i_idev->dev == dev ||
+           l3mdev_master_ifindex_rcu(rt->rt6i_idev->dev) == dev->ifindex ||
+           (flags & XT_RPFILTER_LOOSE))
                ret = true;
  out:
        ip6_rt_put(rt);