Skip to content

Commit f2fbd0a

Browse files
committed
Merge branch 'net-sched-action-init-fixes'
Vlad Buslov says: ==================== Action initalization fixes This series fixes reference counting of action instances and modules in several parts of action init code. The first patch reverts previous fix that didn't properly account for rollback from a failure in the middle of the loop in tcf_action_init() which is properly fixed by the following patch. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 8a12f88 + b3650bf commit f2fbd0a

File tree

3 files changed

+42
-35
lines changed

3 files changed

+42
-35
lines changed

include/net/act_api.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,7 @@ void tcf_idr_insert_many(struct tc_action *actions[]);
170170
void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
171171
int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
172172
struct tc_action **a, int bind);
173-
int __tcf_idr_release(struct tc_action *a, bool bind, bool strict);
174-
175-
static inline int tcf_idr_release(struct tc_action *a, bool bind)
176-
{
177-
return __tcf_idr_release(a, bind, false);
178-
}
173+
int tcf_idr_release(struct tc_action *a, bool bind);
179174

180175
int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
181176
int tcf_unregister_action(struct tc_action_ops *a,
@@ -185,15 +180,16 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
185180
int nr_actions, struct tcf_result *res);
186181
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
187182
struct nlattr *est, char *name, int ovr, int bind,
188-
struct tc_action *actions[], size_t *attr_size,
183+
struct tc_action *actions[], int init_res[], size_t *attr_size,
189184
bool rtnl_held, struct netlink_ext_ack *extack);
190185
struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
191186
bool rtnl_held,
192187
struct netlink_ext_ack *extack);
193188
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
194189
struct nlattr *nla, struct nlattr *est,
195190
char *name, int ovr, int bind,
196-
struct tc_action_ops *ops, bool rtnl_held,
191+
struct tc_action_ops *a_o, int *init_res,
192+
bool rtnl_held,
197193
struct netlink_ext_ack *extack);
198194
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind,
199195
int ref, bool terse);

net/sched/act_api.c

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static int __tcf_action_put(struct tc_action *p, bool bind)
158158
return 0;
159159
}
160160

161-
int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
161+
static int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
162162
{
163163
int ret = 0;
164164

@@ -184,7 +184,18 @@ int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
184184

185185
return ret;
186186
}
187-
EXPORT_SYMBOL(__tcf_idr_release);
187+
188+
int tcf_idr_release(struct tc_action *a, bool bind)
189+
{
190+
const struct tc_action_ops *ops = a->ops;
191+
int ret;
192+
193+
ret = __tcf_idr_release(a, bind, false);
194+
if (ret == ACT_P_DELETED)
195+
module_put(ops->owner);
196+
return ret;
197+
}
198+
EXPORT_SYMBOL(tcf_idr_release);
188199

189200
static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
190201
{
@@ -493,6 +504,7 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
493504
}
494505

495506
p->idrinfo = idrinfo;
507+
__module_get(ops->owner);
496508
p->ops = ops;
497509
*a = p;
498510
return 0;
@@ -992,7 +1004,8 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
9921004
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
9931005
struct nlattr *nla, struct nlattr *est,
9941006
char *name, int ovr, int bind,
995-
struct tc_action_ops *a_o, bool rtnl_held,
1007+
struct tc_action_ops *a_o, int *init_res,
1008+
bool rtnl_held,
9961009
struct netlink_ext_ack *extack)
9971010
{
9981011
struct nla_bitfield32 flags = { 0, 0 };
@@ -1028,23 +1041,14 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
10281041
}
10291042
if (err < 0)
10301043
goto err_out;
1044+
*init_res = err;
10311045

10321046
if (!name && tb[TCA_ACT_COOKIE])
10331047
tcf_set_action_cookie(&a->act_cookie, cookie);
10341048

10351049
if (!name)
10361050
a->hw_stats = hw_stats;
10371051

