From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.160.173 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794047344; b=u4R/wI8XU02TgXqTaPt/BNaL1hxIvj4jVVU2yKwtU7tLefMPJzI18YAQs/CGOFZE910R JQtm4ev6sUDhXMKQmzJziwdieJLo3cjBWT3uLIJdHu79gtqnbAyFnWUeuD2a4Bd8Os5W9 qs9Wf0re3pTzZl5QG0AAMxTgrGOvKn+sSp43UQg2FNVV4Yp/rPnS/TMqtHiWlx9glfwPU YT0LmmAUdbXTax71kbYx7EhUNFWoDW/XVfEXrAt1mqR8i906Ts8mDLQJ7dg3TaukPNeM5 CYvnPeUapWGoLbqpwUGUYfddvJjstLF2YVZvW8Ol/1cjhS2kyvC9HepPZa1gvvpbmew== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794047344; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Gm-Gg:X-Received:Received: Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:Content-Transfer-Encoding: In-Reply-To; bh=kPfxxEoDedkpzijCZq5OLG208Bd3QgI6noPt3uH0hgY=; b=eRMSEMISv0PH3kd7VcXe+3Wud+2GEwd+OL6aESqzKvkbLPUnKOaOwg8DJWxpc27ffcb1 4vZ6kQt1Fn3aelzatSvAUY9s+sC9tIPy1MqklijeDk9ZstoaQu0QxcTRGjcT5xrWrH4Dc 2gXRwvs2douyRTazgujISvHNtjENHx5OmRDMzH1gCk8rBbxEIaB3mj3E2s06+ZSqvuB8N NqE2gSkMmzPUSI9O+BlIg2SdR6BhVXTBRYOSIVJZVT/2Ya4dAbE6OwwH/eg8oqbbUIuTI F9MV2ONhsAAJC8u1x29a1isbWIZYXyXJk3K5iwhVR+56fwPqtXs6qXBenXv+wjLxy5g== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=openai.com; spf=pass smtp.mailfrom=openai.com; dkim=pass header.d=openai.com header.i=@openai.com header.a=rsa-sha256 header.s=google header.b=gU8fV7MN; arc=none smtp.remote-ip=209.85.160.173 Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F962606A339 for ; Sat, 7 Nov 2026 10:29:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 5F962606A339 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=openai.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=openai.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=openai.com header.i=@openai.com header.a=rsa-sha256 header.s=google header.b=gU8fV7MN Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-5495d549924so14396321cf.1 for ; Sat, 07 Nov 2026 02:29:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openai.com; s=google; t=1794047342; x=1794652142; darn=vger.kernel.org; h=in-reply-to:content-transfer-encoding:content-disposition :content-type:mime-version:references:message-id:subject:cc:to:from :date:from:to:cc:subject:date:message-id:reply-to:content-type; bh=kPfxxEoDedkpzijCZq5OLG208Bd3QgI6noPt3uH0hgY=; b=gU8fV7MN8HJRfR0yKPGughXHLXj/wm9K6t0J7Vdu8qZjnVIQY+xLkiocbpG0MrNr5c UJ/rhNua6yMK7CDQPNtNFEeztgoR6MjAAH8ImfZ2SueDr+PyiWGwpEjLxCZfuMOvmU6L 8i/27wDm8zx09wa5f2dtbZpPBiE2L9eSQ/XpY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794047342; x=1794652142; h=in-reply-to:content-transfer-encoding:content-disposition :content-type:mime-version:references:message-id:subject:cc:to:from :date:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=kPfxxEoDedkpzijCZq5OLG208Bd3QgI6noPt3uH0hgY=; b=vlua38pcgW8pSdKWhW49ROe14zuPr7ds/mMZ7XpFrv5MdKuHdcsV7MktwvgICeLuTI LgZY7lccCLIvre75pqr33gL4I9OPTgzji2f4gUolbDNmuiQyWulc+lIpK31QQQanD6kJ 5JrQ5G31YYaYM4uvR4u4IY17lzKSlkd4nhMumi2QPGh+sWvWw5Kqy+MbHhwKIomAieja Gs7ykJDp3iUhD5NA4nr8SaBOt8xOIR3fEtZKOAhxz3wIjm3z2cTGCj5PT/1Qro9XiB0I WlJtcRZriNurLEOg6DP+8C+TqxLV50RG/Ys6euwGtetur9gY1IrRkdf4IMzAA+07HOV5 77dQ== X-Forwarded-Encrypted: i=1; AKwUvBynKHN0gdzeTRp9SvbNig1WWssx1iEyoiYwgZh36qBJJwNmAMGT/b+DTGdIqsoLbn02cejj2CY=@vger.kernel.org X-Gm-Message-State: APuU4Z/Rpld55C4J1S/D1zFMxKdI74xOQq/MXOEcQ9UdHX+rSS4vngBx uOMPBl98E9vDmfqXlWe38WX9+aRKRGxKBZUiUanOXjCt4IJuLyi/TxwUZbUQ0+uU94A= X-Gm-Gg: AYBFou0bq7xMrmlwqcduztwAFPLUTr0yWRJJvSnL/fQh6PP+1jEweIRW9qoBFLkilzj AOlWK2s+z4TKrFJCcyt3YXTsIG8xLnleqAsS91Md5JOkhI8fQUXpd+S/D1+q1Xfhh3CDTpJrq+F hDU4MpEK4TAyCgNwPl7puY2YlarsVpj6ClaO5ZMcXN7S0F2RaePQvjTCfkEFZNmbiE4/NzDnAtT yckYeTQq9r7inK2mR0UY3+QuvA5059inG71saJ3txfXFY86HkPmPvjLG9VaO3WuZB4iUzJ6phPT VC2Jay70pU1KIYsYF8zYdy8mg8pCscPjfKSIsONfunkRDXT3LU/E1lsTV6zK/mnJdHI+sdK6X3u dLCAsINS00INbdsvhxqkuOznn/OS0wsasNouncOZZFaRdB0x+j7lfW1v4xWdMh4I6xXiD4O6g2G Il8JRN7WJwO47qBA8m48VMKBq5xWoKnpEbzXLOkbtaS+dbp7+Rkl+j1Aq10gM3Mu57/GCrM3bk9 ELyjpLSc5hDEG42s60aNYG28jr9iyGwGA2zzU9uq2pLhN3hOJOxOqymGNGdEztGlXskW7nLw6wi dVqA0/rOE/0BrOTyIU5JK71eECfk2gvNTjk6ZL2OjQPwQ26ik3LfNFUUBCsWPvn3+9rkLG42WrY t/KNEsv4= X-Received: by 2002:a05:622a:2508:b0:537:dea7:adb1 with SMTP id d75a77b69052e-54e115b4283mr77969511cf.4.1794047342290; Sat, 07 Nov 2026 02:29:02 -0800 (PST) Received: from com-75606 ([199.47.143.1]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-54e2625abafsm43098871cf.16.2026.11.07.02.29.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Nov 2026 02:29:02 -0800 (PST) Date: Sat, 7 Nov 2026 02:28:58 -0800 From: Kyle Zeng To: Florian Westphal Cc: netfilter-devel@vger.kernel.org, Pablo Neira Ayuso , coreteam@netfilter.org, bridge@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, outbounddisclosures@openai.com Subject: Re: [PATCH] netfilter: br_netfilter: reject unsafe neighbour devices for DNAT Message-ID: References: <20261030042155.73844-1-kylebot@openai.com> X-Mailing-List: netdev@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: On Sat, Nov 07, 2026 at 08:25:41AM +0100, Florian Westphal wrote: > Kyle Zeng wrote: > > The IPv4 and IPv6 bridge prerouting callbacks classify DNAT traffic using > > the logical input device saved in skb->dev. The physical input port can > > have a different bridge master when prerouting resumes, for example after > > an NFQUEUE verdict. Netfilter reassembly can also combine the first > > fragment's bridge information with a different fragment's input device. > > > > br_nf_pre_routing_finish_bridge() replaces skb->dev with the port's > > current bridge master, but looks up the neighbour using the existing > > route. This can put an skb with skb->dev pointing to bridge B on an > > unresolved neighbour of bridge A. Deleting B and resolving the neighbour > > on A then causes a use-after-free in __dev_queue_xmit(). > > > > Before calling the neighbour output method, check that the neighbour > > keeps skb->dev alive. A neighbour holds its device, and a VLAN device > > also holds its real device, so allow a VLAN whose real device is the > > bridge. Release the neighbour and drop the skb on a mismatch. > > > > Doing this in the shared continuation covers both protocol families, > > including a queue in the remaining bridge prerouting hooks. Leave the > > cached-header path unchanged since it does not enqueue the skb. > > > > Signed-off-by: Kyle Zeng > > --- > > I have a reproducer for this issue and can share via DM > > > > net/bridge/br_netfilter_hooks.c | 12 ++++++++++++ > > 1 file changed, 12 insertions(+) > > > > diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c > > index e15355ff215a..726a2d17ed3a 100644 > > --- a/net/bridge/br_netfilter_hooks.c > > +++ b/net/bridge/br_netfilter_hooks.c > > @@ -307,6 +307,18 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ > > > > ret = br_handle_frame_finish(net, sk, skb); > > } else { > > + struct net_device *dev = neigh->dev; > > + > > + /* The neighbour queue must keep skb->dev alive. A VLAN > > + * device also holds a reference to its real device. > > + */ > > + if (is_vlan_dev(dev)) > > + dev = vlan_dev_real_dev(dev); > > + if (dev != skb->dev) { > > + neigh_release(neigh); > > + goto free_skb; > > + } > > + > > I don't understand the vlan check. Why is that needed? > The call to br_nf_pre_routing_finish_bridge is gated via: > > 405 if (skb_dst(skb)->dev == dev) { > 406 skb->dev = br_indev; > 407 nf_bridge_update_protocol(skb); > 408 nf_bridge_push_encap_header(skb); > 409 br_nf_hook_thresh(NF_BR_PRE_ROUTING, > 410 net, sk, skb, skb->dev, > 411 NULL, > 412 br_nf_pre_routing_finish_bridge); > > > ... so this patch ought to be sufficient? > > --- a/net/bridge/br_netfilter_hooks.c > +++ b/net/bridge/br_netfilter_hooks.c > @@ -283,6 +283,10 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ > if (!skb->dev) > goto free_skb; > dst = skb_dst(skb); > + > + if (dst->dev != skb->dev) > + goto free_skb; > + > neigh = dst_neigh_lookup_skb(dst, skb); > > (I can't see how neigh->dev != skb->dev after the extra test). The VLAN check is intended to preserve existing VLAN DNAT behavior. bridge-nf-filter-vlan-tagged=1, bridge-nf-pass-vlan-input-dev=1, and br0.100, the earlier test can pass with dst->dev == dev == br0.100. The continuation then changes skb->dev to br0, so the strict comparison would drop that valid packet. A neighbour on br0.100 is safe here because it holds the VLAN device, which holds its underlying bridge. That is why the slow-path check compares the neighbour´s underlying device with skb->dev.