splice: fix racy pipe->buffers uses
Dave Jones reported a kernel BUG at mm/slub.c:3474! triggered
by splice_shrink_spd() called from vmsplice_to_pipe()
commit 35f3d14dbb
(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>
Cc: stable <stable@vger.kernel.org> # 2.6.35
Tested-by: Dave Jones <davej@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
@@ -3609,6 +3609,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
|
||||
.pages = pages_def,
|
||||
.partial = partial_def,
|
||||
.nr_pages = 0, /* This gets updated below. */
|
||||
.nr_pages_max = PIPE_DEF_BUFFERS,
|
||||
.flags = flags,
|
||||
.ops = &tracing_pipe_buf_ops,
|
||||
.spd_release = tracing_spd_release_pipe,
|
||||
@@ -3680,7 +3681,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
|
||||
|
||||
ret = splice_to_pipe(pipe, &spd);
|
||||
out:
|
||||
splice_shrink_spd(pipe, &spd);
|
||||
splice_shrink_spd(&spd);
|
||||
return ret;
|
||||
|
||||
out_err:
|
||||
@@ -4231,6 +4232,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
|
||||
struct splice_pipe_desc spd = {
|
||||
.pages = pages_def,
|
||||
.partial = partial_def,
|
||||
.nr_pages_max = PIPE_DEF_BUFFERS,
|
||||
.flags = flags,
|
||||
.ops = &buffer_pipe_buf_ops,
|
||||
.spd_release = buffer_spd_release,
|
||||
@@ -4318,7 +4320,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
|
||||
}
|
||||
|
||||
ret = splice_to_pipe(pipe, &spd);
|
||||
splice_shrink_spd(pipe, &spd);
|
||||
splice_shrink_spd(&spd);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user