mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 23:50:02 +02:00
bridge: Validate NS/NA messages using ndisc_check_ns_na()
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> Link: https://patch.msgid.link/20260803112505.613873-4-danieller@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
9dfa6cca89
commit
18668f4747
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user