From: Danielle Ratson <danieller@nvidia.com>
To: <netdev@vger.kernel.org>
Cc: <dsahern@kernel.org>, <idosch@nvidia.com>, <davem@davemloft.net>,
<edumazet@google.com>, <kuba@kernel.org>, <pabeni@redhat.com>,
<horms@kernel.org>, <razor@blackwall.org>, <ja@ssi.bg>,
<petrm@nvidia.com>, <fw@strlen.de>, <kuniyu@google.com>,
<bridge@lists.linux.dev>, <linux-kernel@vger.kernel.org>,
Danielle Ratson <danieller@nvidia.com>
Subject: [PATCH net-next v2 3/5] bridge: Validate NS/NA messages using ndisc_check_ns_na()
Date: Mon, 3 Aug 2026 14:25:03 +0300 [thread overview]
Message-ID: <20260803112505.613873-4-danieller@nvidia.com> (raw)
In-Reply-To: <20260803112505.613873-1-danieller@nvidia.com>
The bridge performs neighbor suppression by snooping NS/NA messages, but
previously only checked the ICMPv6 type and code. This leaves it open to
acting on malformed or spoofed packets that any RFC-compliant node should
reject.
Wire br_is_nd_neigh_msg() into the new ndisc_check_ns_na() helper, which
enforces the full RFC 4861 section 7.1.1/7.1.2 receive validation:
hop limit of 255, valid checksum, correct code, and type-specific rules
(NS target not multicast; NA solicited flag clear for multicast
destinations).
MLD messages are already validated by ipv6_mc_check_mld() before the
bridge acts on them; this brings NS/NA to the same standard.
As a side effect, the skb parameter of br_is_nd_neigh_msg() changes from
const to non-const, since ndisc_check_ns_na() may reallocate the skb head
via pskb_may_pull() and sets the transport header. The returned pointer is
now derived from skb_transport_header() rather than a direct cast.
Reviewed-by: Petr Machata <petrm@nvidia.com>
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: Danielle Ratson <danieller@nvidia.com>
---
net/bridge/br_arp_nd_proxy.c | 11 ++++-------
net/bridge/br_private.h | 2 +-
2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index db08c3272001..445c930ed59b 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -19,6 +19,7 @@
#include <net/addrconf.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ip6_checksum.h>
+#include <net/ndisc.h>
#endif
#include "br_private.h"
@@ -234,16 +235,12 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
#endif
#if IS_ENABLED(CONFIG_IPV6)
-struct nd_msg *br_is_nd_neigh_msg(const struct sk_buff *skb)
+struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb)
{
- struct nd_msg *m = (struct nd_msg *)(ipv6_hdr(skb) + 1);
-
- if (m->icmph.icmp6_code != 0 ||
- (m->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION &&
- m->icmph.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT))
+ if (ndisc_check_ns_na(skb))
return NULL;
- return m;
+ return (struct nd_msg *)skb_transport_header(skb);
}
static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e31439cb4420..d337b1cfb980 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -2367,7 +2367,7 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p);
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
-struct nd_msg *br_is_nd_neigh_msg(const struct sk_buff *skb);
+struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb);
bool br_is_neigh_suppress_enabled(const struct net_bridge_port *p, u16 vid);
bool br_is_neigh_forward_grat_enabled(const struct net_bridge_port *p, u16 vid);
#endif
--
2.54.0
next prev parent reply other threads:[~2026-08-03 11:26 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-03 11:25 [PATCH net-next v2 0/5] bridge: Validate and clean up IPv6 neighbour suppression Danielle Ratson
2026-08-03 11:25 ` [PATCH net-next v2 1/5] bridge: Use direct pointer in br_is_nd_neigh_msg() Danielle Ratson
2026-08-05 8:06 ` Danielle Ratson
2026-08-03 11:25 ` [PATCH net-next v2 2/5] ipv6: ndisc: Add ndisc_check_ns_na() validation helper Danielle Ratson
2026-08-05 8:06 ` Danielle Ratson
2026-08-03 11:25 ` Danielle Ratson [this message]
2026-08-03 11:25 ` [PATCH net-next v2 4/5] bridge: Linearize skb once the ND message type is validated Danielle Ratson
2026-08-03 15:25 ` Nikolay Aleksandrov
2026-08-03 11:25 ` [PATCH net-next v2 5/5] bridge: Use ndisc_parse_options() to parse ND options in br_nd_send() Danielle Ratson
2026-08-05 8:07 ` Danielle Ratson
2026-08-07 23:40 ` [PATCH net-next v2 0/5] bridge: Validate and clean up IPv6 neighbour suppression patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260803112505.613873-4-danieller@nvidia.com \
--to=danieller@nvidia.com \
--cc=bridge@lists.linux.dev \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=ja@ssi.bg \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=petrm@nvidia.com \
--cc=razor@blackwall.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.