Skip to content

Commit ed303cc

Browse files
vbnogueiragregkh
authored andcommitted
net/sched: act_api: Notify user space if any actions were flushed before error
commit 76b39b9 upstream. If during an action flush operation one of the actions is still being referenced, the flush operation is aborted and the kernel returns to user space with an error. However, if the kernel was able to flush, for example, 3 actions and failed on the fourth, the kernel will not notify user space that it deleted 3 actions before failing. This patch fixes that behaviour by notifying user space of how many actions were deleted before flush failed and by setting extack with a message describing what happened. Fixes: 55334a5 ("net_sched: act: refuse to remove bound action outside") Signed-off-by: Victor Nogueira <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1d776f0 commit ed303cc

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

net/sched/act_api.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ static int tcf_idr_release_unsafe(struct tc_action *p)
350350
}
351351

352352
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
353-
const struct tc_action_ops *ops)
353+
const struct tc_action_ops *ops,
354+
struct netlink_ext_ack *extack)
354355
{
355356
struct nlattr *nest;
356357
int n_i = 0;
@@ -366,20 +367,25 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
366367
if (nla_put_string(skb, TCA_KIND, ops->kind))
367368
goto nla_put_failure;
368369

370+
ret = 0;
369371
mutex_lock(&idrinfo->lock);
370372
idr_for_each_entry_ul(idr, p, tmp, id) {
371373
if (IS_ERR(p))
372374
continue;
373375
ret = tcf_idr_release_unsafe(p);
374-
if (ret == ACT_P_DELETED) {
376+
if (ret == ACT_P_DELETED)
375377
module_put(ops->owner);
376-
n_i++;
377-
} else if (ret < 0) {
378-
mutex_unlock(&idrinfo->lock);
379-
goto nla_put_failure;
380-
}
378+
else if (ret < 0)
379+
break;
380+
n_i++;
381381
}
382382
mutex_unlock(&idrinfo->lock);
383+
if (ret < 0) {
384+
if (n_i)
385+
NL_SET_ERR_MSG(extack, "Unable to flush all TC actions");
386+
else
387+
goto nla_put_failure;
388+
}
383389

384390
ret = nla_put_u32(skb, TCA_FCNT, n_i);
385391
if (ret)
@@ -400,7 +406,7 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
400406
struct tcf_idrinfo *idrinfo = tn->idrinfo;
401407

402408
if (type == RTM_DELACTION) {
403-
return tcf_del_walker(idrinfo, skb, ops);
409+
return tcf_del_walker(idrinfo, skb, ops, extack);
404410
} else if (type == RTM_GETACTION) {
405411
return tcf_dump_walker(idrinfo, skb, cb);
406412
} else {

0 commit comments

Comments
 (0)