diff options
author | Eric Dumazet <edumazet@google.com> | 2012-06-12 15:24:40 +0200 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2012-07-12 04:31:59 +0100 |
commit | 9558b2ab1db5e94fcb7d5ab111a32e423a016c09 (patch) | |
tree | 9dbabf74f3c971e5575e75ffab5bdc926021391f /net/core | |
parent | 1990855918045c6bd2c8b7ad62917d141eed4332 (diff) |
splice: fix racy pipe->buffers uses
commit 047fe3605235888f3ebcda0c728cb31937eadfe6 upstream.
Dave Jones reported a kernel BUG at mm/slub.c:3474! triggered
by splice_shrink_spd() called from vmsplice_to_pipe()
commit 35f3d14dbbc5 (pipe: add support for shrinking and growing pipes)
added capability to adjust pipe->buffers.
Problem is some paths don't hold pipe mutex and assume pipe->buffers
doesn't change for their duration.
Fix this by adding nr_pages_max field in struct splice_pipe_desc, and
use it in place of pipe->buffers where appropriate.
splice_shrink_spd() loses its struct pipe_inode_info argument.
Reported-by: Dave Jones <davej@redhat.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Tom Herbert <therbert@google.com>
Tested-by: Dave Jones <davej@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[bwh: Backported to 3.2:
- Adjust context in vmsplice_to_pipe()
- Update one more call to splice_shrink_spd(), from skb_splice_bits()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/skbuff.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2ec200de08b..af9c3c6832f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1663,6 +1663,7 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = MAX_SKB_FRAGS, .flags = flags, .ops = &sock_pipe_buf_ops, .spd_release = sock_spd_release, @@ -1709,7 +1710,7 @@ done: lock_sock(sk); } - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return ret; } |