1038-
/* module count goes up only when brand new policy is created
1039-
* if it exists and is only bound to in a_o->init() then
1040-
* ACT_P_CREATED is not returned (a zero is).
1041-
*/
1042-
if (err != ACT_P_CREATED)
1043-
module_put(a_o->owner);
1044-
1045-
if (!bind && ovr && err == ACT_P_CREATED)
1046-
refcount_set(&a->tcfa_refcnt, 2);
1047-
10481052
return a;
10491053

10501054
err_out:
@@ -1059,7 +1063,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
10591063

10601064
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
10611065
struct nlattr *est, char *name, int ovr, int bind,
1062-
struct tc_action *actions[], size_t *attr_size,
1066+
struct tc_action *actions[], int init_res[], size_t *attr_size,
10631067
bool rtnl_held, struct netlink_ext_ack *extack)
10641068
{
10651069
struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {};
@@ -1087,7 +1091,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
10871091

10881092
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
10891093
act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
1090-
ops[i - 1], rtnl_held, extack);
1094+
ops[i - 1], &init_res[i - 1], rtnl_held,
1095+
extack);
10911096
if (IS_ERR(act)) {
10921097
err = PTR_ERR(act);
10931098
goto err;
@@ -1103,7 +1108,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
11031108
tcf_idr_insert_many(actions);
11041109

11051110
*attr_size = tcf_action_full_attrs_size(sz);
1106-
return i - 1;
1111+
err = i - 1;
1112+
goto err_mod;
11071113

11081114
err:
11091115
tcf_action_destroy(actions, bind);
@@ -1500,21 +1506,26 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
15001506
struct netlink_ext_ack *extack)
15011507
{
15021508
size_t attr_size = 0;
1503-
int loop, ret;
1509+
int loop, ret, i;
15041510
struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
1511+
int init_res[TCA_ACT_MAX_PRIO] = {};
15051512

15061513
for (loop = 0; loop < 10; loop++) {
15071514
ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0,
1508-
actions, &attr_size, true, extack);
1515+
actions, init_res, &attr_size, true, extack);
15091516
if (ret != -EAGAIN)
15101517
break;
15111518
}
15121519

15131520
if (ret < 0)
15141521
return ret;
15151522
ret = tcf_add_notify(net, n, actions, portid, attr_size, extack);
1516-
if (ovr)
1517-
tcf_action_put_many(actions);
1523+
1524+
/* only put existing actions */
1525+
for (i = 0; i < TCA_ACT_MAX_PRIO; i++)
1526+
if (init_res[i] == ACT_P_CREATED)
1527+
actions[i] = NULL;
1528+
tcf_action_put_many(actions);
15181529

15191530
return ret;
15201531
}

net/sched/cls_api.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3040,6 +3040,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
30403040
{
30413041
#ifdef CONFIG_NET_CLS_ACT
30423042
{
3043+
int init_res[TCA_ACT_MAX_PRIO] = {};
30433044
struct tc_action *act;
30443045
size_t attr_size = 0;
30453046

@@ -3051,12 +3052,11 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
30513052
return PTR_ERR(a_o);
30523053
act = tcf_action_init_1(net, tp, tb[exts->police],
30533054
rate_tlv, "police", ovr,
3054-
TCA_ACT_BIND, a_o, rtnl_held,
3055-
extack);
3056-
if (IS_ERR(act)) {
3057-
module_put(a_o->owner);
3055+
TCA_ACT_BIND, a_o, init_res,
3056+
rtnl_held, extack);
3057+
module_put(a_o->owner);
3058+
if (IS_ERR(act))
30583059
return PTR_ERR(act);
3059-
}
30603060

30613061
act->type = exts->type = TCA_OLD_COMPAT;
30623062
exts->actions[0] = act;
@@ -3067,8 +3067,8 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
30673067

30683068
err = tcf_action_init(net, tp, tb[exts->action],
30693069
rate_tlv, NULL, ovr, TCA_ACT_BIND,
3070-
exts->actions, &attr_size,
3071-
rtnl_held, extack);
3070+
exts->actions, init_res,
3071+
&attr_size, rtnl_held, extack);
30723072
if (err < 0)
30733073
return err;
30743074
exts->nr_actions = err;

0 commit comments

Comments
 (0)