Skip to content

Commit

Permalink
cls_cgroup: read classid atomically in classifier
Browse files Browse the repository at this point in the history
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Paul Menage authored and David S. Miller committed May 27, 2009
1 parent 7682455 commit e65fcfd
Showing 1 changed file with 11 additions and 11 deletions.
22 changes: 11 additions & 11 deletions net/sched/cls_cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,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
Expand All @@ -121,17 +120,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)
Expand Down

0 comments on commit e65fcfd

Please sign in to comment.