| From 9a4bebfcd81dd5935941c196efd89f8b950e0fe5 Mon Sep 17 00:00:00 2001 |
| From: Andy Gospodarek <andy@greyhouse.net> |
| Date: Fri, 10 Sep 2010 11:43:20 +0000 |
| Subject: [PATCH] bonding: correctly process non-linear skbs |
| |
| commit ab12811c89e88f2e66746790b1fe4469ccb7bdd9 upstream. |
| |
| It was recently brought to my attention that 802.3ad mode bonds would no |
| longer form when using some network hardware after a driver update. |
| After snooping around I realized that the particular hardware was using |
| page-based skbs and found that skb->data did not contain a valid LACPDU |
| as it was not stored there. That explained the inability to form an |
| 802.3ad-based bond. For balance-alb mode bonds this was also an issue |
| as ARPs would not be properly processed. |
| |
| This patch fixes the issue in my tests and should be applied to 2.6.36 |
| and as far back as anyone cares to add it to stable. |
| |
| Thanks to Alexander Duyck <alexander.h.duyck@intel.com> and Jesse |
| Brandeburg <jesse.brandeburg@intel.com> for the suggestions on this one. |
| |
| Signed-off-by: Andy Gospodarek <andy@greyhouse.net> |
| CC: Alexander Duyck <alexander.h.duyck@intel.com> |
| CC: Jesse Brandeburg <jesse.brandeburg@intel.com> |
| Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| --- |
| drivers/net/bonding/bond_3ad.c | 3 +++ |
| drivers/net/bonding/bond_alb.c | 3 +++ |
| 2 files changed, 6 insertions(+), 0 deletions(-) |
| |
| diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c |
| index 822f586..0ddf4c6 100644 |
| --- a/drivers/net/bonding/bond_3ad.c |
| +++ b/drivers/net/bonding/bond_3ad.c |
| @@ -2466,6 +2466,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac |
| if (!(dev->flags & IFF_MASTER)) |
| goto out; |
| |
| + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) |
| + goto out; |
| + |
| read_lock(&bond->lock); |
| slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev), |
| orig_dev); |
| diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c |
| index 40fdc41..0d42b38 100644 |
| --- a/drivers/net/bonding/bond_alb.c |
| +++ b/drivers/net/bonding/bond_alb.c |
| @@ -368,6 +368,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct |
| goto out; |
| } |
| |
| + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) |
| + goto out; |
| + |
| if (skb->len < sizeof(struct arp_pkt)) { |
| pr_debug("Packet is too small to be an ARP\n"); |
| goto out; |
| -- |
| 1.7.0.4 |
| |