[PATCH OLK-6.6] net: bridge: arp/nd proxy: fix reading neigh ha
From: Nikolay Aleksandrov <razor@blackwall.org> mainline inclusion from mainline-v7.3-rc1 commit 57549ab9079122991dfa0f8248ca00e101e8e69b category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19399 CVE: CVE-2026-90106 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Currently neigh ha address is read directly, but that can result in torn/partial reads if the neigh is being updated. Use neigh_ha_snapshot to take a stable snapshot of the address. Fixes: 057658cb33fb ("bridge: suppress arp pkts on BR_NEIGH_SUPPRESS ports") Fixes: ed842faeb2bd ("bridge: suppress nd pkts on BR_NEIGH_SUPPRESS ports") Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org> Reviewed-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260818150756.890025-2-razor@blackwall.org Signed-off-by: Jakub Kicinski <kuba@kernel.org> Conflicts: net/bridge/br_arp_nd_proxy.c [Context differences are due to the following patches not being merged: fee1fc1d5a54 ("bridge: Do not suppress ARP probes and DAD NS unconditionally")] Signed-off-by: JiangJieHua <jiangjiehua1@huawei.com> --- net/bridge/br_arp_nd_proxy.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c index 985aaf7ff1564..5aac37ed4f608 100644 --- a/net/bridge/br_arp_nd_proxy.c +++ b/net/bridge/br_arp_nd_proxy.c @@ -191,13 +191,15 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br, n = neigh_lookup(&arp_tbl, &tip, vlandev); if (n) { struct net_bridge_fdb_entry *f; + u8 ha[ETH_ALEN] __aligned(2); if (!(READ_ONCE(n->nud_state) & NUD_VALID)) { neigh_release(n); return; } - f = br_fdb_find_rcu(br, n->ha, vid); + neigh_ha_snapshot(ha, n, n->dev); + f = br_fdb_find_rcu(br, ha, vid); if (f) { const struct net_bridge_port *dst = READ_ONCE(f->dst); bool replied = false; @@ -207,10 +209,10 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br, br_is_neigh_suppress_enabled(dst, vid)) { if (!vid) br_arp_send(br, p, skb->dev, sip, tip, - sha, n->ha, sha, 0, 0); + sha, ha, sha, 0, 0); else br_arp_send(br, p, skb->dev, sip, tip, - sha, n->ha, sha, + sha, ha, sha, skb->vlan_proto, skb_vlan_tag_get(skb)); replied = true; @@ -248,7 +250,7 @@ struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *msg) } static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p, - struct sk_buff *request, struct neighbour *n, + struct sk_buff *request, struct neighbour *n, u8 *ha, __be16 vlan_proto, u16 vlan_tci) { struct net_device *dev = request->dev; @@ -300,7 +302,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p, /* Ethernet header */ ether_addr_copy(eth_hdr(reply)->h_dest, daddr); - ether_addr_copy(eth_hdr(reply)->h_source, n->ha); + ether_addr_copy(eth_hdr(reply)->h_source, ha); eth_hdr(reply)->h_proto = htons(ETH_P_IPV6); reply->protocol = htons(ETH_P_IPV6); @@ -330,7 +332,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p, na->icmph.icmp6_override = 1; na->icmph.icmp6_solicited = 1; na->target = ns->target; - ether_addr_copy(&na->opt[2], n->ha); + ether_addr_copy(&na->opt[2], ha); na->opt[0] = ND_OPT_TARGET_LL_ADDR; na->opt[1] = na_olen >> 3; @@ -359,7 +361,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p, __vlan_hwaccel_put_tag(reply, vlan_proto, vlan_tci); netdev_dbg(dev, "nd send dev %s dst %pI6 dst_hw %pM src %pI6 src_hw %pM\n", - dev->name, &pip6->daddr, daddr, &pip6->saddr, n->ha); + dev->name, &pip6->daddr, daddr, &pip6->saddr, ha); if (p) { dev_queue_xmit(reply); @@ -456,24 +458,26 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br, n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, vlandev); if (n) { struct net_bridge_fdb_entry *f; + u8 ha[ETH_ALEN] __aligned(2); if (!(READ_ONCE(n->nud_state) & NUD_VALID)) { neigh_release(n); return; } - f = br_fdb_find_rcu(br, n->ha, vid); + neigh_ha_snapshot(ha, n, n->dev); + f = br_fdb_find_rcu(br, ha, vid); if (f) { const struct net_bridge_port *dst = READ_ONCE(f->dst); bool replied = false; if (br_is_neigh_suppress_enabled(dst, vid)) { if (vid != 0) - br_nd_send(br, p, skb, n, + br_nd_send(br, p, skb, n, ha, skb->vlan_proto, skb_vlan_tag_get(skb)); else - br_nd_send(br, p, skb, n, 0, 0); + br_nd_send(br, p, skb, n, ha, 0, 0); replied = true; } -- 2.33.8
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/28500 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/WRK... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/28500 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/WRK...
participants (2)
-
JiangJieHua -
patchwork bot