Commit 478eb5abb519 for kernel

commit 478eb5abb51931a152abab068f8a717b7ff480fd
Author: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Date:   Wed Sep 9 15:03:35 2026 +0800

    net/sched: act_api: release all action references on NEWACTION failure

    When a batched RTM_NEWACTION request replaces an existing action,
    tcf_idr_check_alloc() takes a temporary reference on it. If a later
    action fails to initialize, tcf_action_destroy() uses strict release
    semantics to clean up the actions initialized so far. For an action
    bound to a filter, the strict check returns -EPERM without dropping
    the temporary reference.

    This error also makes tcf_action_destroy() return before releasing
    subsequent entries. Any new action initialized between the bound
    action and the failing entry is leaked together with its reserved
    IDR slot, preventing reuse of its index.

    Use tcf_idr_release() to drop each reference held by the batch without
    rejecting bound actions. This allows cleanup to continue through all
    initialized entries and preserves the module reference release when
    an action is destroyed. Explicit action deletion and flushing retain
    their separate bind-count checks.

    Fixes: 55334a5db5cd ("net_sched: act: refuse to remove bound action outside")
    Cc: stable@vger.kernel.org
    Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
    Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
    Link: https://patch.msgid.link/20260909070336.32979-2-xuanqiang.luo@linux.dev
    Signed-off-by: Jakub Kicinski <kuba@kernel.org>

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 37eced84dfa5..19501dc99464 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -1200,18 +1200,13 @@ EXPORT_SYMBOL(tcf_action_exec);

 int tcf_action_destroy(struct tc_action *actions[], int bind)
 {
-	const struct tc_action_ops *ops;
 	struct tc_action *a;
 	int ret = 0, i;

 	tcf_act_for_each_action(i, a, actions) {
 		actions[i] = NULL;
-		ops = a->ops;
-		ret = __tcf_idr_release(a, bind, true);
-		if (ret == ACT_P_DELETED)
-			module_put(ops->owner);
-		else if (ret < 0)
-			return ret;
+		/* Drop our reference even if the action is still bound to a filter. */
+		ret = tcf_idr_release(a, bind);
 	}
 	return ret;
 }