diff options
| -rw-r--r-- | net/bridge/br_multicast.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index f19e347f56f6..543b3262d002 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -1430,7 +1430,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
| 1430 | struct net_bridge_port *port, | 1430 | struct net_bridge_port *port, |
| 1431 | struct sk_buff *skb) | 1431 | struct sk_buff *skb) |
| 1432 | { | 1432 | { |
| 1433 | struct sk_buff *skb2 = skb; | 1433 | struct sk_buff *skb2; |
| 1434 | struct ipv6hdr *ip6h; | 1434 | struct ipv6hdr *ip6h; |
| 1435 | struct icmp6hdr *icmp6h; | 1435 | struct icmp6hdr *icmp6h; |
| 1436 | u8 nexthdr; | 1436 | u8 nexthdr; |
| @@ -1469,15 +1469,15 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
| 1469 | if (!skb2) | 1469 | if (!skb2) |
| 1470 | return -ENOMEM; | 1470 | return -ENOMEM; |
| 1471 | 1471 | ||
| 1472 | err = -EINVAL; | ||
| 1473 | if (!pskb_may_pull(skb2, offset + sizeof(struct icmp6hdr))) | ||
| 1474 | goto out; | ||
| 1475 | |||
| 1472 | len -= offset - skb_network_offset(skb2); | 1476 | len -= offset - skb_network_offset(skb2); |
| 1473 | 1477 | ||
| 1474 | __skb_pull(skb2, offset); | 1478 | __skb_pull(skb2, offset); |
| 1475 | skb_reset_transport_header(skb2); | 1479 | skb_reset_transport_header(skb2); |
| 1476 | 1480 | ||
| 1477 | err = -EINVAL; | ||
| 1478 | if (!pskb_may_pull(skb2, sizeof(*icmp6h))) | ||
| 1479 | goto out; | ||
| 1480 | |||
| 1481 | icmp6h = icmp6_hdr(skb2); | 1481 | icmp6h = icmp6_hdr(skb2); |
| 1482 | 1482 | ||
| 1483 | switch (icmp6h->icmp6_type) { | 1483 | switch (icmp6h->icmp6_type) { |
| @@ -1516,7 +1516,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
| 1516 | switch (icmp6h->icmp6_type) { | 1516 | switch (icmp6h->icmp6_type) { |
| 1517 | case ICMPV6_MGM_REPORT: | 1517 | case ICMPV6_MGM_REPORT: |
| 1518 | { | 1518 | { |
| 1519 | struct mld_msg *mld = (struct mld_msg *)icmp6h; | 1519 | struct mld_msg *mld; |
| 1520 | if (!pskb_may_pull(skb2, sizeof(*mld))) { | ||
| 1521 | err = -EINVAL; | ||
| 1522 | goto out; | ||
| 1523 | } | ||
| 1524 | mld = (struct mld_msg *)skb_transport_header(skb2); | ||
| 1520 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; | 1525 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; |
| 1521 | err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); | 1526 | err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); |
| 1522 | break; | 1527 | break; |
| @@ -1529,15 +1534,18 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
| 1529 | break; | 1534 | break; |
| 1530 | case ICMPV6_MGM_REDUCTION: | 1535 | case ICMPV6_MGM_REDUCTION: |
| 1531 | { | 1536 | { |
| 1532 | struct mld_msg *mld = (struct mld_msg *)icmp6h; | 1537 | struct mld_msg *mld; |
| 1538 | if (!pskb_may_pull(skb2, sizeof(*mld))) { | ||
| 1539 | err = -EINVAL; | ||
| 1540 | goto out; | ||
| 1541 | } | ||
| 1542 | mld = (struct mld_msg *)skb_transport_header(skb2); | ||
| 1533 | br_ip6_multicast_leave_group(br, port, &mld->mld_mca); | 1543 | br_ip6_multicast_leave_group(br, port, &mld->mld_mca); |
| 1534 | } | 1544 | } |
| 1535 | } | 1545 | } |
| 1536 | 1546 | ||
| 1537 | out: | 1547 | out: |
| 1538 | __skb_push(skb2, offset); | 1548 | kfree_skb(skb2); |
| 1539 | if (skb2 != skb) | ||
| 1540 | kfree_skb(skb2); | ||
| 1541 | return err; | 1549 | return err; |
| 1542 | } | 1550 | } |
| 1543 | #endif | 1551 | #endif |
