tipc: Ensure outgoing messages on Ethernet have sufficient headroom
authorAllan Stephens <allan.stephens@windriver.com>
Fri, 3 Sep 2010 08:33:40 +0000 (08:33 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Sep 2010 01:12:56 +0000 (18:12 -0700)
Add code to expand the headroom of an outgoing TIPC message if the
sk_buff has insufficient room to hold the header for the associated
Ethernet device.  This change is necessary to ensure that messages
TIPC does not create itself (eg. incoming messages that are being
routed to another node) do not cause problems, since TIPC has no
control over the amount of headroom available in such messages.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/eth_media.c

index 6230d16020c49917f5f28e06b514d379f698205d..81253d0b24b9d0cd2780602cac850f95d379c070 100644 (file)
@@ -72,17 +72,26 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
 {
        struct sk_buff *clone;
        struct net_device *dev;
+       int delta;
 
        clone = skb_clone(buf, GFP_ATOMIC);
-       if (clone) {
-               skb_reset_network_header(clone);
-               dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
-               clone->dev = dev;
-               dev_hard_header(clone, dev, ETH_P_TIPC,
-                                &dest->dev_addr.eth_addr,
-                                dev->dev_addr, clone->len);
-               dev_queue_xmit(clone);
+       if (!clone)
+               return 0;
+
+       dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
+       delta = dev->hard_header_len - skb_headroom(buf);
+
+       if ((delta > 0) &&
+           pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
+               kfree_skb(clone);
+               return 0;
        }
+
+       skb_reset_network_header(clone);
+       clone->dev = dev;
+       dev_hard_header(clone, dev, ETH_P_TIPC, &dest->dev_addr.eth_addr,
+                       dev->dev_addr, clone->len);
+       dev_queue_xmit(clone);
        return 0;
 }