Re: [PATCH net-next v2 4/5] bridge: Linearize skb once the ND message type is validated

Nikolay Aleksandrov <[email protected]>
Newsgroups gmane.linux.network.bridge,gmane.linux.network,gmane.linux.kernel
Message-ID <anCy4eCZAbz3Tv4u@penguin>
On Mon, Aug 03, 2026 at 02:25:04PM +0300, Danielle Ratson wrote:
> br_nd_send() parses ND options from ns->opt[] and therefore needs the skb
> to be linear. Commit a01aee7cafc5 ("bridge: br_nd_send: linearize skb
> before parsing ND options") ensured that by linearizing inside
> br_nd_send() itself.
> 
> Move the linearization up into br_is_nd_neigh_msg(), right after
> ndisc_check_ns_na() has validated the message as an NS/NA. This makes a
> linear buffer a property of every recognized ND message, so that this and
> any future ND message handling operate on a linear skb and cannot
> reintroduce that class of bug by forgetting to linearize.
> 
> Since the skb is now linear by the time br_nd_send() runs, drop the
> linearization there and derive ns from the transport header set by
> ndisc_check_ns_na(), instead of recomputing it from the network header.
> 
> If linearization fails under memory pressure, br_is_nd_neigh_msg() returns
> NULL and the packet falls back to normal forwarding rather than being
> suppressed.
> 
> Reviewed-by: Petr Machata <[email protected]>
> Signed-off-by: Danielle Ratson <[email protected]>
> ---
> 
> Notes:
>     v2:
>     	* Add a comment noting that br_is_nd_neigh_msg() also linearizes the
>     	  skb.
> 
>  net/bridge/br_arp_nd_proxy.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
> index 445c930ed59b..6b6de0eff38c 100644
> --- a/net/bridge/br_arp_nd_proxy.c
> +++ b/net/bridge/br_arp_nd_proxy.c
> @@ -235,11 +235,17 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
>  #endif
>  
>  #if IS_ENABLED(CONFIG_IPV6)
> +/* Validate skb as an NS/NA and linearize it for br_nd_send()'s ND
> + * option parsing; returns the nd_msg, or NULL on failure.
> + */
>  struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb)
>  {
>  	if (ndisc_check_ns_na(skb))
>  		return NULL;
>  
> +	if (skb_linearize(skb))
> +		return NULL;
> +
>  	return (struct nd_msg *)skb_transport_header(skb);
>  }
>  
> @@ -259,7 +265,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p,
>  	bool dad;
>  	u16 pvid;
>  
> -	if (!dev || skb_linearize(request))
> +	if (!dev)
>  		return;
>  
>  	len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
> @@ -276,8 +282,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p,
>  	skb_set_mac_header(reply, 0);
>  
>  	daddr = eth_hdr(request)->h_source;
> -	ns = (struct nd_msg *)(skb_network_header(request) +
> -			       sizeof(struct ipv6hdr));
> +	ns = (struct nd_msg *)skb_transport_header(request);
>  
>  	/* Do we need option processing ? */
>  	ns_olen = request->len - (skb_network_offset(request) +
> -- 
> 2.54.0
> 

Thanks,
Acked-by: Nikolay Aleksandrov <[email protected]>
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.