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 <[email protected]> Cc: Jamal Hadi Salim <[email protected]> Cc: Jiri Pirko <[email protected]> Signed-off-by: Cong Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
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)

net/sched/act_ipt.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,6 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
189189
ipt->tcfi_t = t;
190190
ipt->tcfi_hook = hook;
191191
spin_unlock_bh(&ipt->tcf_lock);
192-
if (ret == ACT_P_CREATED)
193-
tcf_idr_insert(tn, *a);
194192
return ret;
195193

196194
err3:

net/sched/act_mirred.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
194194
spin_lock(&mirred_list_lock);
195195
list_add(&m->tcfm_list, &mirred_list);
196196
spin_unlock(&mirred_list_lock);
197-
198-
tcf_idr_insert(tn, *a);
199197
}
200198

201199
return ret;

net/sched/act_mpls.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,6 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
273273
if (p)
274274
kfree_rcu(p, rcu);
275275

276-
if (ret == ACT_P_CREATED)
277-
tcf_idr_insert(tn, *a);
278276
return ret;
279277
put_chain:
280278
if (goto_ch)

net/sched/act_nat.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
9393
if (goto_ch)
9494
tcf_chain_put_by_act(goto_ch);
9595

96-
if (ret == ACT_P_CREATED)
97-
tcf_idr_insert(tn, *a);
98-
9996
return ret;
10097
release_idr:
10198
tcf_idr_release(*a, bind);

net/sched/act_pedit.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
238238
spin_unlock_bh(&p->tcf_lock);
239239
if (goto_ch)
240240
tcf_chain_put_by_act(goto_ch);
241-
if (ret == ACT_P_CREATED)
242-
tcf_idr_insert(tn, *a);
243241
return ret;
244242

245243
put_chain:

net/sched/act_police.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,6 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
201201
if (new)
202202
kfree_rcu(new, rcu);
203203

204-
if (ret == ACT_P_CREATED)
205-
tcf_idr_insert(tn, *a);
206204
return ret;
207205

208206
failure:

net/sched/act_sample.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,6 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
116116
if (goto_ch)
117117
tcf_chain_put_by_act(goto_ch);
118118

119-
if (ret == ACT_P_CREATED)
120-
tcf_idr_insert(tn, *a);
121119
return ret;
122120
put_chain:
123121
if (goto_ch)

net/sched/act_simple.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
157157
goto release_idr;
158158
}
159159

160-
if (ret == ACT_P_CREATED)
161-
tcf_idr_insert(tn, *a);
162160
return ret;
163161
put_chain:
164162
if (goto_ch)

net/sched/act_skbedit.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
225225
if (goto_ch)
226226
tcf_chain_put_by_act(goto_ch);
227227

228-
if (ret == ACT_P_CREATED)
229-
tcf_idr_insert(tn, *a);
230228
return ret;
231229
put_chain:
232230
if (goto_ch)

net/sched/act_skbmod.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,6 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
190190
if (goto_ch)
191191
tcf_chain_put_by_act(goto_ch);
192192

193-
if (ret == ACT_P_CREATED)
194-
tcf_idr_insert(tn, *a);
195193
return ret;
196194
put_chain:
197195
if (goto_ch)

net/sched/act_tunnel_key.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,6 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
537537
if (goto_ch)
538538
tcf_chain_put_by_act(goto_ch);
539539

540-
if (ret == ACT_P_CREATED)
541-
tcf_idr_insert(tn, *a);
542-
543540
return ret;
544541

545542
put_chain:

net/sched/act_vlan.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,6 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
229229
if (p)
230230
kfree_rcu(p, rcu);
231231

232-
if (ret == ACT_P_CREATED)
233-
tcf_idr_insert(tn, *a);
234232
return ret;
235233
put_chain:
236234
if (goto_ch)

0 commit comments

Comments
 (0)