| From foo@baz Sun 09 Jun 2019 09:24:16 AM CEST |
| From: Xin Long <lucien.xin@gmail.com> |
| Date: Sun, 2 Jun 2019 19:10:24 +0800 |
| Subject: ipv4: not do cache for local delivery if bc_forwarding is enabled |
| |
| From: Xin Long <lucien.xin@gmail.com> |
| |
| [ Upstream commit 0a90478b93a46bdcd56ba33c37566a993e455d54 ] |
| |
| With the topo: |
| |
| h1 ---| rp1 | |
| | route rp3 |--- h3 (192.168.200.1) |
| h2 ---| rp2 | |
| |
| If rp1 bc_forwarding is set while rp2 bc_forwarding is not, after |
| doing "ping 192.168.200.255" on h1, then ping 192.168.200.255 on |
| h2, and the packets can still be forwared. |
| |
| This issue was caused by the input route cache. It should only do |
| the cache for either bc forwarding or local delivery. Otherwise, |
| local delivery can use the route cache for bc forwarding of other |
| interfaces. |
| |
| This patch is to fix it by not doing cache for local delivery if |
| all.bc_forwarding is enabled. |
| |
| Note that we don't fix it by checking route cache local flag after |
| rt_cache_valid() in "local_input:" and "ip_mkroute_input", as the |
| common route code shouldn't be touched for bc_forwarding. |
| |
| Fixes: 5cbf777cfdf6 ("route: add support for directed broadcast forwarding") |
| Reported-by: Jianlin Shi <jishi@redhat.com> |
| Signed-off-by: Xin Long <lucien.xin@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv4/route.c | 22 +++++++++++----------- |
| 1 file changed, 11 insertions(+), 11 deletions(-) |
| |
| --- a/net/ipv4/route.c |
| +++ b/net/ipv4/route.c |
| @@ -1954,7 +1954,7 @@ static int ip_route_input_slow(struct sk |
| u32 itag = 0; |
| struct rtable *rth; |
| struct flowi4 fl4; |
| - bool do_cache; |
| + bool do_cache = true; |
| |
| /* IP on this device is disabled. */ |
| |
| @@ -2031,6 +2031,9 @@ static int ip_route_input_slow(struct sk |
| if (res->type == RTN_BROADCAST) { |
| if (IN_DEV_BFORWARD(in_dev)) |
| goto make_route; |
| + /* not do cache if bc_forwarding is enabled */ |
| + if (IPV4_DEVCONF_ALL(net, BC_FORWARDING)) |
| + do_cache = false; |
| goto brd_input; |
| } |
| |
| @@ -2068,16 +2071,13 @@ brd_input: |
| RT_CACHE_STAT_INC(in_brd); |
| |
| local_input: |
| - do_cache = false; |
| - if (res->fi) { |
| - if (!itag) { |
| - rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); |
| - if (rt_cache_valid(rth)) { |
| - skb_dst_set_noref(skb, &rth->dst); |
| - err = 0; |
| - goto out; |
| - } |
| - do_cache = true; |
| + do_cache &= res->fi && !itag; |
| + if (do_cache) { |
| + rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); |
| + if (rt_cache_valid(rth)) { |
| + skb_dst_set_noref(skb, &rth->dst); |
| + err = 0; |
| + goto out; |
| } |
| } |
| |