diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2016-08-14 08:35:01 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-18 02:27:51 +0300 |
commit | 0852e455238f8550fa92b1e40355eb2c6805787e (patch) | |
tree | 516e10d249bd34a6eaf587ca9040ca6599a62029 | |
parent | 22dc13c837c33207548c8ee5116b64e2930a6e23 (diff) | |
download | linux-0852e455238f8550fa92b1e40355eb2c6805787e.tar.xz |
net_sched: unify the init logic for act_police
Jamal reported a crash when we create a police action
with a specific index, this is because the init logic
is not correct, we should always create one for this
case. Just unify the logic with other tc actions.
Fixes: a03e6fe56971 ("act_police: fix a crash during removal")
Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/sched/act_police.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index b3c7e975fc9e..259352d978df 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -125,6 +125,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, struct tcf_police *police; struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; struct tc_action_net *tn = net_generic(net, police_net_id); + bool exists = false; int size; if (nla == NULL) @@ -139,24 +140,24 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, size = nla_len(tb[TCA_POLICE_TBF]); if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat)) return -EINVAL; + parm = nla_data(tb[TCA_POLICE_TBF]); + exists = tcf_hash_check(tn, parm->index, a, bind); + if (exists && bind) + return 0; - if (parm->index) { - if (tcf_hash_check(tn, parm->index, a, bind)) { - if (ovr) - goto override; - /* not replacing */ - return -EEXIST; - } - } else { + if (!exists) { ret = tcf_hash_create(tn, parm->index, NULL, a, &act_police_ops, bind, false); if (ret) return ret; ret = ACT_P_CREATED; + } else { + tcf_hash_release(*a, bind); + if (!ovr) + return -EEXIST; } -override: police = to_police(*a); if (parm->rate.rate) { err = -ENOMEM; |