From mboxrd@z Thu Jan 1 00:00:00 1970 From: Cong Wang Subject: [Patch net 12/13] cls_tcindex: use tcf_exts_get_net() before call_rcu() Date: Mon, 6 Nov 2017 13:47:29 -0800 Message-ID: <20171106214730.24421-13-xiyou.wangcong@gmail.com> References: <20171106214730.24421-1-xiyou.wangcong@gmail.com> Cc: Cong Wang , Lucas Bates , Jamal Hadi Salim , Jiri Pirko To: netdev@vger.kernel.org Return-path: Received: from mail-pg0-f67.google.com ([74.125.83.67]:57045 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752721AbdKFVsI (ORCPT ); Mon, 6 Nov 2017 16:48:08 -0500 Received: by mail-pg0-f67.google.com with SMTP id m18so9283266pgd.13 for ; Mon, 06 Nov 2017 13:48:07 -0800 (PST) In-Reply-To: <20171106214730.24421-1-xiyou.wangcong@gmail.com> Sender: netdev-owner@vger.kernel.org List-ID: Hold netns refcnt before call_rcu() and release it after the tcf_exts_destroy() is done. Note, on ->destroy() path we have to respect the return value of tcf_exts_get_net(), on other paths it should always return true, so we don't need to care. Cc: Lucas Bates Cc: Jamal Hadi Salim Cc: Jiri Pirko Signed-off-by: Cong Wang --- net/sched/cls_tcindex.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index beaa95e09c25..a76937ee0b2d 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -139,13 +139,19 @@ static int tcindex_init(struct tcf_proto *tp) return 0; } +static void __tcindex_destroy_rexts(struct tcindex_filter_result *r) +{ + tcf_exts_destroy(&r->exts); + tcf_exts_put_net(&r->exts); +} + static void tcindex_destroy_rexts_work(struct work_struct *work) { struct tcindex_filter_result *r; r = container_of(work, struct tcindex_filter_result, work); rtnl_lock(); - tcf_exts_destroy(&r->exts); + __tcindex_destroy_rexts(r); rtnl_unlock(); } @@ -158,14 +164,20 @@ static void tcindex_destroy_rexts(struct rcu_head *head) tcf_queue_work(&r->work); } +static void __tcindex_destroy_fexts(struct tcindex_filter *f) +{ + tcf_exts_destroy(&f->result.exts); + tcf_exts_put_net(&f->result.exts); + kfree(f); +} + static void tcindex_destroy_fexts_work(struct work_struct *work) { struct tcindex_filter *f = container_of(work, struct tcindex_filter, work); rtnl_lock(); - tcf_exts_destroy(&f->result.exts); - kfree(f); + __tcindex_destroy_fexts(f); rtnl_unlock(); } @@ -210,10 +222,17 @@ static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last) * grace period, since converted-to-rcu actions are relying on that * in cleanup() callback */ - if (f) - call_rcu(&f->rcu, tcindex_destroy_fexts); - else - call_rcu(&r->rcu, tcindex_destroy_rexts); + if (f) { + if (tcf_exts_get_net(&f->result.exts)) + call_rcu(&f->rcu, tcindex_destroy_fexts); + else + __tcindex_destroy_fexts(f); + } else { + if (tcf_exts_get_net(&r->exts)) + call_rcu(&r->rcu, tcindex_destroy_rexts); + else + __tcindex_destroy_rexts(r); + } *last = false; return 0; -- 2.13.0