On Tue, Nov 23, 2021 at 7:29 PM Justin Forbes <jmforbes@xxxxxxxxxxx> wrote: > > On Mon, Nov 15, 2021 at 7:04 PM Greg Kroah-Hartman > <gregkh@xxxxxxxxxxxxxxxxxxx> wrote: > > > > From: Miklos Szeredi <mszeredi@xxxxxxxxxx> > > > > commit 712a951025c0667ff00b25afc360f74e639dfabe 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 <fdinoff@xxxxxxxxxx> > > Link: https://lore.kernel.org/r/CAAmZXrsGg2xsP1CK+cbuEMumtrqdvD-NKnWzhNcvn71RV3c1yw@xxxxxxxxxxxxxx/ > > Fixes: dd3bb14f44a6 ("fuse: support splice() writing to fuse device") > > Cc: <stable@xxxxxxxxxxxxxxx> # v2.6.35 > > Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxxxxx> > > Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > > It appears this patch causes a rather serious regression in flatpacks > using portals to access files. Reverting this patch restores expected > behavior. I have asked users in the Fedora bug to test with 5.16-rc2 > to see if we are just missing a dependent patch in stable, or if this > is broken there as well, but no response yet.: > > https://bugzilla.redhat.com/show_bug.cgi?id=2025285 > https://github.com/flatpak/flatpak/issues/4595 Hi, Thanks for the report. Can someone with the reproducer try the attached patch? I think the race there is unlikely but possible. Thanks, Miklos
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 79f7eda49e06..959d2b7f9e9d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -847,14 +847,14 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) replace_page_cache_page(oldpage, newpage); + get_page(newpage); + /* * Release while we have extra ref on stolen page. Otherwise * anon_pipe_buf_release() might think the page can be reused. */ pipe_buf_release(cs->pipe, buf); - get_page(newpage); - if (!(buf->flags & PIPE_BUF_FLAG_LRU)) lru_cache_add(newpage);