net: Fix data corruption when splicing from sockets.
commit813fa24255a5de93ef3fc4c2efff3ee31a2545b6
authorJarek Poplawski <jarkao2@gmail.com>
Tue, 20 Jan 2009 01:03:56 +0000 (19 17:03 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 17 Feb 2009 17:29:05 +0000 (17 09:29 -0800)
tree919bcc9b8fb7648f2af717e72df9b6491fac1e17
parentcfc7f11699d572ed0cba07f3560258c2216b7ef0
net: Fix data corruption when splicing from sockets.

[ Upstream commit 8b9d3728977760f6bd1317c4420890f73695354e ]

The trick in socket splicing where we try to convert the skb->data
into a page based reference using virt_to_page() does not work so
well.

The idea is to pass the virt_to_page() reference via the pipe
buffer, and refcount the buffer using a SKB reference.

But if we are splicing from a socket to a socket (via sendpage)
this doesn't work.

The from side processing will grab the page (and SKB) references.
The sendpage() calls will grab page references only, return, and
then the from side processing completes and drops the SKB ref.

The page based reference to skb->data is not enough to keep the
kmalloc() buffer backing it from being reused.  Yet, that is
all that the socket send side has at this point.

This leads to data corruption if the skb->data buffer is reused
by SLAB before the send side socket actually gets the TX packet
out to the device.

The fix employed here is to simply allocate a page and copy the
skb->data bytes into that page.

This will hurt performance, but there is no clear way to fix this
properly without a copy at the present time, and it is important
to get rid of the data corruption.

With fixes from Herbert Xu.

Tested-by: Willy Tarreau <w@1wt.eu>
Foreseen-by: Changli Gao <xiaosuo@gmail.com>
Diagnosed-by: Willy Tarreau <w@1wt.eu>
Reported-by: Willy Tarreau <w@1wt.eu>
Fixed-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
net/core/skbuff.c