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.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index f03e2e98cd44..f701a21acb34 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1451,7 +1451,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1451 struct net_bridge_port *port, 1451 struct net_bridge_port *port,
1452 struct sk_buff *skb) 1452 struct sk_buff *skb)
1453{ 1453{
1454 struct sk_buff *skb2 = skb; 1454 struct sk_buff *skb2;
1455 struct ipv6hdr *ip6h; 1455 struct ipv6hdr *ip6h;
1456 struct icmp6hdr *icmp6h; 1456 struct icmp6hdr *icmp6h;
1457 u8 nexthdr; 1457 u8 nexthdr;
@@ -1490,15 +1490,15 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1490 if (!skb2) 1490 if (!skb2)
1491 return -ENOMEM; 1491 return -ENOMEM;
1492 1492
1493 err = -EINVAL;
1494 if (!pskb_may_pull(skb2, offset + sizeof(struct icmp6hdr)))
1495 goto out;
1496
1493 len -= offset - skb_network_offset(skb2); 1497 len -= offset - skb_network_offset(skb2);
1494 1498
1495 __skb_pull(skb2, offset); 1499 __skb_pull(skb2, offset);
1496 skb_reset_transport_header(skb2); 1500 skb_reset_transport_header(skb2);
1497 1501
1498 err = -EINVAL;
1499 if (!pskb_may_pull(skb2, sizeof(*icmp6h)))
1500 goto out;
1501
1502 icmp6h = icmp6_hdr(skb2); 1502 icmp6h = icmp6_hdr(skb2);
1503 1503
1504 switch (icmp6h->icmp6_type) { 1504 switch (icmp6h->icmp6_type) {
@@ -1537,7 +1537,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1537 switch (icmp6h->icmp6_type) { 1537 switch (icmp6h->icmp6_type) {
1538 case ICMPV6_MGM_REPORT: 1538 case ICMPV6_MGM_REPORT:
1539 { 1539 {
1540 struct mld_msg *mld = (struct mld_msg *)icmp6h; 1540 struct mld_msg *mld;
1541 if (!pskb_may_pull(skb2, sizeof(*mld))) {
1542 err = -EINVAL;
1543 goto out;
1544 }
1545 mld = (struct mld_msg *)skb_transport_header(skb2);
1541 BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; 1546 BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
1542 err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); 1547 err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
1543 break; 1548 break;
@@ -1550,15 +1555,18 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1550 break; 1555 break;
1551 case ICMPV6_MGM_REDUCTION: 1556 case ICMPV6_MGM_REDUCTION:
1552 { 1557 {
1553 struct mld_msg *mld = (struct mld_msg *)icmp6h; 1558 struct mld_msg *mld;
1559 if (!pskb_may_pull(skb2, sizeof(*mld))) {
1560 err = -EINVAL;
1561 goto out;
1562 }
1563 mld = (struct mld_msg *)skb_transport_header(skb2);
1554 br_ip6_multicast_leave_group(br, port, &mld->mld_mca); 1564 br_ip6_multicast_leave_group(br, port, &mld->mld_mca);
1555 } 1565 }
1556 } 1566 }
1557 1567
1558out: 1568out:
1559 __skb_push(skb2, offset); 1569 kfree_skb(skb2);
1560 if (skb2 != skb)
1561 kfree_skb(skb2);
1562 return err; 1570 return err;
1563} 1571}
1564#endif 1572#endif