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 C9F3BC169C4 for ; Mon, 11 Feb 2019 21:06:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 948B42081B for ; Mon, 11 Feb 2019 21:06:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RzP2NrkG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727121AbfBKVGb (ORCPT ); Mon, 11 Feb 2019 16:06:31 -0500 Received: from mail-pf1-f196.google.com ([209.85.210.196]:45370 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726930AbfBKVG2 (ORCPT ); Mon, 11 Feb 2019 16:06:28 -0500 Received: by mail-pf1-f196.google.com with SMTP id j3so129596pfi.12 for ; Mon, 11 Feb 2019 13:06:28 -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=IW3vsBJSPZt+BgU6y1xUvqlmi43MgcSzhEW5gIrIYnw=; b=RzP2NrkGx6JgyYQf50ye4LEcm0l6crf8iTQZ2O37k3YhrKG4VBfHXqWjYC+OSxxGll UxhHI41ZzvC3L4spudzFEbHEKXm3yTa8uwVaP2OKUQXdue46750/Hmwv4xYHhK4N46fI XubvprynleNgf+2EHbfDtUIsHuIOmb9iYi7yYu5G9sV6T0uqpnxAwi0OLKa3IRTRuuHf 8+vYrBjFqf/FIpgj7VrX/O9NDoCLAPkYf2Dvb3rgI/+7BLOONmoUq882uBZCkBde9zN3 mPzSb4VsTHUT6VQWsdC05cdORmOz1nyAYZEDYWEv04iGRKuKxHjk+13k/Tr1RLa4ENd7 WwDw== 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=IW3vsBJSPZt+BgU6y1xUvqlmi43MgcSzhEW5gIrIYnw=; b=eHdL4q37hxzYV9c9tZcVFS85kTV69j9hWyMQjf1cLM24cXZ1/HHGFFSRG3rSDE3mFM MTky0+7ijdo+TN0mnHzxRYbKTWX3qbLqfvZKurXpsQYizH61GFjhzoyZ+9LCZLJZaFi/ TTTLbaq5+TvCbaYJEUTMIUTV7c9g37i6sBOFXOZMsf+liXWWuaBmrVnGm3RRR74pevuY CUszOnuRhonPHg/tiwiwOl1IUXNJgYoQ0L+nhOYiK0wRxPBhplXgNeb0cRWeD5EHOGiX MeWjNPLbcNzFnUppjPDNnVYH9a+IO2cMl2GyT86sVjsuvLfa2SrYVjkiXiTRXp6WJ3uO 7Z4Q== X-Gm-Message-State: AHQUAubcTqBaTC3MO3CQ1HQR5IkAruwH4fzXaEw4U7gjDkiod6zwuW7F JLUhY+Kwg9CeX+i17rlHCIlZvQ6B X-Google-Smtp-Source: AHgI3IZMehayAHml9Ps7PGQUDJB+HLzXDMjsLS7L9K1iA13/PGH2bVuRdZAsXZ5mf99O0yxcNjbSUQ== X-Received: by 2002:a62:68c5:: with SMTP id d188mr241694pfc.194.1549919187701; Mon, 11 Feb 2019 13:06:27 -0800 (PST) Received: from tw-172-25-17-123.office.twttr.net ([8.25.197.25]) by smtp.gmail.com with ESMTPSA id q127sm14873872pgq.39.2019.02.11.13.06.26 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 11 Feb 2019 13:06:26 -0800 (PST) From: Cong Wang To: netdev@vger.kernel.org Cc: Cong Wang , Jamal Hadi Salim , Jiri Pirko Subject: [Patch net v2 2/3] net_sched: fix a memory leak in cls_tcindex Date: Mon, 11 Feb 2019 13:06:15 -0800 Message-Id: <20190211210616.9592-3-xiyou.wangcong@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190211210616.9592-1-xiyou.wangcong@gmail.com> References: <20190211210616.9592-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(). For net-next, we need to consider whether we should initialize ->net in tcf_exts_init() instead, before that just directly test CONFIG_NET_CLS_ACT=y. Cc: Jamal Hadi Salim Cc: Jiri Pirko Signed-off-by: Cong Wang --- net/sched/cls_tcindex.c | 46 +++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 79b52a637dda..70ea5b1a7889 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -221,14 +221,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_work(struct work_struct *work) { struct tcindex_data *p = container_of(to_rcu_work(work), @@ -279,7 +271,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; @@ -293,6 +285,9 @@ static int tcindex_alloc_perfect_hash(struct tcindex_data *cp) TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); if (err < 0) goto errout; +#ifdef CONFIG_NET_CLS_ACT + cp->perfect[i].exts.net = net; +#endif } return 0; @@ -341,7 +336,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; @@ -410,7 +405,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 { @@ -566,13 +561,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); + } + } tcf_queue_work(&p->rwork, tcindex_destroy_work); } -- 2.20.1