datapath: Ensure packet length matches headers during checksum setup.
authorJesse Gross <jesse@nicira.com>
Mon, 26 Apr 2010 21:19:28 +0000 (14:19 -0700)
committerJesse Gross <jesse@nicira.com>
Fri, 30 Apr 2010 01:14:03 +0000 (18:14 -0700)
During the setup of checksumming pointers we need to make sure that
the transport headers are in the skb linear data area.  However, we
don't currently verify that the lengths in the packet headers are
within the size of the packet.  This makes that check before a
BUG() check does it for us.

CC: "Nick Couchman" <Nick.Couchman@seakr.com>
datapath/datapath.c

index 4f74795e8c05ff4b6f21923a18cbbeaff3e72281..83dd76fefcbd4d6d072c98d72b12b7cc5285cd2d 100644 (file)
@@ -551,22 +551,9 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
 }
 
 #if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
-/* This code is based on a skb_checksum_setup from net/dev/core.c from a
- * combination of Lenny's 2.6.26 Xen kernel and Xen's
- * linux-2.6.18-92.1.10.el5.xs5.0.0.394.644.  We can't call this function
- * directly because it isn't exported in all versions. */
-static int skb_pull_up_to(struct sk_buff *skb, void *ptr)
-{
-       if (ptr < (void *)skb->tail)
-               return 1;
-       if (__pskb_pull_tail(skb,
-                            ptr - (void *)skb->data - skb_headlen(skb))) {
-               return 1;
-       } else {
-               return 0;
-       }
-}
-
+/* This code is based on skb_checksum_setup() from Xen's net/dev/core.c.  We
+ * can't call this function directly because it isn't exported in all
+ * versions. */
 int vswitch_skb_checksum_setup(struct sk_buff *skb)
 {
        struct iphdr *iph;
@@ -580,7 +567,7 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb)
        if (skb->protocol != htons(ETH_P_IP))
                goto out;
 
-       if (!skb_pull_up_to(skb, skb_network_header(skb) + sizeof(struct iphdr)))
+       if (!pskb_may_pull(skb, skb_network_header(skb) + sizeof(struct iphdr) - skb->data))
                goto out;
 
        iph = ip_hdr(skb);
@@ -602,7 +589,7 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb)
                goto out;
        }
 
-       if (!skb_pull_up_to(skb, th + csum_offset + 2))
+       if (!pskb_may_pull(skb, th + csum_offset + 2 - skb->data))
                goto out;
 
        skb->ip_summed = CHECKSUM_PARTIAL;