summaryrefslogtreecommitdiff
path: root/net/bridge/br_multicast.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-04 13:55:49 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-04 13:55:49 -0800
commit65f42886e24be2197b1263f138eabf40c6774d00 (patch)
treec45ab3a3634a9a949f54b7ee4ca9295db5674e5e /net/bridge/br_multicast.c
parent8a87694ed159d7abd2c9ed657416696c05db2252 (diff)
parent9fc3bbb4a752f108cf096d96640f3b548bbbce6c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: ipv4/route.c: respect prefsrc for local routes bridge: stp: ensure mac header is set bridge: fix br_multicast_ipv6_rcv for paged skbs atl1: fix oops when changing tx/rx ring params drivers/atm/atmtcp.c: add missing atm_dev_put starfire: Fix dma_addr_t size test for MIPS tg3: fix return value check in tg3_read_vpd() Broadcom CNIC core network driver: fix mem leak on allocation failures in cnic_alloc_uio_rings() ISDN, Gigaset: Fix memory leak in do_disconnect_req() CAN: Use inode instead of kernel address for /proc file skfp: testing the wrong variable in skfp_driver_init() ppp: allow disabling multilink protocol ID compression ehea: Avoid changing vlan flags ueagle-atm: fix PHY signal initialization race
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 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,
struct net_bridge_port *port,
struct sk_buff *skb)
{
- struct sk_buff *skb2 = skb;
+ struct sk_buff *skb2;
struct ipv6hdr *ip6h;
struct icmp6hdr *icmp6h;
u8 nexthdr;
@@ -1469,15 +1469,15 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
if (!skb2)
return -ENOMEM;
+ err = -EINVAL;
+ if (!pskb_may_pull(skb2, offset + sizeof(struct icmp6hdr)))
+ goto out;
+
len -= offset - skb_network_offset(skb2);
__skb_pull(skb2, offset);
skb_reset_transport_header(skb2);
- err = -EINVAL;
- if (!pskb_may_pull(skb2, sizeof(*icmp6h)))
- goto out;
-
icmp6h = icmp6_hdr(skb2);
switch (icmp6h->icmp6_type) {
@@ -1516,7 +1516,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
switch (icmp6h->icmp6_type) {
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;
err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
break;
@@ -1529,15 +1534,18 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
break;
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);
}
}
out:
- __skb_push(skb2, offset);
- if (skb2 != skb)
- kfree_skb(skb2);
+ kfree_skb(skb2);
return err;
}
#endif