aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_multicast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r--net/bridge/br_multicast.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index eb5b256ffc88..543b3262d002 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -437,7 +437,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
437 ip6h = ipv6_hdr(skb); 437 ip6h = ipv6_hdr(skb);
438 438
439 *(__force __be32 *)ip6h = htonl(0x60000000); 439 *(__force __be32 *)ip6h = htonl(0x60000000);
440 ip6h->payload_len = 8 + sizeof(*mldq); 440 ip6h->payload_len = htons(8 + sizeof(*mldq));
441 ip6h->nexthdr = IPPROTO_HOPOPTS; 441 ip6h->nexthdr = IPPROTO_HOPOPTS;
442 ip6h->hop_limit = 1; 442 ip6h->hop_limit = 1;
443 ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0); 443 ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0);
@@ -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
1537out: 1547out:
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