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

netfilter: ip6t_rpfilter: Fix regression with VRF interfaces

When calling ip6_route_lookup() for the packet arriving on the VRF
interface, the result is always the real (slave) interface. Expect this
when validating the result.

Fixes: acc641ab95b66 ("netfilter: rpfilter/fib: Populate flowic_l3mdev field")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Phil Sutter and committed by
Pablo Neira Ayuso
efb056e5 e6d57e9f

+29 -7
+3 -1
net/ipv6/netfilter/ip6t_rpfilter.c
··· 72 72 goto out; 73 73 } 74 74 75 - if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE)) 75 + if (rt->rt6i_idev->dev == dev || 76 + l3mdev_master_ifindex_rcu(rt->rt6i_idev->dev) == dev->ifindex || 77 + (flags & XT_RPFILTER_LOOSE)) 76 78 ret = true; 77 79 out: 78 80 ip6_rt_put(rt);
+26 -6
tools/testing/selftests/netfilter/rpath.sh
··· 62 62 ip -net "$ns2" a a fec0:42::1/64 dev d0 nodad 63 63 64 64 # firewall matches to test 65 - [ -n "$iptables" ] && ip netns exec "$ns2" \ 66 - "$iptables" -t raw -A PREROUTING -s 192.168.0.0/16 -m rpfilter 67 - [ -n "$ip6tables" ] && ip netns exec "$ns2" \ 68 - "$ip6tables" -t raw -A PREROUTING -s fec0::/16 -m rpfilter 65 + [ -n "$iptables" ] && { 66 + common='-t raw -A PREROUTING -s 192.168.0.0/16' 67 + ip netns exec "$ns2" "$iptables" $common -m rpfilter 68 + ip netns exec "$ns2" "$iptables" $common -m rpfilter --invert 69 + } 70 + [ -n "$ip6tables" ] && { 71 + common='-t raw -A PREROUTING -s fec0::/16' 72 + ip netns exec "$ns2" "$ip6tables" $common -m rpfilter 73 + ip netns exec "$ns2" "$ip6tables" $common -m rpfilter --invert 74 + } 69 75 [ -n "$nft" ] && ip netns exec "$ns2" $nft -f - <<EOF 70 76 table inet t { 71 77 chain c { ··· 95 89 [ -n "$1" ] || return 0 96 90 ip netns exec "$ns2" "$1" -t raw -vS | grep -q -- "-m rpfilter -c 0 0" 97 91 } 92 + ipt_zero_reverse_rule() { # (command) 93 + [ -n "$1" ] || return 0 94 + ip netns exec "$ns2" "$1" -t raw -vS | \ 95 + grep -q -- "-m rpfilter --invert -c 0 0" 96 + } 98 97 nft_zero_rule() { # (family) 99 98 [ -n "$nft" ] || return 0 100 99 ip netns exec "$ns2" "$nft" list chain inet t c | \ ··· 112 101 ip netns exec "$netns" ping -q -c 1 -W 1 "$@" >/dev/null 113 102 } 114 103 115 - testrun() { 116 - # clear counters first 104 + clear_counters() { 117 105 [ -n "$iptables" ] && ip netns exec "$ns2" "$iptables" -t raw -Z 118 106 [ -n "$ip6tables" ] && ip netns exec "$ns2" "$ip6tables" -t raw -Z 119 107 if [ -n "$nft" ]; then ··· 121 111 ip netns exec "$ns2" $nft -s list table inet t; 122 112 ) | ip netns exec "$ns2" $nft -f - 123 113 fi 114 + } 115 + 116 + testrun() { 117 + clear_counters 124 118 125 119 # test 1: martian traffic should fail rpfilter matches 126 120 netns_ping "$ns1" -I v0 192.168.42.1 && \ ··· 134 120 135 121 ipt_zero_rule "$iptables" || die "iptables matched martian" 136 122 ipt_zero_rule "$ip6tables" || die "ip6tables matched martian" 123 + ipt_zero_reverse_rule "$iptables" && die "iptables not matched martian" 124 + ipt_zero_reverse_rule "$ip6tables" && die "ip6tables not matched martian" 137 125 nft_zero_rule ip || die "nft IPv4 matched martian" 138 126 nft_zero_rule ip6 || die "nft IPv6 matched martian" 127 + 128 + clear_counters 139 129 140 130 # test 2: rpfilter match should pass for regular traffic 141 131 netns_ping "$ns1" 192.168.23.1 || \ ··· 149 131 150 132 ipt_zero_rule "$iptables" && die "iptables match not effective" 151 133 ipt_zero_rule "$ip6tables" && die "ip6tables match not effective" 134 + ipt_zero_reverse_rule "$iptables" || die "iptables match over-effective" 135 + ipt_zero_reverse_rule "$ip6tables" || die "ip6tables match over-effective" 152 136 nft_zero_rule ip && die "nft IPv4 match not effective" 153 137 nft_zero_rule ip6 && die "nft IPv6 match not effective" 154 138