Skip to content

Commit e49d8c2

Browse files
congwangdavem330
authored andcommitted
net_sched: defer tcf_idr_insert() in tcf_action_init_1()
All TC actions call tcf_idr_insert() for new action at the end of their ->init(), so we can actually move it to a central place in tcf_action_init_1(). And once the action is inserted into the global IDR, other parallel process could free it immediately as its refcnt is still 1, so we can not fail after this, we need to move it after the goto action validation to avoid handling the failure case after insertion. This is found during code review, is not directly triggered by syzbot. And this prepares for the next patch. Cc: Vlad Buslov <vladbu@mellanox.com> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: Jiri Pirko <jiri@resnulli.us> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7241c5a commit e49d8c2

22 files changed

+21
-66
lines changed

include/net/act_api.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,6 @@ int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
166166
struct nlattr *est, struct tc_action **a,
167167
const struct tc_action_ops *ops, int bind,
168168
u32 flags);
169-
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
170-
171169
void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
172170
int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
173171
struct tc_action **a, int bind);

net/sched/act_api.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -467,17 +467,6 @@ int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
467467
}
468468
EXPORT_SYMBOL(tcf_idr_create_from_flags);
469469

470-
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
471-
{
472-
struct tcf_idrinfo *idrinfo = tn->idrinfo;
473-
474-
mutex_lock(&idrinfo->lock);
475-
/* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
476-
WARN_ON(!IS_ERR(idr_replace(&idrinfo->action_idr, a, a->tcfa_index)));
477-
mutex_unlock(&idrinfo->lock);
478-
}
479-
EXPORT_SYMBOL(tcf_idr_insert);
480-
481470
/* Cleanup idr index that was allocated but not initialized. */
482471

483472
void tcf_idr_cleanup(struct tc_action_net *tn, u32 index)
@@ -902,6 +891,16 @@ static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = {
902891
[TCA_ACT_HW_STATS] = NLA_POLICY_BITFIELD32(TCA_ACT_HW_STATS_ANY),
903892
};
904893

894+
static void tcf_idr_insert(struct tc_action *a)
895+
{
896+
struct tcf_idrinfo *idrinfo = a->idrinfo;
897+
898+
mutex_lock(&idrinfo->lock);
899+
/* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
900+
WARN_ON(!IS_ERR(idr_replace(&idrinfo->action_idr, a, a->tcfa_index)));
901+
mutex_unlock(&idrinfo->lock);
902+
}
903+
905904
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
906905
struct nlattr *nla, struct nlattr *est,
907906
char *name, int ovr, int bind,
@@ -989,6 +988,16 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
989988
if (err < 0)
990989
goto err_mod;
991990

991+
if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN) &&
992+
!rcu_access_pointer(a->goto_chain)) {
993+
tcf_action_destroy_1(a, bind);
994+
NL_SET_ERR_MSG(extack, "can't use goto chain with NULL chain");
995+
return ERR_PTR(-EINVAL);
996+
}
997+
998+
if (err == ACT_P_CREATED)
999+
tcf_idr_insert(a);
1000+
9921001
if (!name && tb[TCA_ACT_COOKIE])
9931002
tcf_set_action_cookie(&a->act_cookie, cookie);
9941003

@@ -1002,13 +1011,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
10021011
if (err != ACT_P_CREATED)
10031012
module_put(a_o->owner);
10041013

1005-
if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN) &&
1006-
!rcu_access_pointer(a->goto_chain)) {
1007-
tcf_action_destroy_1(a, bind);
1008-
NL_SET_ERR_MSG(extack, "can't use goto chain with NULL chain");
1009-
return ERR_PTR(-EINVAL);
1010-
}
1011-
10121014
return a;
10131015

10141016
err_mod:

net/sched/act_bpf.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
365365
if (goto_ch)
366366
tcf_chain_put_by_act(goto_ch);
367367

368-
if (res == ACT_P_CREATED) {
369-
tcf_idr_insert(tn, *act);
370-
} else {
368+
if (res != ACT_P_CREATED) {
371369
/* make sure the program being replaced is no longer executing */
372370
synchronize_rcu();
373371
tcf_bpf_cfg_cleanup(&old);

net/sched/act_connmark.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
139139
ci->net = net;
140140
ci->zone = parm->zone;
141141

142-
tcf_idr_insert(tn, *a);
143142
ret = ACT_P_CREATED;
144143
} else if (ret > 0) {
145144
ci = to_connmark(*a);

net/sched/act_csum.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
110110
if (params_new)
111111
kfree_rcu(params_new, rcu);
112112

113-
if (ret == ACT_P_CREATED)
114-
tcf_idr_insert(tn, *a);
115-
116113
return ret;
117114
put_chain:
118115
if (goto_ch)

net/sched/act_ct.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,8 +1297,6 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
12971297
tcf_chain_put_by_act(goto_ch);
12981298
if (params)
12991299
call_rcu(&params->rcu, tcf_ct_params_free);
1300-
if (res == ACT_P_CREATED)
1301-
tcf_idr_insert(tn, *a);
13021300

13031301
return res;
13041302

net/sched/act_ctinfo.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,6 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
269269
if (cp_new)
270270
kfree_rcu(cp_new, rcu);
271271

272-
if (ret == ACT_P_CREATED)
273-
tcf_idr_insert(tn, *a);
274-
275272
return ret;
276273

277274
put_chain:

net/sched/act_gact.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,6 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
140140
if (goto_ch)
141141
tcf_chain_put_by_act(goto_ch);
142142

143-
if (ret == ACT_P_CREATED)
144-
tcf_idr_insert(tn, *a);
145143
return ret;
146144
release_idr:
147145
tcf_idr_release(*a, bind);

net/sched/act_gate.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,6 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
437437
if (goto_ch)
438438
tcf_chain_put_by_act(goto_ch);
439439

440-
if (ret == ACT_P_CREATED)
441-
tcf_idr_insert(tn, *a);
442-
443440
return ret;
444441

445442
chain_put:

net/sched/act_ife.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
627627
if (p)
628628
kfree_rcu(p, rcu);
629629

630-
if (ret == ACT_P_CREATED)
631-
tcf_idr_insert(tn, *a);
632-
633630
return ret;
634631
metadata_parse_err:
635632
if (goto_ch)

0 commit comments

Comments
 (0)