mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
Merge branch 'bridge-vxlan-harden-nd-option-parsing-paths'
Yang Yang says: ==================== bridge/vxlan: harden ND option parsing paths This series hardens ND option parsing in bridge and vxlan paths. Patch 1 linearizes the request skb in br_nd_send() before walking ND options. Patch 2 adds explicit ND option length validation in br_nd_send(). Patch 3 adds matching ND option length validation in vxlan_na_create(). ==================== Link: https://patch.msgid.link/20260326034441.2037420-1-n05ec@lzu.edu.cn Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
1a6fdb3518
|
|
@ -1965,12 +1965,14 @@ static struct sk_buff *vxlan_na_create(struct sk_buff *request,
|
|||
ns_olen = request->len - skb_network_offset(request) -
|
||||
sizeof(struct ipv6hdr) - sizeof(*ns);
|
||||
for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
|
||||
if (!ns->opt[i + 1]) {
|
||||
if (!ns->opt[i + 1] || i + (ns->opt[i + 1] << 3) > ns_olen) {
|
||||
kfree_skb(reply);
|
||||
return NULL;
|
||||
}
|
||||
if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
|
||||
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
|
||||
if ((ns->opt[i + 1] << 3) >=
|
||||
sizeof(struct nd_opt_hdr) + ETH_ALEN)
|
||||
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,12 +251,12 @@ struct nd_msg *br_is_nd_neigh_msg(const 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,
|
||||
__be16 vlan_proto, u16 vlan_tci, struct nd_msg *ns)
|
||||
__be16 vlan_proto, u16 vlan_tci)
|
||||
{
|
||||
struct net_device *dev = request->dev;
|
||||
struct net_bridge_vlan_group *vg;
|
||||
struct nd_msg *na, *ns;
|
||||
struct sk_buff *reply;
|
||||
struct nd_msg *na;
|
||||
struct ipv6hdr *pip6;
|
||||
int na_olen = 8; /* opt hdr + ETH_ALEN for target */
|
||||
int ns_olen;
|
||||
|
|
@ -264,7 +264,7 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p,
|
|||
u8 *daddr;
|
||||
u16 pvid;
|
||||
|
||||
if (!dev)
|
||||
if (!dev || skb_linearize(request))
|
||||
return;
|
||||
|
||||
len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
|
||||
|
|
@ -281,17 +281,21 @@ 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));
|
||||
|
||||
/* Do we need option processing ? */
|
||||
ns_olen = request->len - (skb_network_offset(request) +
|
||||
sizeof(struct ipv6hdr)) - sizeof(*ns);
|
||||
for (i = 0; i < ns_olen - 1; i += (ns->opt[i + 1] << 3)) {
|
||||
if (!ns->opt[i + 1]) {
|
||||
if (!ns->opt[i + 1] || i + (ns->opt[i + 1] << 3) > ns_olen) {
|
||||
kfree_skb(reply);
|
||||
return;
|
||||
}
|
||||
if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
|
||||
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
|
||||
if ((ns->opt[i + 1] << 3) >=
|
||||
sizeof(struct nd_opt_hdr) + ETH_ALEN)
|
||||
daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -472,9 +476,9 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
|
|||
if (vid != 0)
|
||||
br_nd_send(br, p, skb, n,
|
||||
skb->vlan_proto,
|
||||
skb_vlan_tag_get(skb), msg);
|
||||
skb_vlan_tag_get(skb));
|
||||
else
|
||||
br_nd_send(br, p, skb, n, 0, 0, msg);
|
||||
br_nd_send(br, p, skb, n, 0, 0);
|
||||
replied = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user