net: tcp: fix rtable leak in tcp_is_local[6]
ip_rt_put/ip6_rt_put call is missed after route lookup routine.
So if lookup returns ok, rtable leak will happen.
Change-Id: Ica137043879b4305b70401cf7e8efda24405e3ff
Signed-off-by: Liping Zhang <liping.zhang@spreadtrum.com>
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index d0ee839..dcc8f4d 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3420,16 +3420,26 @@
static int tcp_is_local(struct net *net, __be32 addr) {
struct rtable *rt;
struct flowi4 fl4 = { .daddr = addr };
+ int is_local;
rt = ip_route_output_key(net, &fl4);
if (IS_ERR_OR_NULL(rt))
return 0;
- return rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK);
+
+ is_local = rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK);
+ ip_rt_put(rt);
+ return is_local;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static int tcp_is_local6(struct net *net, struct in6_addr *addr) {
struct rt6_info *rt6 = rt6_lookup(net, addr, addr, 0, 0);
- return rt6 && rt6->dst.dev && (rt6->dst.dev->flags & IFF_LOOPBACK);
+ int is_local;
+ if (rt6 == NULL)
+ return 0;
+
+ is_local = rt6->dst.dev && (rt6->dst.dev->flags & IFF_LOOPBACK);
+ dst_release(&rt6->dst);
+ return is_local;
}
#endif