netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: netdev@vger.kernel.org
Cc: Jamal Hadi Salim <jhs@mojatatu.com>,
	Cong Wang <xiyou.wangcong@gmail.com>,
	Jiri Pirko <jiri@resnulli.us>,
	stable@vger.kernel.org
Subject: [PATCH 1/7] fix hnode refcounting
Date: Wed,  5 Sep 2018 20:04:08 +0100	[thread overview]
Message-ID: <20180905190414.5477-1-viro@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20180905190134.GQ19965@ZenIV.linux.org.uk>

From: Al Viro <viro@zeniv.linux.org.uk>

cls_u32.c misuses refcounts for struct tc_u_hnode - it counts references via
->hlist and via ->tp_root together.  u32_destroy() drops the former and, in
case when there had been links, leaves the sucker on the list.  As the result,
there's nothing to protect it from getting freed once links are dropped.
That also makes the "is it busy" check incapable of catching the root hnode -
it *is* busy (there's a reference from tp), but we don't see it as something
separate.  "Is it our root?" check partially covers that, but the problem
exists for others' roots as well.

AFAICS, the minimal fix preserving the existing behaviour (where it doesn't
include oopsen, that is) would be this:
        * count tp->root and tp_c->hlist as separate references.  I.e.
have u32_init() set refcount to 2, not 1.
	* in u32_destroy() we always drop the former; in u32_destroy_hnode() -
the latter.

	That way we have *all* references contributing to refcount.  List
removal happens in u32_destroy_hnode() (called only when ->refcnt is 1)
an in u32_destroy() in case of tc_u_common going away, along with everything
reachable from it.  IOW, that way we know that u32_destroy_key() won't
free something still on the list (or pointed to by someone's ->root).

Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 net/sched/cls_u32.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index f218ccf1e2d9..3f985f29ef30 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -398,6 +398,7 @@ static int u32_init(struct tcf_proto *tp)
 	rcu_assign_pointer(tp_c->hlist, root_ht);
 	root_ht->tp_c = tp_c;
 
+	root_ht->refcnt++;
 	rcu_assign_pointer(tp->root, root_ht);
 	tp->data = tp_c;
 	return 0;
@@ -610,7 +611,7 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
 	struct tc_u_hnode __rcu **hn;
 	struct tc_u_hnode *phn;
 
-	WARN_ON(ht->refcnt);
+	WARN_ON(--ht->refcnt);
 
 	u32_clear_hnode(tp, ht, extack);
 
@@ -649,7 +650,7 @@ static void u32_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
 
 	WARN_ON(root_ht == NULL);
 
-	if (root_ht && --root_ht->refcnt == 0)
+	if (root_ht && --root_ht->refcnt == 1)
 		u32_destroy_hnode(tp, root_ht, extack);
 
 	if (--tp_c->refcnt == 0) {
@@ -698,7 +699,6 @@ static int u32_delete(struct tcf_proto *tp, void *arg, bool *last,
 	}
 
 	if (ht->refcnt == 1) {
-		ht->refcnt--;
 		u32_destroy_hnode(tp, ht, extack);
 	} else {
 		NL_SET_ERR_MSG_MOD(extack, "Can not delete in-use filter");
-- 
2.11.0

  reply	other threads:[~2018-09-05 23:35 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-05 19:01 [PATCHES] cls_u32 cleanups and fixes Al Viro
2018-09-05 19:04 ` Al Viro [this message]
2018-09-05 19:04   ` [PATCH 2/7] mark root hnode explicitly Al Viro
2018-09-06 10:28     ` Jamal Hadi Salim
2018-09-06 10:34       ` Jamal Hadi Salim
2018-09-06 10:42         ` Jamal Hadi Salim
2018-09-06 10:59         ` Al Viro
2018-09-06 11:04           ` Jamal Hadi Salim
2018-09-07  2:57           ` Cong Wang
2018-09-07  3:04             ` Al Viro
2018-09-07  3:23               ` Cong Wang
2018-09-07  3:49                 ` Al Viro
2018-09-07  4:14                   ` Cong Wang
2018-09-05 19:04   ` [PATCH 3/7] make sure that divisor is a power of 2 Al Viro
2018-09-06 10:28     ` Jamal Hadi Salim
2018-09-05 19:04   ` [PATCH 4/7] get rid of unused argument of u32_destroy_key() Al Viro
2018-09-06 10:34     ` Jamal Hadi Salim
2018-09-05 19:04   ` [PATCH 5/7] get rid of tc_u_knode ->tp Al Viro
2018-09-06 10:35     ` Jamal Hadi Salim
2018-09-05 19:04   ` [PATCH 6/7] get rid of tc_u_common ->rcu Al Viro
2018-09-06 10:36     ` Jamal Hadi Salim
2018-09-07  4:18     ` Cong Wang
2018-09-07  4:28       ` Al Viro
2018-09-05 19:04   ` [PATCH 7/7] clean tc_u_common hashtable Al Viro
2018-09-06 10:36     ` Jamal Hadi Salim
2018-09-06 10:21   ` [PATCH 1/7] fix hnode refcounting Jamal Hadi Salim
2018-09-07  2:35     ` Al Viro
2018-09-07 12:13       ` Jamal Hadi Salim
2018-09-07 12:33         ` Jamal Hadi Salim
2018-09-08 15:03         ` Al Viro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180905190414.5477-1-viro@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=jhs@mojatatu.com \
    --cc=jiri@resnulli.us \
    --cc=netdev@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=xiyou.wangcong@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).