|
@@ -1451,7 +1451,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
|
|
struct net_bridge_port *port,
|
|
struct net_bridge_port *port,
|
|
struct sk_buff *skb)
|
|
struct sk_buff *skb)
|
|
{
|
|
{
|
|
- struct sk_buff *skb2 = skb;
|
|
|
|
|
|
+ struct sk_buff *skb2;
|
|
struct ipv6hdr *ip6h;
|
|
struct ipv6hdr *ip6h;
|
|
struct icmp6hdr *icmp6h;
|
|
struct icmp6hdr *icmp6h;
|
|
u8 nexthdr;
|
|
u8 nexthdr;
|
|
@@ -1490,15 +1490,15 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
|
|
if (!skb2)
|
|
if (!skb2)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
+ err = -EINVAL;
|
|
|
|
+ if (!pskb_may_pull(skb2, offset + sizeof(struct icmp6hdr)))
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
len -= offset - skb_network_offset(skb2);
|
|
len -= offset - skb_network_offset(skb2);
|
|
|
|
|
|
__skb_pull(skb2, offset);
|
|
__skb_pull(skb2, offset);
|
|
skb_reset_transport_header(skb2);
|
|
skb_reset_transport_header(skb2);
|
|
|
|
|
|
- err = -EINVAL;
|
|
|
|
- if (!pskb_may_pull(skb2, sizeof(*icmp6h)))
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
icmp6h = icmp6_hdr(skb2);
|
|
icmp6h = icmp6_hdr(skb2);
|
|
|
|
|
|
switch (icmp6h->icmp6_type) {
|
|
switch (icmp6h->icmp6_type) {
|
|
@@ -1537,7 +1537,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
|
|
switch (icmp6h->icmp6_type) {
|
|
switch (icmp6h->icmp6_type) {
|
|
case ICMPV6_MGM_REPORT:
|
|
case ICMPV6_MGM_REPORT:
|
|
{
|
|
{
|
|
- struct mld_msg *mld = (struct mld_msg *)icmp6h;
|
|
|
|
|
|
+ struct mld_msg *mld;
|
|
|
|
+ if (!pskb_may_pull(skb2, sizeof(*mld))) {
|
|
|
|
+ err = -EINVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ mld = (struct mld_msg *)skb_transport_header(skb2);
|
|
BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
|
|
BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
|
|
err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
|
|
err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
|
|
break;
|
|
break;
|
|
@@ -1550,15 +1555,18 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
|
|
break;
|
|
break;
|
|
case ICMPV6_MGM_REDUCTION:
|
|
case ICMPV6_MGM_REDUCTION:
|
|
{
|
|
{
|
|
- struct mld_msg *mld = (struct mld_msg *)icmp6h;
|
|
|
|
|
|
+ struct mld_msg *mld;
|
|
|
|
+ if (!pskb_may_pull(skb2, sizeof(*mld))) {
|
|
|
|
+ err = -EINVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ mld = (struct mld_msg *)skb_transport_header(skb2);
|
|
br_ip6_multicast_leave_group(br, port, &mld->mld_mca);
|
|
br_ip6_multicast_leave_group(br, port, &mld->mld_mca);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
out:
|
|
out:
|
|
- __skb_push(skb2, offset);
|
|
|
|
- if (skb2 != skb)
|
|
|
|
- kfree_skb(skb2);
|
|
|
|
|
|
+ kfree_skb(skb2);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|