From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793212661; b=KNaHj45hMkAv00bdrszeKoY+8TPVr45r0NWzVqRjoo0Q1WqbTb96jPJzHYA/PC96i1YL cCE2/YCVPnHgdDXaWs0YI35bzHeaQCb3fDcsLDTSnU1FDWp+khpBGegSVGUmsA6Rd6eZ8 MFoBKYMJiu1rRsxzYxWQTxgpyaBVTLAEIWF9JWWM7dOQVfBGhGfxN/30DEf6kBTkxegC8 RJ7qyzpWqVR9RkFpHBGFgbCCvw654MaqsfBGPRJFJtPUFyJ1V3R/ls7AJGuwSsyqZ5V8b kh/OZKAeFodX/jz09lnQc4yCVtaEOz+US9Gr5Y55Fd3L2BDI13gp3bLqvIb6GyB7RWw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793212661; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=Nme9YB+MKGzqQHURsOOl3aL6rJF77KJlrphQ4dNPT/o=; b=HPMZYpF4rDnbwE4WFbxYoD2Ii08zbP2PaWwGlTWXNs0TaknKKyoomuB434RrXDIgDhgR QFVsEmmU0ZWOiYdzBM0DLOylXlqTd4naUDun2y9CLWNl1G8Yaz0L4DCRFAd3ekVzxYP70 w3wZ+MlJhEb6HYo9sKjzjyj0qW5b8LY/1oCJNfO7p+8e9AIAsQm0BeuMGGimty4Ek58/A i2W3azn9Gs5ZWWY1vItp+gGxlZ/o0h6UPN+5bGd0HNMLtB7oL77Np9+XYMODAhDXcLvMw A1phPBdVMc5mik6fMu88SlvDuw7wpVhZ0NIduyLEiVQdjS64sPKWT4SgZtakH6i95fQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=ijcJpC6h; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C10FA606A31C; Wed, 28 Oct 2026 18:37:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key, unprotected) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=ijcJpC6h Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1E6971F01825; Wed, 28 Oct 2026 18:37:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1793212660; bh=Nme9YB+MKGzqQHURsOOl3aL6rJF77KJlrphQ4dNPT/o=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ijcJpC6h4afGCi4RV86R1pmVtejMd/n2fT1p5HEuZgG4f+/Vd2jOw8Nw2DFIJUwSJ 16ugw3BzMpQdNWMOwStvy6mrm1Uu9jfEYwJ1DxiblDsIaWYLmAhoqYAl0NG191+b4L /GwrYPuisrTcjRdKWt8wlmPtwwTl4QfHyI8hl4T0= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, "Sashiko (nipa)" , Jamal Hadi Salim , Simon Horman , Jakub Kicinski , Sasha Levin Subject: [PATCH 6.1 0231/1887] net/sched: cls_api: reclaim an empty proto on the error path Date: Wed, 28 Oct 2026 17:38:47 +0100 Message-ID: <20261028170504.488179481@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261028170459.200466217@linuxfoundation.org> References: <20261028170459.200466217@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: patches@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.1-stable review patch. If anyone has any objections, please let me know. ------------------ From: Jamal Hadi Salim [ Upstream commit 0bb8eab29b55045281a4963d4557f2776cdf8cfa ] Two racing tc filter add requests on the same chain/prio of an unlocked classifier both run change() on the shared proto and both can fail: the winner's tcf_chain_tp_delete_empty() attempt gives up because the loser's handle is still in the idr, and the loser's error path drops only its own reference without a second reclamation attempt. The empty proto stays linked in the chain, holding the chain reference, a block reference and the classifier module reference until the chain or block is torn down. Reclaim the proto on the error path of any failed request that holds a proto reference. The reclamation is emptiness-gated: tcf_chain_tp_delete_empty() unlinks the proto only when delete_empty() admits it is empty, so a live shared proto is never unlinked. A proto the request created is reclaimed unconditionally - it is the only owner, so marking it for deletion is safe even without a delete_empty callback. Classifiers without one (the check marks the proto unconditionally) are rtnl-serialized, so the raced window this guard closes cannot arise for them. This is a follow-up to commit d4e359b3608a ("net/sched: cls_api: fix teardown of an adopted proto on insert-race loss"), which stopped the loser of the insert race from unlinking the winner's live proto but left the empty-proto residual in place. Conditions to recreate: - CONFIG_NET_CLS_FLOWER=y; veth pair - tc qdisc add dev veth0 ingress - two concurrent `tc filter add dev veth0 ingress protocol ip pref 1 flower skip_sw ... action drop` (both fail in fl_hw_replace_filter after publishing their handle in the idr); repeat in a loop - an empty flower tp stays linked after both requests fail; visible as a bare `filter protocol ip pref 1 flower chain 0` header in `tc filter show` with no filter entries - CAP_NET_ADMIN (namespace-local via unshare -Urn suffices) Fixes: 8b64678e0af8 ("net: sched: refactor tp insert/delete for concurrent execution") Reported-by: Sashiko (nipa) Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260805134049.927864-1-victor@mojatatu.com Signed-off-by: Jamal Hadi Salim Reviewed-by: Simon Horman Link: https://patch.msgid.link/QDISC-JCOT.v1.20260910090924@mojatatu.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/sched/cls_api.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 341128a00420c..dbaf6e72aa2da 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -2211,7 +2211,20 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, } errout: - if (err && tp_state == TP_CREATED) + if (err && !IS_ERR_OR_NULL(tp) && + (tp_state == TP_CREATED || tp->ops->delete_empty)) + /* + * The request is dropping its reference to tp. If it was + * the last user (the idr is empty now), reclaim the proto. + * A tp this request created is reclaimed unconditionally: + * it is the only owner, so marking it for deletion is + * safe. Otherwise only classifiers with a delete_empty + * callback are reclaimed -- the callback admits an empty + * proto only, so a live shared proto is never unlinked. + * Classifiers without one (deleting is set + * unconditionally) are rtnl-serialized, so the raced + * window this guard closes cannot arise for them. + */ tcf_chain_tp_delete_empty(chain, tp, rtnl_held, NULL); errout_tp: if (chain) { -- 2.53.0