Thread (3 messages) read the whole thread 3 messages, 2 authors, 5d ago
COOLING5d

[PATCH net 1/1] net: openvswitch: reject mismatched flow IDs

From: Ren Wei <hidden>
Date: 2026-07-27 16:52:32
Subsystem: networking [general], openvswitch, the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Aaron Conole, Eelco Chaudron, Ilya Maximets, Linus Torvalds

From: Zhiling Zou <redacted>

ovs_flow_cmd_new() looks for a duplicate flow before deciding whether the
request should insert a new flow or update an existing one.  When the new
request carries a UFID, the function first looks up the UFID, but falls
back to a key lookup if the UFID is not found.

That fallback can find a flow which is identified by a different UFID, or
by its key.  The update path then replaces that flow's actions even
though the request identified a different flow.  If the caller asked for
an echoed notification, the reply skb was already sized from the request
identifier, but ovs_flow_cmd_fill_info() serializes the matched flow's
identifier.  A short request UFID can therefore make the fill fail with
-EMSGSIZE and hit the BUG_ON() in the update path.

Track whether the matched flow was found by the same identifier as the
request, and reject updates where the identifier does not match.  This
keeps OVS_FLOW_CMD_NEW from retargeting a different flow and avoids
building a reply for an identifier that the skb was not sized for.

Fixes: 74ed7ab9264c ("openvswitch: Add support for unique flow IDs.")
Cc: stable@vger.kernel.org
Reported-by: Vega <redacted>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zhiling Zou <redacted>
Signed-off-by: Ren Wei <redacted>
---
 net/openvswitch/datapath.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index eaf332b156d73..1637420f854d5 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1010,6 +1010,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
 	u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
 	int error;
 	bool log = !a[OVS_FLOW_ATTR_PROBE];
+	bool id_match = false;
 
 	/* Must have key and actions. */
 	error = -EINVAL;
@@ -1075,10 +1076,17 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	/* Check if this is a duplicate flow */
-	if (ovs_identifier_is_ufid(&new_flow->id))
+	if (ovs_identifier_is_ufid(&new_flow->id)) {
 		flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);
-	if (!flow)
+		if (flow)
+			id_match = true;
+	}
+	if (!flow) {
 		flow = ovs_flow_tbl_lookup(&dp->table, key);
+		if (flow)
+			id_match = ovs_identifier_is_key(&new_flow->id) &&
+				   ovs_identifier_is_key(&flow->id);
+	}
 	if (likely(!flow)) {
 		rcu_assign_pointer(new_flow->sf_acts, acts);
 
@@ -1113,9 +1121,12 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
 			error = -EEXIST;
 			goto err_unlock_ovs;
 		}
-		/* The flow identifier has to be the same for flow updates.
-		 * Look for any overlapping flow.
-		 */
+		/* The flow identifier has to be the same for flow updates. */
+		if (unlikely(!id_match)) {
+			error = -ENOENT;
+			goto err_unlock_ovs;
+		}
+		/* Look for any overlapping flow. */
 		if (unlikely(!ovs_flow_cmp(flow, &match))) {
 			if (ovs_identifier_is_key(&flow->id))
 				flow = ovs_flow_tbl_lookup_exact(&dp->table,
-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help