Netdev List
 help / color / mirror / Atom feed
* [PATCH] net: flow_offload: clean up indirect flow block on bind failure
@ 2026-07-17 19:44 Shuangpeng Bai
  0 siblings, 0 replies; only message in thread
From: Shuangpeng Bai @ 2026-07-17 19:44 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni
  Cc: horms, elic, jiri, netdev, linux-kernel, Shuangpeng Bai, stable

flow_indr_dev_setup_offload() records FLOW_BLOCK_BIND requests in
flow_indir_dev_list before it calls registered indirect providers. When no
registered provider binds the block, it returns -EOPNOTSUPP. The replay
entry is left behind.

One affected path is nftables netdev offload. A netdev base chain on a
device without ndo_setup_tc can take the indirect path if an indirect
provider is registered. If none of the registered providers binds the
block, the operation fails with -EOPNOTSUPP.

The failed NEWCHAIN transaction can then abort and free the nft_base_chain,
while the replay entry still points at that basechain and its flow_block
cb_list. If another provider is registered later, the stale entry is
replayed, potentially passing freed data to the provider callback or
splicing callback entries into freed memory.

Use the return value of indir_dev_add() only to track ownership of the
replay entry. Preserve the existing behavior of not propagating -EEXIST
or -ENOMEM. If this invocation inserted an entry, remove it again when
the bind fails.

Fixes: 74fc4f828769 ("net: Fix offloading indirect devices dependency on qdisc order creation")

Cc: stable@vger.kernel.org
Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
---
 net/core/flow_offload.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index 5071d7fe6ce2..5fbb1ae4679d 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -606,15 +606,20 @@ int flow_indr_dev_setup_offload(struct net_device *dev,	struct Qdisc *sch,
 				void (*cleanup)(struct flow_block_cb *block_cb))
 {
 	struct flow_indr_dev *this;
+	bool replay_added = false;
 	u32 count = 0;
 	int err;
 
 	mutex_lock(&flow_indr_block_lock);
 	if (bo) {
-		if (bo->command == FLOW_BLOCK_BIND)
-			indir_dev_add(data, dev, sch, type, cleanup, bo);
-		else if (bo->command == FLOW_BLOCK_UNBIND)
+		if (bo->command == FLOW_BLOCK_BIND) {
+			int add_err;
+
+			add_err = indir_dev_add(data, dev, sch, type, cleanup, bo);
+			replay_added = add_err == 0;
+		} else if (bo->command == FLOW_BLOCK_UNBIND) {
 			indir_dev_remove(data);
+		}
 	}
 
 	list_for_each_entry(this, &flow_block_indr_dev_list, list) {
@@ -623,9 +628,17 @@ int flow_indr_dev_setup_offload(struct net_device *dev,	struct Qdisc *sch,
 			count++;
 	}
 
+	if (bo && list_empty(&bo->cb_list)) {
+		if (replay_added)
+			indir_dev_remove(data);
+		err = -EOPNOTSUPP;
+	} else {
+		err = count;
+	}
+
 	mutex_unlock(&flow_indr_block_lock);
 
-	return (bo && list_empty(&bo->cb_list)) ? -EOPNOTSUPP : count;
+	return err;
 }
 EXPORT_SYMBOL(flow_indr_dev_setup_offload);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-07-17 19:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-17 19:44 [PATCH] net: flow_offload: clean up indirect flow block on bind failure Shuangpeng Bai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox