Re: [PATCH net v2] vxlan: keep the last remote linked during FDB flush

Ido Schimmel <[email protected]>
Newsgroups org.kernel.vger.stable,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <20260805131654.GA1489442@shredder>
On Tue, Aug 04, 2026 at 06:09:58AM +0000, David Lee wrote:
> From: Kyle Zeng <[email protected]>
> 
> A non-nexthop FDB entry is expected to have at least one remote while it
> remains reachable through the FDB hash table. A filtered bulk flush
> violates this invariant when every remote matches: It unlinks the last
> remote in vxlan_fdb_dst_destroy() and only afterwards tells vxlan_flush()
> to destroy the parent FDB entry.
> 
> An RCU reader can find the parent during this interval.
> first_remote_rcu() then applies list_entry_rcu() to the empty list head,
> producing an invalid remote pointer that the receive learning path can
> read from and write to.
> 
> When a matching remote is the sole remaining remote, leave it linked and
> ask the caller to destroy the entire FDB entry. vxlan_fdb_destroy() keeps
> the remote attached while sending the deletion notification and removing
> the parent from the lookup structures.
> 
> Fixes: c499fccb71cb ("vxlan: vxlan_core: Support FDB flushing by destination VNI")
> Cc: [email protected]
> Assisted-by: Codex:gpt-5.6-sol Codex:gpt-5.5-cyber
> Signed-off-by: Kyle Zeng <[email protected]>
> Co-developed-by: David Lee <[email protected]>
> Signed-off-by: David Lee <[email protected]>
> ---
> Changes in v2:
> - Add the net tree prefix to the subject.
> - Restore Kyle Zeng as the patch author and correct the sign-off chain.
> - Move the research credit below the commit-message separator.
> - Add the recipients reported by netdev CI.
> 
> v1: https://lore.kernel.org/all/[email protected]/
> 
> Bug found and triaged by OpenAI Security Research and
> validated by Trail of Bits.
> 
> Trail of Bits has a reproducer for this bug that triggers a
> KASAN slab-out-of-bounds read in vxlan_snoop() and can share if needed.
> 
>  drivers/net/vxlan/vxlan_core.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
> index d834a4865..a00df127d 100644
> --- a/drivers/net/vxlan/vxlan_core.c
> +++ b/drivers/net/vxlan/vxlan_core.c
> @@ -3058,6 +3058,11 @@ vxlan_fdb_flush_match_remotes(struct vxlan_fdb *f, struct vxlan_dev *vxlan,
>  		if (!vxlan_fdb_flush_remote_matches(desc, rd))
>  			continue;
>  
> +		if (list_is_singular(&f->remotes)) {
> +			*p_destroy_fdb = true;
> +			return;
> +		}
> +
>  		vxlan_fdb_dst_destroy(vxlan, f, rd, true);
>  		remotes_flushed = true;
>  	}

Can you squash the below into v3?

'*p_destroy_fdb' at the end is always false and it's initialized as such
by the caller, so we can remove this line and 'remotes_flushed'.

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 117fae9c05a4..0f686bcc5a20 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3058,7 +3058,6 @@ vxlan_fdb_flush_match_remotes(struct vxlan_fdb *f, struct vxlan_dev *vxlan,
 			      const struct vxlan_fdb_flush_desc *desc,
 			      bool *p_destroy_fdb)
 {
-	bool remotes_flushed = false;
 	struct vxlan_rdst *rd, *tmp;
 
 	list_for_each_entry_safe(rd, tmp, &f->remotes, list) {
@@ -3071,10 +3070,7 @@ vxlan_fdb_flush_match_remotes(struct vxlan_fdb *f, struct vxlan_dev *vxlan,
 		}
 
 		vxlan_fdb_dst_destroy(vxlan, f, rd, true);
-		remotes_flushed = true;
 	}
-
-	*p_destroy_fdb = remotes_flushed && list_empty(&f->remotes);
 }
 
 /* Purge the forwarding table */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.