Skip to content

Commit 55334a5

Browse files
congwangdavem330
authored andcommitted
net_sched: act: refuse to remove bound action outside
When an action is bonnd to a filter, there is no point to remove it outside. Currently we just silently decrease the refcnt, we should reject this explicitly with EPERM. Cc: Jamal Hadi Salim <[email protected]> Cc: David S. Miller <[email protected]> Signed-off-by: Cong Wang <[email protected]> Signed-off-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4f1e9d8 commit 55334a5

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

include/net/act_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ void tcf_hash_insert(struct tc_action *a);
109109

110110
int tcf_register_action(struct tc_action_ops *a, unsigned int mask);
111111
int tcf_unregister_action(struct tc_action_ops *a);
112-
void tcf_action_destroy(struct list_head *actions, int bind);
112+
int tcf_action_destroy(struct list_head *actions, int bind);
113113
int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
114114
struct tcf_result *res);
115115
int tcf_action_init(struct net *net, struct nlattr *nla,

net/sched/act_api.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ int tcf_hash_release(struct tc_action *a, int bind)
5353
if (p) {
5454
if (bind)
5555
p->tcfc_bindcnt--;
56+
else if (p->tcfc_bindcnt > 0)
57+
return -EPERM;
5658

5759
p->tcfc_refcnt--;
5860
if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
@@ -123,6 +125,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
123125
struct tcf_common *p;
124126
struct nlattr *nest;
125127
int i = 0, n_i = 0;
128+
int ret = -EINVAL;
126129

127130
nest = nla_nest_start(skb, a->order);
128131
if (nest == NULL)
@@ -133,10 +136,12 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
133136
head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
134137
hlist_for_each_entry_safe(p, n, head, tcfc_head) {
135138
a->priv = p;
136-
if (ACT_P_DELETED == tcf_hash_release(a, 0)) {
139+
ret = tcf_hash_release(a, 0);
140+
if (ret == ACT_P_DELETED) {
137141
module_put(a->ops->owner);
138142
n_i++;
139-
}
143+
} else if (ret < 0)
144+
goto nla_put_failure;
140145
}
141146
}
142147
if (nla_put_u32(skb, TCA_FCNT, n_i))
@@ -146,7 +151,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
146151
return n_i;
147152
nla_put_failure:
148153
nla_nest_cancel(skb, nest);
149-
return -EINVAL;
154+
return ret;
150155
}
151156

152157
static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
@@ -401,16 +406,21 @@ int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
401406
}
402407
EXPORT_SYMBOL(tcf_action_exec);
403408

404-
void tcf_action_destroy(struct list_head *actions, int bind)
409+
int tcf_action_destroy(struct list_head *actions, int bind)
405410
{
406411
struct tc_action *a, *tmp;
412+
int ret = 0;
407413

408414
list_for_each_entry_safe(a, tmp, actions, list) {
409-
if (tcf_hash_release(a, bind) == ACT_P_DELETED)
415+
ret = tcf_hash_release(a, bind);
416+
if (ret == ACT_P_DELETED)
410417
module_put(a->ops->owner);
418+
else if (ret < 0)
419+
return ret;
411420
list_del(&a->list);
412421
kfree(a);
413422
}
423+
return ret;
414424
}
415425

416426
int
@@ -838,7 +848,11 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
838848
}
839849

840850
/* now do the delete */
841-
tcf_action_destroy(actions, 0);
851+
ret = tcf_action_destroy(actions, 0);
852+
if (ret < 0) {
853+
kfree_skb(skb);
854+
return ret;
855+
}
842856

843857
ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
844858
n->nlmsg_flags & NLM_F_ECHO);

0 commit comments

Comments
 (0)