| Submitter | Eric Dumazet |
|---|---|
| Date | March 14, 2013, 3:40 p.m. |
| Message ID | <1363275632.29475.32.camel@edumazet-glaptop> |
| Download | mbox | patch |
| Permalink | /patch/227719/ |
| State | Accepted |
| Delegated to: | David Miller |
| Headers | show |
Comments
From: Eric Dumazet <eric.dumazet@gmail.com> Date: Thu, 14 Mar 2013 16:40:32 +0100 > From: Eric Dumazet <edumazet@google.com> > > Chrome OS team reported a crash on a Pixel ChromeBook in TCP stack : > > https://code.google.com/p/chromium/issues/detail?id=182056 > > commit a21d45726acac (tcp: avoid order-1 allocations on wifi and tx > path) did a poor choice adding an 'avail_size' field to skb, while > what we really needed was a 'reserved_tailroom' one. > > It would have avoided commit 22b4a4f22da (tcp: fix retransmit of > partially acked frames) and this commit. > > Crash occurs because skb_split() is not aware of the 'avail_size' > management (and should not be aware) > > Signed-off-by: Eric Dumazet <edumazet@google.com> > Reported-by: Mukesh Agrawal <quiche@chromium.org> Applied and queued up for -stable, thanks Eric. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Patch
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 821c7f4..6f2bb86 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -500,7 +500,7 @@ struct sk_buff { union { __u32 mark; __u32 dropcount; - __u32 avail_size; + __u32 reserved_tailroom; }; sk_buff_data_t inner_transport_header; @@ -1447,7 +1447,10 @@ static inline int skb_tailroom(const struct sk_buff *skb) */ static inline int skb_availroom(const struct sk_buff *skb) { - return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len; + if (skb_is_nonlinear(skb)) + return 0; + + return skb->end - skb->tail - skb->reserved_tailroom; } /** diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 47e854f..e220207 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -775,7 +775,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) * Make sure that we have exactly size bytes * available to the caller, no more, no less. */ - skb->avail_size = size; + skb->reserved_tailroom = skb->end - skb->tail - size; return skb; } __kfree_skb(skb); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e2b4461..817fbb3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1298,7 +1298,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) eat = min_t(int, len, skb_headlen(skb)); if (eat) { __skb_pull(skb, eat); - skb->avail_size -= eat; len -= eat; if (!len) return;