Skip to content

Commit

Permalink
tcp: fix skb_availroom()
Browse files Browse the repository at this point in the history
Chrome OS team reported a crash on a Pixel ChromeBook in TCP stack :

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

commit a21d457 (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 22b4a4f (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>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Mar 14, 2013
1 parent b701f16 commit 16fad69
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 4 deletions.
7 changes: 5 additions & 2 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion net/ipv4/tcp_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 16fad69

Please sign in to comment.