tcp: fix skb_availroom()
Chrome OS team reported a crash on a Pixel ChromeBook in TCP stack : https://code.google.com/p/chromium/issues/detail?id=182056 commita21d45726a
(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 commit22b4a4f22d
(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> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b701f16dd4
commit
16fad69cfe
3 changed files with 6 additions and 4 deletions
|
@ -500,7 +500,7 @@ struct sk_buff {
|
||||||
union {
|
union {
|
||||||
__u32 mark;
|
__u32 mark;
|
||||||
__u32 dropcount;
|
__u32 dropcount;
|
||||||
__u32 avail_size;
|
__u32 reserved_tailroom;
|
||||||
};
|
};
|
||||||
|
|
||||||
sk_buff_data_t inner_transport_header;
|
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)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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
|
* 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);
|
||||||
|
|
|
@ -1298,7 +1298,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;
|
||||||
|
|
Loading…
Reference in a new issue