Commit 7be8ef2c authored by Dmytro Linkin's avatar Dmytro Linkin Committed by David S. Miller

net: sched: use temporary variable for actions indexes

Currently init call of all actions (except ipt) init their 'parm'
structure as a direct pointer to nla data in skb. This leads to race
condition when some of the filter actions were initialized successfully
(and were assigned with idr action index that was written directly
into nla data), but then were deleted and retried (due to following
action module missing or classifier-initiated retry), in which case
action init code tries to insert action to idr with index that was
assigned on previous iteration. During retry the index can be reused
by another action that was inserted concurrently, which causes
unintended action sharing between filters.
To fix described race condition, save action idr index to temporary
stack-allocated variable instead on nla data.

Fixes: 0190c1d4 ("net: sched: atomically check-allocate action")
Signed-off-by: default avatarDmytro Linkin <dmitrolin@mellanox.com>
Signed-off-by: default avatarVlad Buslov <vladbu@mellanox.com>
Acked-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7fb5a711
...@@ -285,6 +285,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -285,6 +285,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct tcf_bpf *prog; struct tcf_bpf *prog;
bool is_bpf, is_ebpf; bool is_bpf, is_ebpf;
int ret, res = 0; int ret, res = 0;
u32 index;
if (!nla) if (!nla)
return -EINVAL; return -EINVAL;
...@@ -298,13 +299,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -298,13 +299,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_ACT_BPF_PARMS]); parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
index = parm->index;
ret = tcf_idr_check_alloc(tn, &parm->index, act, bind); ret = tcf_idr_check_alloc(tn, &index, act, bind);
if (!ret) { if (!ret) {
ret = tcf_idr_create(tn, parm->index, est, act, ret = tcf_idr_create(tn, index, est, act,
&act_bpf_ops, bind, true); &act_bpf_ops, bind, true);
if (ret < 0) { if (ret < 0) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
...@@ -103,6 +103,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ...@@ -103,6 +103,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
struct tcf_connmark_info *ci; struct tcf_connmark_info *ci;
struct tc_connmark *parm; struct tc_connmark *parm;
int ret = 0, err; int ret = 0, err;
u32 index;
if (!nla) if (!nla)
return -EINVAL; return -EINVAL;
...@@ -116,13 +117,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ...@@ -116,13 +117,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_CONNMARK_PARMS]); parm = nla_data(tb[TCA_CONNMARK_PARMS]);
index = parm->index;
ret = tcf_idr_check_alloc(tn, &parm->index, a, bind); ret = tcf_idr_check_alloc(tn, &index, a, bind);
if (!ret) { if (!ret) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_connmark_ops, bind, false); &act_connmark_ops, bind, false);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
...@@ -52,6 +52,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, ...@@ -52,6 +52,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
struct tc_csum *parm; struct tc_csum *parm;
struct tcf_csum *p; struct tcf_csum *p;
int ret = 0, err; int ret = 0, err;
u32 index;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -64,13 +65,13 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, ...@@ -64,13 +65,13 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
if (tb[TCA_CSUM_PARMS] == NULL) if (tb[TCA_CSUM_PARMS] == NULL)
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_CSUM_PARMS]); parm = nla_data(tb[TCA_CSUM_PARMS]);
index = parm->index;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_csum_ops, bind, true); &act_csum_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -666,6 +666,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, ...@@ -666,6 +666,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
struct tc_ct *parm; struct tc_ct *parm;
struct tcf_ct *c; struct tcf_ct *c;
int err, res = 0; int err, res = 0;
u32 index;
if (!nla) { if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed"); NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed");
...@@ -681,16 +682,16 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, ...@@ -681,16 +682,16 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
} }
parm = nla_data(tb[TCA_CT_PARMS]); parm = nla_data(tb[TCA_CT_PARMS]);
index = parm->index;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
if (!err) { if (!err) {
err = tcf_idr_create(tn, parm->index, est, a, err = tcf_idr_create(tn, index, est, a,
&act_ct_ops, bind, true); &act_ct_ops, bind, true);
if (err) { if (err) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return err; return err;
} }
res = ACT_P_CREATED; res = ACT_P_CREATED;
......
...@@ -157,10 +157,10 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, ...@@ -157,10 +157,10 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ctinfo_net_id); struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
u32 dscpmask = 0, dscpstatemask, index;
struct nlattr *tb[TCA_CTINFO_MAX + 1]; struct nlattr *tb[TCA_CTINFO_MAX + 1];
struct tcf_ctinfo_params *cp_new; struct tcf_ctinfo_params *cp_new;
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
u32 dscpmask = 0, dscpstatemask;
struct tc_ctinfo *actparm; struct tc_ctinfo *actparm;
struct tcf_ctinfo *ci; struct tcf_ctinfo *ci;
u8 dscpmaskshift; u8 dscpmaskshift;
...@@ -206,12 +206,13 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, ...@@ -206,12 +206,13 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
} }
/* done the validation:now to the actual action allocation */ /* done the validation:now to the actual action allocation */
err = tcf_idr_check_alloc(tn, &actparm->index, a, bind); index = actparm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, actparm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_ctinfo_ops, bind, false); &act_ctinfo_ops, bind, false);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, actparm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -61,6 +61,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -61,6 +61,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
struct tc_gact *parm; struct tc_gact *parm;
struct tcf_gact *gact; struct tcf_gact *gact;
int ret = 0; int ret = 0;
u32 index;
int err; int err;
#ifdef CONFIG_GACT_PROB #ifdef CONFIG_GACT_PROB
struct tc_gact_p *p_parm = NULL; struct tc_gact_p *p_parm = NULL;
...@@ -77,6 +78,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -77,6 +78,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
if (tb[TCA_GACT_PARMS] == NULL) if (tb[TCA_GACT_PARMS] == NULL)
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_GACT_PARMS]); parm = nla_data(tb[TCA_GACT_PARMS]);
index = parm->index;
#ifndef CONFIG_GACT_PROB #ifndef CONFIG_GACT_PROB
if (tb[TCA_GACT_PROB] != NULL) if (tb[TCA_GACT_PROB] != NULL)
...@@ -94,12 +96,12 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -94,12 +96,12 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
} }
#endif #endif
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_gact_ops, bind, true); &act_gact_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -479,6 +479,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -479,6 +479,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
u8 *saddr = NULL; u8 *saddr = NULL;
bool exists = false; bool exists = false;
int ret = 0; int ret = 0;
u32 index;
int err; int err;
if (!nla) { if (!nla) {
...@@ -507,7 +508,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -507,7 +508,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) { if (err < 0) {
kfree(p); kfree(p);
return err; return err;
...@@ -519,10 +521,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -519,10 +521,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
} }
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops, ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
bind, true); bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
kfree(p); kfree(p);
return ret; return ret;
} }
......
...@@ -104,6 +104,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -104,6 +104,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
struct net_device *dev; struct net_device *dev;
bool exists = false; bool exists = false;
int ret, err; int ret, err;
u32 index;
if (!nla) { if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed"); NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
...@@ -118,8 +119,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -118,8 +119,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
} }
parm = nla_data(tb[TCA_MIRRED_PARMS]); parm = nla_data(tb[TCA_MIRRED_PARMS]);
index = parm->index;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -136,21 +137,21 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -136,21 +137,21 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option"); NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
return -EINVAL; return -EINVAL;
} }
if (!exists) { if (!exists) {
if (!parm->ifindex) { if (!parm->ifindex) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist"); NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
return -EINVAL; return -EINVAL;
} }
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_mirred_ops, bind, true); &act_mirred_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -138,6 +138,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, ...@@ -138,6 +138,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
struct tcf_mpls *m; struct tcf_mpls *m;
int ret = 0, err; int ret = 0, err;
u8 mpls_ttl = 0; u8 mpls_ttl = 0;
u32 index;
if (!nla) { if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes"); NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes");
...@@ -153,6 +154,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, ...@@ -153,6 +154,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
} }
parm = nla_data(tb[TCA_MPLS_PARMS]); parm = nla_data(tb[TCA_MPLS_PARMS]);
index = parm->index;
/* Verify parameters against action type. */ /* Verify parameters against action type. */
switch (parm->m_action) { switch (parm->m_action) {
...@@ -209,7 +211,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, ...@@ -209,7 +211,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
} }
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -217,10 +219,10 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, ...@@ -217,10 +219,10 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
return 0; return 0;
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_mpls_ops, bind, true); &act_mpls_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
...@@ -44,6 +44,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -44,6 +44,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
struct tc_nat *parm; struct tc_nat *parm;
int ret = 0, err; int ret = 0, err;
struct tcf_nat *p; struct tcf_nat *p;
u32 index;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
if (tb[TCA_NAT_PARMS] == NULL) if (tb[TCA_NAT_PARMS] == NULL)
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_NAT_PARMS]); parm = nla_data(tb[TCA_NAT_PARMS]);
index = parm->index;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_nat_ops, bind, false); &act_nat_ops, bind, false);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
struct tcf_pedit *p; struct tcf_pedit *p;
int ret = 0, err; int ret = 0, err;
int ksize; int ksize;
u32 index;
if (!nla) { if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed"); NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed");
...@@ -179,18 +180,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -179,18 +180,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
if (IS_ERR(keys_ex)) if (IS_ERR(keys_ex))
return PTR_ERR(keys_ex); return PTR_ERR(keys_ex);
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
if (!parm->nkeys) { if (!parm->nkeys) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed"); NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
ret = -EINVAL; ret = -EINVAL;
goto out_free; goto out_free;
} }
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_pedit_ops, bind, false); &act_pedit_ops, bind, false);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
goto out_free; goto out_free;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -57,6 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, ...@@ -57,6 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
struct tc_action_net *tn = net_generic(net, police_net_id); struct tc_action_net *tn = net_generic(net, police_net_id);
struct tcf_police_params *new; struct tcf_police_params *new;
bool exists = false; bool exists = false;
u32 index;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -73,7 +74,8 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, ...@@ -73,7 +74,8 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_POLICE_TBF]); parm = nla_data(tb[TCA_POLICE_TBF]);
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -81,10 +83,10 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, ...@@ -81,10 +83,10 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
return 0; return 0;
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, NULL, a, ret = tcf_idr_create(tn, index, NULL, a,
&act_police_ops, bind, true); &act_police_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -41,8 +41,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, ...@@ -41,8 +41,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
struct tc_action_net *tn = net_generic(net, sample_net_id); struct tc_action_net *tn = net_generic(net, sample_net_id);
struct nlattr *tb[TCA_SAMPLE_MAX + 1]; struct nlattr *tb[TCA_SAMPLE_MAX + 1];
struct psample_group *psample_group; struct psample_group *psample_group;
u32 psample_group_num, rate, index;
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
u32 psample_group_num, rate;
struct tc_sample *parm; struct tc_sample *parm;
struct tcf_sample *s; struct tcf_sample *s;
bool exists = false; bool exists = false;
...@@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, ...@@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_SAMPLE_PARMS]); parm = nla_data(tb[TCA_SAMPLE_PARMS]);
index = parm->index;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, ...@@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
return 0; return 0;
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_sample_ops, bind, true); &act_sample_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
......
...@@ -95,6 +95,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -95,6 +95,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct tcf_defact *d; struct tcf_defact *d;
bool exists = false; bool exists = false;
int ret = 0, err; int ret = 0, err;
u32 index;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -108,7 +109,8 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -108,7 +109,8 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_DEF_PARMS]); parm = nla_data(tb[TCA_DEF_PARMS]);
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -119,15 +121,15 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -119,15 +121,15 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return -EINVAL; return -EINVAL;
} }
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_simp_ops, bind, false); &act_simp_ops, bind, false);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
...@@ -99,6 +99,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -99,6 +99,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
u16 *queue_mapping = NULL, *ptype = NULL; u16 *queue_mapping = NULL, *ptype = NULL;
bool exists = false; bool exists = false;
int ret = 0, err; int ret = 0, err;
u32 index;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -146,8 +147,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -146,8 +147,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
} }
parm = nla_data(tb[TCA_SKBEDIT_PARMS]); parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
index = parm->index;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -158,15 +159,15 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -158,15 +159,15 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return -EINVAL; return -EINVAL;
} }
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_skbedit_ops, bind, true); &act_skbedit_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
...@@ -87,12 +87,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, ...@@ -87,12 +87,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
struct tcf_skbmod_params *p, *p_old; struct tcf_skbmod_params *p, *p_old;
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tc_skbmod *parm; struct tc_skbmod *parm;
u32 lflags = 0, index;
struct tcf_skbmod *d; struct tcf_skbmod *d;
bool exists = false; bool exists = false;
u8 *daddr = NULL; u8 *daddr = NULL;
u8 *saddr = NULL; u8 *saddr = NULL;
u16 eth_type = 0; u16 eth_type = 0;
u32 lflags = 0;
int ret = 0, err; int ret = 0, err;
if (!nla) if (!nla)
...@@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, ...@@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
} }
parm = nla_data(tb[TCA_SKBMOD_PARMS]); parm = nla_data(tb[TCA_SKBMOD_PARMS]);
index = parm->index;
if (parm->flags & SKBMOD_F_SWAPMAC) if (parm->flags & SKBMOD_F_SWAPMAC)
lflags = SKBMOD_F_SWAPMAC; lflags = SKBMOD_F_SWAPMAC;
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, ...@@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return -EINVAL; return -EINVAL;
} }
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_skbmod_ops, bind, true); &act_skbmod_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
...@@ -225,6 +225,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, ...@@ -225,6 +225,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
__be16 flags = 0; __be16 flags = 0;
u8 tos, ttl; u8 tos, ttl;
int ret = 0; int ret = 0;
u32 index;
int err; int err;
if (!nla) { if (!nla) {
...@@ -245,7 +246,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, ...@@ -245,7 +246,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
} }
parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]); parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -345,7 +347,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, ...@@ -345,7 +347,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
} }
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_tunnel_key_ops, bind, true); &act_tunnel_key_ops, bind, true);
if (ret) { if (ret) {
NL_SET_ERR_MSG(extack, "Cannot create TC IDR"); NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
...@@ -403,7 +405,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, ...@@ -403,7 +405,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
...@@ -116,6 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -116,6 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
u8 push_prio = 0; u8 push_prio = 0;
bool exists = false; bool exists = false;
int ret = 0, err; int ret = 0, err;
u32 index;
if (!nla) if (!nla)
return -EINVAL; return -EINVAL;
...@@ -128,7 +129,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -128,7 +129,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (!tb[TCA_VLAN_PARMS]) if (!tb[TCA_VLAN_PARMS])
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_VLAN_PARMS]); parm = nla_data(tb[TCA_VLAN_PARMS]);
err = tcf_idr_check_alloc(tn, &parm->index, a, bind); index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind);
if (err < 0) if (err < 0)
return err; return err;
exists = err; exists = err;
...@@ -144,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -144,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return -EINVAL; return -EINVAL;
} }
push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
...@@ -152,7 +154,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -152,7 +154,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return -ERANGE; return -ERANGE;
} }
...@@ -166,7 +168,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -166,7 +168,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
} }
} else { } else {
...@@ -180,16 +182,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -180,16 +182,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
else else
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return -EINVAL; return -EINVAL;
} }
action = parm->v_action; action = parm->v_action;
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_vlan_ops, bind, true); &act_vlan_ops, bind, true);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, parm->index); tcf_idr_cleanup(tn, index);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment