diff mbox

cls_cgroup: read classid atomically in classifier

Message ID 20090526195840.8464.36548.stgit@menage.mtv.corp.google.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Paul Menage May 26, 2009, 7:59 p.m. UTC
cls_cgroup: read classid atomically in classifier

Avoid reading the unsynchronized value cs->classid multiple times,
since it could change concurrently from non-zero to zero; this would
result in the classifier returning a positive result with a bogus
(zero) classid.

Signed-off-by: Paul Menage <menage@google.com>
Reviewed-by: Li Zefan <lizf@cn.fujitsu.com>

---

Fixes a whitespace issue from the previous version of the patch

 net/sched/cls_cgroup.c |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Andrew Morton May 26, 2009, 9:04 p.m. UTC | #1
On Tue, 26 May 2009 12:59:11 -0700
Paul Menage <menage@google.com> wrote:

> Avoid reading the unsynchronized value cs->classid multiple times,
> since it could change concurrently from non-zero to zero; this would
> result in the classifier returning a positive result with a bogus
> (zero) classid.

When this race occurs, what are the user-visible consequences?

People who need to decide to which kernels a patch should be applied
like to know such things.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Menage May 26, 2009, 9:39 p.m. UTC | #2
On Tue, May 26, 2009 at 2:04 PM, Andrew Morton
<akpm@linux-foundation.org> wrote:
> On Tue, 26 May 2009 12:59:11 -0700
> Paul Menage <menage@google.com> wrote:
>
>> Avoid reading the unsynchronized value cs->classid multiple times,
>> since it could change concurrently from non-zero to zero; this would
>> result in the classifier returning a positive result with a bogus
>> (zero) classid.
>
> When this race occurs, what are the user-visible consequences?

My guess is very little - rather than returning -1 to indicate that
there's no classid associated with the flow, we're returning a
positive response that the classid is 0. I don't know the network
scheduling code well enough to predict what effect that would have,
but I'd guess it results in the subsequent classid->queue lookup
failing and the packet being shunted down some default queue (unless
the user happens to have set up a queue with id 0). But the race looks
to be against the intent of the code, which is to return -1 if the
classid is 0, or fill in the res struct if it's non-zero.

>
> People who need to decide to which kernels a patch should be applied
> like to know such things.
>

I don't think this is a -stable candidate.

Paul
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller May 27, 2009, 3:47 a.m. UTC | #3
From: Paul Menage <menage@google.com>
Date: Tue, 26 May 2009 12:59:11 -0700

> cls_cgroup: read classid atomically in classifier
> 
> Avoid reading the unsynchronized value cs->classid multiple times,
> since it could change concurrently from non-zero to zero; this would
> result in the classifier returning a positive result with a bogus
> (zero) classid.
> 
> Signed-off-by: Paul Menage <menage@google.com>
> Reviewed-by: Li Zefan <lizf@cn.fujitsu.com>

Patch applied, thanks!
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 1ab4542..0f815cc 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -98,8 +98,7 @@  static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
 			       struct tcf_result *res)
 {
 	struct cls_cgroup_head *head = tp->root;
-	struct cgroup_cls_state *cs;
-	int ret = 0;
+	u32 classid;
 
 	/*
 	 * Due to the nature of the classifier it is required to ignore all
@@ -115,17 +114,18 @@  static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
 		return -1;
 
 	rcu_read_lock();
-	cs = task_cls_state(current);
-	if (cs->classid && tcf_em_tree_match(skb, &head->ematches, NULL)) {
-		res->classid = cs->classid;
-		res->class = 0;
-		ret = tcf_exts_exec(skb, &head->exts, res);
-	} else
-		ret = -1;
-
+	classid = task_cls_state(current)->classid;
 	rcu_read_unlock();
 
-	return ret;
+	if (!classid)
+		return -1;
+
+	if (!tcf_em_tree_match(skb, &head->ematches, NULL))
+		return -1;
+
+	res->classid = classid;
+	res->class = 0;
+	return tcf_exts_exec(skb, &head->exts, res);
 }
 
 static unsigned long cls_cgroup_get(struct tcf_proto *tp, u32 handle)