aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/act_sample.c
diff options
context:
space:
mode:
authorVlad Buslov <vladbu@mellanox.com>2018-07-05 17:24:30 +0300
committerDavid S. Miller <davem@davemloft.net>2018-07-08 12:42:29 +0900
commit4e8ddd7f1758ca4ddd0c1f7cf3e66fce736241d2 (patch)
tree645aad92e91829027f16cb33553063ac88cf6442 /net/sched/act_sample.c
parentnet: sched: implement reference counted action release (diff)
downloadlinux-dev-4e8ddd7f1758ca4ddd0c1f7cf3e66fce736241d2.tar.xz
linux-dev-4e8ddd7f1758ca4ddd0c1f7cf3e66fce736241d2.zip
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 <marcelo.leitner@gmail.com> Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--net/sched/act_sample.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index 6f79d2afcba2..a8582e1347db 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -69,10 +69,9 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
if (ret)
return ret;
ret = ACT_P_CREATED;
- } else {
+ } else if (!ovr) {
tcf_idr_release(*a, bind);
- if (!ovr)
- return -EEXIST;
+ return -EEXIST;
}
s = to_sample(*a);
@@ -81,8 +80,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
s->psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]);
psample_group = psample_group_get(net, s->psample_group_num);
if (!psample_group) {
- if (ret == ACT_P_CREATED)
- tcf_idr_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -ENOMEM;
}
RCU_INIT_POINTER(s->psample_group, psample_group);