From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35B0CC282C2 for ; Mon, 11 Feb 2019 01:47:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0355920811 for ; Mon, 11 Feb 2019 01:47:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KHl6fMym" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726882AbfBKBru (ORCPT ); Sun, 10 Feb 2019 20:47:50 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:41439 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726821AbfBKBrt (ORCPT ); Sun, 10 Feb 2019 20:47:49 -0500 Received: by mail-pf1-f193.google.com with SMTP id b7so4495499pfi.8 for ; Sun, 10 Feb 2019 17:47:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ygPNxsM4+9WhDnH8y5w4mQb9O9P5J1Ke+syOlWmQl+A=; b=KHl6fMymMMsZM37cuzEqs0cWIYtexckUeaXgvv/d2ol4Hub5BI1mzVvVx4NAs5Jx0y MRgTGFV5NX2QRiFn18x/3/jBGt1BI6YwD72ULbm/KJxVvjj7OxE2MvTKyVZCwmy3cmps XlnFj5gZIAokjzPPp0ZKoODmpI+yoqSIEOxhU4drO/E6yCQnz9dVNen14QB/+x9RjEau TK7pgbJ/Anyd3iUWdqXB3F5rwKfJXhg3NzmgZ//9RcpKLb/vTX5yWwAjgIak9ADod53B Ba10gbMN3zd8n9r6ztj0TnN4+EwafDKxCRoaHY0RTZ/hcgmv46/g9pNFBicLRBBm6JXB Gu7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ygPNxsM4+9WhDnH8y5w4mQb9O9P5J1Ke+syOlWmQl+A=; b=TmPiPVBFUdKs6og782nSoRsPAdD6RZ874qZg782+jgOfqWmHnC3OC9dk8x/KHxeRsx wAIer1RuXjGLE0qnbc9Kez/ETyOP9Iz1gqbhCIXpVBBTi5NxBPELtMhYFBzwBhfry6kp NrpkWMXuXYys+N1ElSgRCOMXW8IjCmnKwuNYmGL39N3vjrcqOq6AtuV9ncFAHvyNiXxh tkWNxK2zPZprrHpV7U9ADcqnGemuTatJjID5/xMpSntg3KCz+W5HPSAl5cqOGkSfGm8L /rvofk4cOiuFzNLwz5za2glYS7tmTxaSkE263TNQ0XTqCjPXhrdJJuXL5cM8GK0i6NdU dgaQ== X-Gm-Message-State: AHQUAuatOx0uOI7gfpBAhUScn127JuRDIzhNqi3IpoZg5cAt5YgHhONY s+fgRDRuJ+SqFP3+ac7aTtxRrhCB X-Google-Smtp-Source: AHgI3Iby9IJVE+wsoYW2CwuLenWARyPufn3Pr/q6dnBdtI6DXi5CiircvV+3m9BK0FhbmSKYdezACQ== X-Received: by 2002:a62:3603:: with SMTP id d3mr35334086pfa.146.1549849668257; Sun, 10 Feb 2019 17:47:48 -0800 (PST) Received: from tw-172-25-17-123.office.twttr.net ([8.25.197.25]) by smtp.gmail.com with ESMTPSA id p67sm11406703pfg.44.2019.02.10.17.47.47 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 10 Feb 2019 17:47:47 -0800 (PST) From: Cong Wang To: netdev@vger.kernel.org Cc: Cong Wang , Jamal Hadi Salim , Jiri Pirko Subject: [Patch net 2/3] net_sched: fix a memory leak in cls_tcindex Date: Sun, 10 Feb 2019 17:47:30 -0800 Message-Id: <20190211014731.23932-3-xiyou.wangcong@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190211014731.23932-1-xiyou.wangcong@gmail.com> References: <20190211014731.23932-1-xiyou.wangcong@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When tcindex_destroy() destroys all the filter results in the perfect hash table, it invokes the walker to delete each of them. However, results with class==0 are skipped in either tcindex_walk() or tcindex_delete(), which causes a memory leak reported by kmemleak. This patch fixes it by skipping the walker and directly deleting these filter results so we don't miss any filter result. As a result of this change, we have to initialize exts->net properly in tcindex_alloc_perfect_hash(). In net-next, we need to evaluate whether we should initialize ->net in tcf_exts_init() instead. Cc: Jamal Hadi Salim Cc: Jiri Pirko Signed-off-by: Cong Wang --- net/sched/cls_tcindex.c | 44 ++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 14e6d80dd58e..6c3436e8436c 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -222,14 +222,6 @@ static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last, return 0; } -static int tcindex_destroy_element(struct tcf_proto *tp, - void *arg, struct tcf_walker *walker) -{ - bool last; - - return tcindex_delete(tp, arg, &last, NULL); -} - static void __tcindex_destroy(struct tcindex_data *p) { kfree(p->perfect); @@ -292,7 +284,7 @@ static void tcindex_free_perfect_hash(struct tcindex_data *cp) kfree(cp->perfect); } -static int tcindex_alloc_perfect_hash(struct tcindex_data *cp) +static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp) { int i, err = 0; @@ -306,6 +298,7 @@ static int tcindex_alloc_perfect_hash(struct tcindex_data *cp) TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); if (err < 0) goto errout; + cp->perfect[i].exts.net = net; } return 0; @@ -355,7 +348,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, if (p->perfect) { int i; - if (tcindex_alloc_perfect_hash(cp) < 0) + if (tcindex_alloc_perfect_hash(net, cp) < 0) goto errout; for (i = 0; i < cp->hash; i++) cp->perfect[i].res = p->perfect[i].res; @@ -424,7 +417,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, err = -ENOMEM; if (!cp->perfect && !cp->h) { if (valid_perfect_hash(cp)) { - if (tcindex_alloc_perfect_hash(cp) < 0) + if (tcindex_alloc_perfect_hash(net, cp) < 0) goto errout_alloc; balloc = 1; } else { @@ -585,13 +578,32 @@ static void tcindex_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) { struct tcindex_data *p = rtnl_dereference(tp->root); - struct tcf_walker walker; + int i; pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p); - walker.count = 0; - walker.skip = 0; - walker.fn = tcindex_destroy_element; - tcindex_walk(tp, &walker); + + if (p->perfect) { + for (i = 0; i < p->hash; i++) { + struct tcindex_filter_result *r = p->perfect + i; + + tcf_unbind_filter(tp, &r->res); + if (tcf_exts_get_net(&r->exts)) + tcf_queue_work(&r->rwork, + tcindex_destroy_rexts_work); + else + __tcindex_destroy_rexts(r); + } + } + + for (i = 0; p->h && i < p->hash; i++) { + struct tcindex_filter *f, *next; + bool last; + + for (f = rtnl_dereference(p->h[i]); f; f = next) { + next = rtnl_dereference(f->next); + tcindex_delete(tp, &f->result, &last, NULL); + } + } if (maybe_get_net(p->net)) tcf_queue_work(&p->rwork, tcindex_destroy_work); -- 2.20.1