Skip to content

Commit 4e8ddd7

Browse files
w1ldptrdavem330
authored andcommitted
net: sched: don't release reference on action overwrite
Return from action init function with reference to action taken, even when overwriting existing action. Action init API initializes its fourth argument (pointer to pointer to tc action) to either existing action with same index or newly created action. In case of existing index(and bind argument is zero), init function returns without incrementing action reference counter. Caller of action init then proceeds working with action, without actually holding reference to it. This means that action could be deleted concurrently. Change action init behavior to always take reference to action before returning successfully, in order to protect from concurrent deletion. Reviewed-by: Marcelo Ricardo Leitner <[email protected]> Signed-off-by: Vlad Buslov <[email protected]> Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 16af606 commit 4e8ddd7

17 files changed

+50
-58
lines changed

net/sched/act_api.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -870,8 +870,6 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
870870
}
871871
act->order = i;
872872
sz += tcf_action_fill_size(act);
873-
if (ovr)
874-
refcount_inc(&act->tcfa_refcnt);
875873
list_add_tail(&act->list, actions);
876874
}
877875

net/sched/act_bpf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,10 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
311311
if (bind)
312312
return 0;
313313

314-
tcf_idr_release(*act, bind);
315-
if (!replace)
314+
if (!replace) {
315+
tcf_idr_release(*act, bind);
316316
return -EEXIST;
317+
}
317318
}
318319

319320
is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS];
@@ -356,8 +357,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
356357

357358
return res;
358359
out:
359-
if (res == ACT_P_CREATED)
360-
tcf_idr_release(*act, bind);
360+
tcf_idr_release(*act, bind);
361361

362362
return ret;
363363
}

net/sched/act_connmark.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,10 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
135135
ci = to_connmark(*a);
136136
if (bind)
137137
return 0;
138-
tcf_idr_release(*a, bind);
139-
if (!ovr)
138+
if (!ovr) {
139+
tcf_idr_release(*a, bind);
140140
return -EEXIST;
141+
}
141142
/* replacing action and zone */
142143
ci->tcf_action = parm->action;
143144
ci->zone = parm->zone;

net/sched/act_csum.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,18 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
7676
} else {
7777
if (bind)/* dont override defaults */
7878
return 0;
79-
tcf_idr_release(*a, bind);
80-
if (!ovr)
79+
if (!ovr) {
80+
tcf_idr_release(*a, bind);
8181
return -EEXIST;
82+
}
8283
}
8384

8485
p = to_tcf_csum(*a);
8586
ASSERT_RTNL();
8687

8788
params_new = kzalloc(sizeof(*params_new), GFP_KERNEL);
8889
if (unlikely(!params_new)) {
89-
if (ret == ACT_P_CREATED)
90-
tcf_idr_release(*a, bind);
90+
tcf_idr_release(*a, bind);
9191
return -ENOMEM;
9292
}
9393
params_old = rtnl_dereference(p->params);

net/sched/act_gact.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,10 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
100100
} else {
101101
if (bind)/* dont override defaults */
102102
return 0;
103-
tcf_idr_release(*a, bind);
104-
if (!ovr)
103+
if (!ovr) {
104+
tcf_idr_release(*a, bind);
105105
return -EEXIST;
106+
}
106107
}
107108

108109
gact = to_gact(*a);

net/sched/act_ife.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -498,12 +498,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
498498
return ret;
499499
}
500500
ret = ACT_P_CREATED;
501-
} else {
501+
} else if (!ovr) {
502502
tcf_idr_release(*a, bind);
503-
if (!ovr) {
504-
kfree(p);
505-
return -EEXIST;
506-
}
503+
kfree(p);
504+
return -EEXIST;
507505
}
508506

509507
ife = to_ife(*a);
@@ -548,6 +546,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
548546

549547
if (exists)
550548
spin_unlock_bh(&ife->tcf_lock);
549+
tcf_idr_release(*a, bind);
550+
551551
kfree(p);
552552
return err;
553553
}

net/sched/act_ipt.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,11 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
145145
} else {
146146
if (bind)/* dont override defaults */
147147
return 0;
148-
tcf_idr_release(*a, bind);
149148

150-
if (!ovr)
149+
if (!ovr) {
150+
tcf_idr_release(*a, bind);
151151
return -EEXIST;
152+
}
152153
}
153154
hook = nla_get_u32(tb[TCA_IPT_HOOK]);
154155

net/sched/act_mirred.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,9 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
132132
if (ret)
133133
return ret;
134134
ret = ACT_P_CREATED;
135-
} else {
135+
} else if (!ovr) {
136136
tcf_idr_release(*a, bind);
137-
if (!ovr)
138-
return -EEXIST;
137+
return -EEXIST;
139138
}
140139
m = to_mirred(*a);
141140

net/sched/act_nat.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
6666
} else {
6767
if (bind)
6868
return 0;
69-
tcf_idr_release(*a, bind);
70-
if (!ovr)
69+
if (!ovr) {
70+
tcf_idr_release(*a, bind);
7171
return -EEXIST;
72+
}
7273
}
7374
p = to_tcf_nat(*a);
7475

net/sched/act_pedit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
194194
} else {
195195
if (bind)
196196
goto out_free;
197-
tcf_idr_release(*a, bind);
198197
if (!ovr) {
198+
tcf_idr_release(*a, bind);
199199
ret = -EEXIST;
200200
goto out_free;
201201
}

0 commit comments

Comments
 (0)