Commit 3bb4aac6 authored by Eric Dumazet's avatar Eric Dumazet Committed by Ben Hutchings

tcp: fix skb_availroom()

[ Upstream commit 16fad69c ]

Chrome OS team reported a crash on a Pixel ChromeBook in TCP stack :

https://code.google.com/p/chromium/issues/detail?id=182056

commit a21d4572 (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 22b4a4f2 (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: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarMukesh Agrawal <quiche@chromium.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent f43dc583
...@@ -455,7 +455,7 @@ struct sk_buff { ...@@ -455,7 +455,7 @@ struct sk_buff {
union { union {
__u32 mark; __u32 mark;
__u32 dropcount; __u32 dropcount;
__u32 avail_size; __u32 reserved_tailroom;
}; };
__u16 vlan_tci; __u16 vlan_tci;
...@@ -1332,7 +1332,10 @@ static inline int skb_tailroom(const struct sk_buff *skb) ...@@ -1332,7 +1332,10 @@ static inline int skb_tailroom(const struct sk_buff *skb)
*/ */
static inline int skb_availroom(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;
} }
/** /**
......
...@@ -704,7 +704,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) ...@@ -704,7 +704,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)
* Make sure that we have exactly size bytes * Make sure that we have exactly size bytes
* available to the caller, no more, no less. * available to the caller, no more, no less.
*/ */
skb->avail_size = size; skb->reserved_tailroom = skb->end - skb->tail - size;
return skb; return skb;
} }
__kfree_skb(skb); __kfree_skb(skb);
......
...@@ -1096,7 +1096,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) ...@@ -1096,7 +1096,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
eat = min_t(int, len, skb_headlen(skb)); eat = min_t(int, len, skb_headlen(skb));
if (eat) { if (eat) {
__skb_pull(skb, eat); __skb_pull(skb, eat);
skb->avail_size -= eat;
len -= eat; len -= eat;
if (!len) if (!len)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment