From: Ben Pfaff Date: Tue, 11 Nov 2008 23:40:28 +0000 (-0800) Subject: Fix datapath make_writable() function. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a5396937e998ae8b9a281871e213545b2953f6c;p=openvswitch Fix datapath make_writable() function. - We weren't necessarily pulling enough into the headers in the non-shared case, since the IP header by itself can be longer than 40 bytes. - The skb is guaranteed not to have a destructor at this point. --- diff --git a/datapath/dp_act.c b/datapath/dp_act.c index daa319a2..14eaac33 100644 --- a/datapath/dp_act.c +++ b/datapath/dp_act.c @@ -502,26 +502,17 @@ void execute_actions(struct datapath *dp, struct sk_buff *skb, int make_writable(struct sk_buff **pskb) { - /* Based on skb_make_writable() in net/netfilter/core.c. */ - struct sk_buff *nskb; - - /* Not exclusive use of packet? Must copy. */ - if (skb_shared(*pskb) || skb_cloned(*pskb)) - goto copy_skb; - - return pskb_may_pull(*pskb, 40); /* FIXME? */ - -copy_skb: - nskb = skb_copy(*pskb, GFP_ATOMIC); - if (!nskb) - return 0; - BUG_ON(skb_is_nonlinear(nskb)); - - /* Rest of kernel will get very unhappy if we pass it a - suddenly-orphaned skbuff */ - if ((*pskb)->sk) - skb_set_owner_w(nskb, (*pskb)->sk); - kfree_skb(*pskb); - *pskb = nskb; - return 1; + struct sk_buff *skb = *pskb; + if (skb_shared(skb) || skb_cloned(skb)) { + struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); + if (!nskb) + return 0; + kfree_skb(skb); + *pskb = nskb; + return 1; + } else { + unsigned int hdr_len = (skb_transport_offset(skb) + + sizeof(struct tcphdr)); + return pskb_may_pull(skb, min(hdr_len, skb->len)); + } }