Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: Fix rpfilter dropping vrf packets by mistake

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>

authored by

Miaohe Lin and committed by
Pablo Neira Ayuso
b575b24b 1b0890cd

+7 -2
+1
net/ipv4/netfilter/ipt_rpfilter.c
··· 78 78 flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; 79 79 flow.flowi4_tos = RT_TOS(iph->tos); 80 80 flow.flowi4_scope = RT_SCOPE_UNIVERSE; 81 + flow.flowi4_oif = l3mdev_master_ifindex_rcu(xt_in(par)); 81 82 82 83 return rpfilter_lookup_reverse(xt_net(par), &flow, xt_in(par), info->flags) ^ invert; 83 84 }
+6 -2
net/ipv6/netfilter/ip6t_rpfilter.c
··· 55 55 if (rpfilter_addr_linklocal(&iph->saddr)) { 56 56 lookup_flags |= RT6_LOOKUP_F_IFACE; 57 57 fl6.flowi6_oif = dev->ifindex; 58 - } else if ((flags & XT_RPFILTER_LOOSE) == 0) 58 + /* Set flowi6_oif for vrf devices to lookup route in l3mdev domain. */ 59 + } else if (netif_is_l3_master(dev) || netif_is_l3_slave(dev) || 60 + (flags & XT_RPFILTER_LOOSE) == 0) 59 61 fl6.flowi6_oif = dev->ifindex; 60 62 61 63 rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags); ··· 72 70 goto out; 73 71 } 74 72 75 - if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE)) 73 + if (rt->rt6i_idev->dev == dev || 74 + l3mdev_master_ifindex_rcu(rt->rt6i_idev->dev) == dev->ifindex || 75 + (flags & XT_RPFILTER_LOOSE)) 76 76 ret = true; 77 77 out: 78 78 ip6_rt_put(rt);