From: Greg Kroah-Hartman Date: Mon, 22 Jun 2026 09:01:40 +0000 (+0200) Subject: 7.1-stable patches X-Git-Tag: v6.18.37~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=493acf9892550eabf017889d4a525b15acfd5ae3;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches added patches: fuse-re-lock-request-before-replacing-page-cache-folio.patch --- diff --git a/queue-7.1/fuse-re-lock-request-before-replacing-page-cache-folio.patch b/queue-7.1/fuse-re-lock-request-before-replacing-page-cache-folio.patch new file mode 100644 index 0000000000..47737cfaf9 --- /dev/null +++ b/queue-7.1/fuse-re-lock-request-before-replacing-page-cache-folio.patch @@ -0,0 +1,67 @@ +From a078484921052d0badd827fcc2770b5cfc1d4120 Mon Sep 17 00:00:00 2001 +From: Joanne Koong +Date: Mon, 18 May 2026 22:28:06 -0700 +Subject: fuse: re-lock request before replacing page cache folio + +From: Joanne Koong + +commit a078484921052d0badd827fcc2770b5cfc1d4120 upstream. + +fuse_try_move_folio() unlocks the request on entry but does not +re-lock it on the success path. This means fuse_chan_abort() can end the +request and free the fuse_io_args (eg fuse_readpages_end()) while the +subsequent copy chain logic after fuse_try_move_folio() accesses the +fuse_io_args, leading to use-after-free issues. + +Fix this by calling lock_request() before replace_page_cache_folio(). +This ensures the request is locked on the success path which will +prevent the fuse_io_args from being freed while the later copying logic +runs, and also ensures that the ap->folios[i]->mapping is never null +since ap->folios[i] will always point to the newfolio after +replace_page_cache_folio(). + +Fixes: ce534fb05292 ("fuse: allow splice to move pages") +Cc: stable@vger.kernel.org +Reported-by: Lei Lu +Signed-off-by: Joanne Koong +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/fuse/dev.c | 19 +++++-------------- + 1 file changed, 5 insertions(+), 14 deletions(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1037,6 +1037,10 @@ static int fuse_try_move_folio(struct fu + if (WARN_ON(folio_test_mlocked(oldfolio))) + goto out_fallback_unlock; + ++ err = lock_request(cs->req); ++ if (err) ++ goto out_fallback_unlock; ++ + replace_page_cache_folio(oldfolio, newfolio); + + folio_get(newfolio); +@@ -1050,20 +1054,7 @@ static int fuse_try_move_folio(struct fu + */ + pipe_buf_release(cs->pipe, buf); + +- err = 0; +- spin_lock(&cs->req->waitq.lock); +- if (test_bit(FR_ABORTED, &cs->req->flags)) +- err = -ENOENT; +- else +- *foliop = newfolio; +- spin_unlock(&cs->req->waitq.lock); +- +- if (err) { +- folio_unlock(newfolio); +- folio_put(newfolio); +- goto out_put_old; +- } +- ++ *foliop = newfolio; + folio_unlock(oldfolio); + /* Drop ref for ap->pages[] array */ + folio_put(oldfolio); diff --git a/queue-7.1/series b/queue-7.1/series index 7dd13f0fed..cc7e8535e2 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -1 +1,2 @@ io_uring-net-avoid-msghdr-on-op_connect-op_bind-asyn.patch +fuse-re-lock-request-before-replacing-page-cache-folio.patch