From: Jun Yang br_nd_send() calls LL_RESERVED_SPACE(dev) once to size the reply skb and again to reserve its headroom. When a port requiring more headroom is added to the bridge, br_add_if() can increase dev->needed_headroom between the two calls. The reserved headroom can then exceed the space accounted for by alloc_skb(). Take one headroom snapshot and use it for both the allocation size and skb_reserve(). Fixes: ed842faeb2bd ("bridge: suppress nd pkts on BR_NEIGH_SUPPRESS ports") Cc: stable@kernel.org Reported-by: TencentOS Corvus AI Assisted-by: tencentos-corvus-ai:hy4-preview Signed-off-by: Jun Yang --- A KASAN reproducer for this issue is available if requested. net/bridge/br_arp_nd_proxy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c index 87a40e2f1c50..985ed43f7e30 100644 --- a/net/bridge/br_arp_nd_proxy.c +++ b/net/bridge/br_arp_nd_proxy.c @@ -262,6 +262,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p, struct sk_buff *reply; struct ipv6hdr *pip6; int na_olen = 8; /* opt hdr + ETH_ALEN for target */ + int headroom; int ns_olen; u8 *daddr; bool dad; @@ -271,7 +272,8 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p, if (!dev) return; - len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) + + headroom = LL_RESERVED_SPACE(dev); + len = headroom + sizeof(struct ipv6hdr) + sizeof(*na) + na_olen + dev->needed_tailroom; reply = alloc_skb(len, GFP_ATOMIC); @@ -280,7 +282,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p, reply->protocol = htons(ETH_P_IPV6); reply->dev = dev; - skb_reserve(reply, LL_RESERVED_SPACE(dev)); + skb_reserve(reply, headroom); skb_push(reply, sizeof(struct ethhdr)); skb_set_mac_header(reply, 0); base-commit: ffdf678dd16610e3f006dac904bd37c09684673c -- 2.54.0 (Apple Git-157)