Skip to content

Commit 6ba6332

Browse files
Miklos Szeredijosephhz
authored andcommitted
fuse: fix page stealing
ANBZ: torvalds#208 commit 712a951 upstream. It is possible to trigger a crash by splicing anon pipe bufs to the fuse device. The reason for this is that anon_pipe_buf_release() will reuse buf->page if the refcount is 1, but that page might have already been stolen and its flags modified (e.g. PG_lru added). This happens in the unlikely case of fuse_dev_splice_write() getting around to calling pipe_buf_release() after a page has been stolen, added to the page cache and removed from the page cache. Fix by calling pipe_buf_release() right after the page was inserted into the page cache. In this case the page has an elevated refcount so any release function will know that the page isn't reusable. Reported-by: Frank Dinoff <[email protected]> Link: https://lore.kernel.org/r/CAAmZXrsGg2xsP1CK+cbuEMumtrqdvD-NKnWzhNcvn71RV3c1yw@mail.gmail.com/ Fixes: dd3bb14 ("fuse: support splice() writing to fuse device") Cc: <[email protected]> # v2.6.35 Signed-off-by: Miklos Szeredi <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Hongnan Li <[email protected]> Reviewed-by: Joseph Qi <[email protected]>
1 parent 6300e01 commit 6ba6332

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

fs/fuse/dev.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,12 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
931931
goto out_put_old;
932932
}
933933

934+
/*
935+
* Release while we have extra ref on stolen page. Otherwise
936+
* anon_pipe_buf_release() might think the page can be reused.
937+
*/
938+
pipe_buf_release(cs->pipe, buf);
939+
934940
get_page(newpage);
935941

936942
if (!(buf->flags & PIPE_BUF_FLAG_LRU))
@@ -2072,8 +2078,12 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
20722078

20732079
pipe_lock(pipe);
20742080
out_free:
2075-
for (idx = 0; idx < nbuf; idx++)
2076-
pipe_buf_release(pipe, &bufs[idx]);
2081+
for (idx = 0; idx < nbuf; idx++) {
2082+
struct pipe_buffer *buf = &bufs[idx];
2083+
2084+
if (buf->ops)
2085+
pipe_buf_release(pipe, buf);
2086+
}
20772087
pipe_unlock(pipe);
20782088

20792089
kvfree(bufs);

0 commit comments

Comments
 (0)