From c89bcb02e0ad81977024a7b40267049068ec88d9 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Wed, 4 Jun 2008 15:45:58 -0700 Subject: [PATCH] --- yaml --- r: 97687 b: refs/heads/master c: 293ad60401da621b8b329abbe8c388edb25f658a h: refs/heads/master i: 97685: e3681e39f9da2e58ef9def0a1117b8a2ebaba26a 97683: 135a3f5aeb338d2e999b0cf9a595fe8ff5fcf191 97679: c70200d1edc2639d87906138275d8abaad739416 v: v3 --- [refs] | 2 +- trunk/net/core/skbuff.c | 5 +++-- trunk/net/ipv4/tcp.c | 9 ++++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 45485c16a9e7..9c2cd151ba7f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 26af65cbeb2467a486ae4fc7242c94e470c67c50 +refs/heads/master: 293ad60401da621b8b329abbe8c388edb25f658a diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 5c459f2b7985..1e556d312117 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -1445,6 +1445,7 @@ int skb_splice_bits(struct sk_buff *__skb, unsigned int offset, if (spd.nr_pages) { int ret; + struct sock *sk = __skb->sk; /* * Drop the socket lock, otherwise we have reverse @@ -1455,9 +1456,9 @@ int skb_splice_bits(struct sk_buff *__skb, unsigned int offset, * we call into ->sendpage() with the i_mutex lock held * and networking will grab the socket lock. */ - release_sock(__skb->sk); + release_sock(sk); ret = splice_to_pipe(pipe, &spd); - lock_sock(__skb->sk); + lock_sock(sk); return ret; } diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index f88653138621..ab66683b8043 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -1227,7 +1227,14 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, copied += used; offset += used; } - if (offset != skb->len) + /* + * If recv_actor drops the lock (e.g. TCP splice + * receive) the skb pointer might be invalid when + * getting here: tcp_collapse might have deleted it + * while aggregating skbs from the socket queue. + */ + skb = tcp_recv_skb(sk, seq-1, &offset); + if (!skb || (offset+1 != skb->len)) break; } if (tcp_hdr(skb)->fin) {