diff options
author | Xin Long <lucien.xin@gmail.com> | 2018-11-13 19:48:28 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-11-23 10:17:02 +0300 |
commit | b536dd802a36dd14e8d5e68201cecab46ccb9669 (patch) | |
tree | a97e3bfeb73e32315f2e44b7e90987611d4446f8 /net/ipv6/route.c | |
parent | 60258098e8e04fe5911090244e06558f4a4d24a7 (diff) | |
download | linux-b536dd802a36dd14e8d5e68201cecab46ccb9669.tar.xz |
ipv6: fix a dst leak when removing its exception
[ Upstream commit 761f60261b4401aa368d71d431b4c218af0efcee ]
These is no need to hold dst before calling rt6_remove_exception_rt().
The call to dst_hold_safe() in ip6_link_failure() was for ip6_del_rt(),
which has been removed in Commit 93531c674315 ("net/ipv6: separate
handling of FIB entries from dst based routes"). Otherwise, it will
cause a dst leak.
This patch is to simply remove the dst_hold_safe() call before calling
rt6_remove_exception_rt() and also do the same in ip6_del_cached_rt().
It's safe, because the removal of the exception that holds its dst's
refcnt is protected by rt6_exception_lock.
Fixes: 93531c674315 ("net/ipv6: separate handling of FIB entries from dst based routes")
Fixes: 23fb93a4d3f1 ("net/ipv6: Cleanup exception and cache route handling")
Reported-by: Li Shuang <shuali@redhat.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 1cf00d857fc1..ed72ae3c54e7 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2263,8 +2263,7 @@ static void ip6_link_failure(struct sk_buff *skb) if (rt) { rcu_read_lock(); if (rt->rt6i_flags & RTF_CACHE) { - if (dst_hold_safe(&rt->dst)) - rt6_remove_exception_rt(rt); + rt6_remove_exception_rt(rt); } else { struct fib6_info *from; struct fib6_node *fn; @@ -3266,8 +3265,8 @@ static int ip6_del_cached_rt(struct rt6_info *rt, struct fib6_config *cfg) if (cfg->fc_flags & RTF_GATEWAY && !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) goto out; - if (dst_hold_safe(&rt->dst)) - rc = rt6_remove_exception_rt(rt); + + rc = rt6_remove_exception_rt(rt); out: return rc; } |