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> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7682455ec3
commit
e65fcfd63a
1 changed files with 11 additions and 11 deletions
|
@ -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
|
||||
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue