fuse: fix fuse_fill_write_pages() upper bound calculation
authorJoanne Koong <joannelkoong@gmail.com>
Sat, 14 Jun 2025 00:01:14 +0000 (17:01 -0700)
committerChristian Brauner <brauner@kernel.org>
Tue, 24 Jun 2025 09:07:19 +0000 (11:07 +0200)
This fixes a bug in commit 63c69ad3d18a ("fuse: refactor
fuse_fill_write_pages()") where max_pages << PAGE_SHIFT is mistakenly
used as the calculation for the max_pages upper limit but there's the
possibility that copy_folio_from_iter_atomic() may copy over bytes
from the iov_iter that are less than the full length of the folio,
which would lead to exceeding max_pages.

This commit fixes it by adding a 'ap->num_folios < max_folios' check.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Link: https://lore.kernel.org/20250614000114.910380-1-joannelkoong@gmail.com
Fixes: 63c69ad3d18a ("fuse: refactor fuse_fill_write_pages()")
Tested-by: Brian Foster <bfoster@redhat.com>
Reported-by: Brian Foster <bfoster@redhat.com>
Closes: https://lore.kernel.org/linux-fsdevel/aEq4haEQScwHIWK6@bfoster/
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/fuse/file.c

index f102afc03359b232738a2f1b656f9318b1af8207..47006d0753f1cdbf8155ae6dd7086be42e16a52e 100644 (file)
@@ -1147,7 +1147,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
 static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
                                     struct address_space *mapping,
                                     struct iov_iter *ii, loff_t pos,
-                                    unsigned int max_pages)
+                                    unsigned int max_folios)
 {
        struct fuse_args_pages *ap = &ia->ap;
        struct fuse_conn *fc = get_fuse_conn(mapping->host);
@@ -1157,12 +1157,11 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
        int err = 0;
 
        num = min(iov_iter_count(ii), fc->max_write);
-       num = min(num, max_pages << PAGE_SHIFT);
 
        ap->args.in_pages = true;
        ap->descs[0].offset = offset;
 
-       while (num) {
+       while (num && ap->num_folios < max_folios) {
                size_t tmp;
                struct folio *folio;
                pgoff_t index = pos >> PAGE_SHIFT;