[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20190625081758.rgcyo2reabuxxd6e@salvia>
Date: Tue, 25 Jun 2019 10:17:58 +0200
From: Pablo Neira Ayuso <pablo@...filter.org>
To: linmiaohe <linmiaohe@...wei.com>
Cc: "kadlec@...ckhole.kfki.hu" <kadlec@...ckhole.kfki.hu>,
"fw@...len.de" <fw@...len.de>,
"davem@...emloft.net" <davem@...emloft.net>,
"kuznet@....inr.ac.ru" <kuznet@....inr.ac.ru>,
"yoshfuji@...ux-ipv6.org" <yoshfuji@...ux-ipv6.org>,
"netfilter-devel@...r.kernel.org" <netfilter-devel@...r.kernel.org>,
"coreteam@...filter.org" <coreteam@...filter.org>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"dsahern@...il.com" <dsahern@...il.com>,
Mingfangsen <mingfangsen@...wei.com>
Subject: Re: [PATCH v3] net: netfilter: Fix rpfilter dropping vrf packets by
mistake
On Wed, Jun 19, 2019 at 09:49:04AM +0000, linmiaohe wrote:
>
> On 2019/6/18 23:58, Pablo Neira Ayuso wrote:
> > On Thu, Apr 25, 2019 at 09:43:53PM +0800, linmiaohe wrote:
> >> From: Miaohe Lin <linmiaohe@...wei.com>
> >>
> >> When firewalld is enabled with ipv4/ipv6 rpfilter, vrf
> >> ipv4/ipv6 packets will be dropped because in device is vrf but out
> >> device is an enslaved device. So failed with the check of the
> >> rpfilter.
> >>
> >> Signed-off-by: Miaohe Lin <linmiaohe@...wei.com>
> >> ---
> >> --- a/net/ipv4/netfilter/ipt_rpfilter.c
> >> +++ b/net/ipv4/netfilter/ipt_rpfilter.c
> >> @@ -81,6 +81,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),
> >> --- a/net/ipv6/netfilter/ip6t_rpfilter.c
> >> +++ b/net/ipv6/netfilter/ip6t_rpfilter.c
> >> @@ -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)
> >> + } else if (((flags & XT_RPFILTER_LOOSE) == 0) ||
> >> + (netif_is_l3_master(dev)) ||
> >> + (netif_is_l3_slave(dev)))
> >> fl6.flowi6_oif = dev->ifindex;
> >>
> >> rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags); @@
> >> -73,6 +75,12 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
> >> goto out;
> >> }
> >>
> >> + if (netif_is_l3_master(dev)) {
> >> + dev = dev_get_by_index_rcu(dev_net(dev), IP6CB(skb)->iif);
> >> + if (!dev)
> >> + goto out;
> >> + }
> >
> > So, for the l3 device cases this makes:
> >
> > #1 ip6_route_lookup() to fetch the route, using the device in xt_in()
> > (the _LOOSE flag is ignored for the l3 device case).
> >
> > #2 If this is a l3dev master, then you make a global lookup for the
> > device using IP6CB(skb)->iif.
> >
> > #3 You check if route matches with the device, using the new device
> > from the lookup:
> >
> > if (rt->rt6i_idev->dev == dev ...
> >
> > If there is no other way to fix this, OK, that's fair enough.
> >
> > Still this fix looks a bit tricky to me.
> >
> > And this assymmetric between the IPv4 and IPv6 codebase looks rare.
> >
> > Probably someone can explain me this in more detail? I'd appreciate.
> >
> > Thanks!
> >
> Thanks for your reply. I will try to explain this in more detail.
> Vrf device will pass through netfilter hook twice. One with skb->dev=l3mdev
> Slave device and another one with skb->dev=l3mdev master deivce.
> If a device is an l3mdev, l3mdev_master_ifindex_rcu will return l3mdev
> master device ifindex otherwise 0 . So for non l3mdev cases, v4 version is
> as same as the previous one. And for l3mdev cases, flow.flowi4_oif
> will be l3mdev master device ifindex, so we can do a fib lookup in l3mdev
> domain as expected. Since fib_info_nh_uses_dev help us handle the case with
> dev=l3mdev slave or master and XT_RPFILTER_LOOSE do not lookup route
> table, we finish v4.
> For v6 version we need to set fl6.flowi6_oif as we are supposed to lookup
> fib in l3mdev domain even in XT_RPFILTER_LOOSE mode.
> And fib result rt->rt6i_idev->dev is l3mdev slave device, we need change
> dev to enslaved l3mdev device when dev passed in is l3mdev master device.
> The key is l3mdev will pass through netfilter hook twice with skb dev is l3mdev slave
> and master . And we need to set flowi6_oif as fib lookup should in the l3mdev
> domain.
Thanks for explaining.
Something must be wrong in all these helper function logic because
this new code logic is hard to follow for the IPv6 chunk...
Can you explore a more readable fix?
So I'm not inclined to quickly take this patch.
Thanks.
Powered by blists - more mailing lists