From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Wang Subject: [PATCH net 2/2] ipv6: fix memory leak on dst->_metrics Date: Tue, 18 Sep 2018 13:45:00 -0700 Message-ID: <20180918204500.106240-3-tracywwnj@gmail.com> References: <20180918204500.106240-1-tracywwnj@gmail.com> <20180918204500.106240-2-tracywwnj@gmail.com> Mime-Version: 1.0 Content-Transfer-Encoding: 8bit Cc: Eric Dumazet , David Ahern , Cong Wang , Sabrina Dubroca , Wei Wang To: David Miller , netdev@vger.kernel.org Return-path: Received: from mail-pl1-f195.google.com ([209.85.214.195]:42265 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729824AbeISCUB (ORCPT ); Tue, 18 Sep 2018 22:20:01 -0400 Received: by mail-pl1-f195.google.com with SMTP id g23-v6so1543394plq.9 for ; Tue, 18 Sep 2018 13:45:42 -0700 (PDT) In-Reply-To: <20180918204500.106240-2-tracywwnj@gmail.com> Sender: netdev-owner@vger.kernel.org List-ID: From: Wei Wang When dst->_metrics and f6i->fib6_metrics share the same memory, both take reference count on the dst_metrics structure. However, when dst is destroyed, ip6_dst_destroy() only invokes dst_destroy_metrics_generic() which does not take care of READONLY metrics and does not release refcnt. This causes memory leak. Similar to ipv4 logic, the fix is to properly release refcnt and free the memory space pointed by dst->_metrics if refcnt becomes 0. Fixes: 93531c674315 ("net/ipv6: separate handling of FIB entries from dst based routes") Reported-by: Sabrina Dubroca Signed-off-by: Wei Wang Signed-off-by: Eric Dumazet --- net/ipv6/route.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b5d3e6b294ab..826b14de7dbb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -364,11 +364,14 @@ EXPORT_SYMBOL(ip6_dst_alloc); static void ip6_dst_destroy(struct dst_entry *dst) { + struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); struct rt6_info *rt = (struct rt6_info *)dst; struct fib6_info *from; struct inet6_dev *idev; - dst_destroy_metrics_generic(dst); + if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) + kfree(p); + rt6_uncached_list_del(rt); idev = rt->rt6i_idev; -- 2.19.0.397.gdd90340f6a-goog