]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs/ntfs3: zero stale pagecache beyond valid data length
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Fri, 22 May 2026 12:46:23 +0000 (14:46 +0200)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Tue, 2 Jun 2026 15:02:31 +0000 (17:02 +0200)
Zero cached folios beyond the valid data length when closing a writable
mapping. This keeps cached data beyond initialized file contents zeroed
and prevents stale pagecache exposure after mmap-based writes.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/file.c

index f421a36b1ed63fbec336c3fadcef00be801e4cf9..2d1de3739ffea5c4bc42e6554fcc5f9ea4474946 100644 (file)
@@ -323,18 +323,44 @@ static int ntfs_extend_initialized_size(struct file *file,
        return 0;
 }
 
+/* Zero pagecache after 'from'. */
+static void ntfs_zero_tail(struct address_space *mapping, loff_t from)
+{
+       struct folio_batch fbatch;
+       pgoff_t index = from >> PAGE_SHIFT;
+       unsigned nr, i;
+
+       folio_batch_init(&fbatch);
+
+       nr = filemap_get_folios(mapping, &index, -1, &fbatch);
+
+       for (i = 0; i < nr; i++) {
+               struct folio *folio = fbatch.folios[i];
+               u32 st = folio_pos(folio) < from ?
+                                offset_in_folio(folio, from) :
+                                0;
+
+               folio_lock(folio);
+               folio_zero_segment(folio, st, folio_size(folio));
+
+               folio_unlock(folio);
+       }
+       folio_batch_release(&fbatch);
+}
+
 static void ntfs_filemap_close(struct vm_area_struct *vma)
 {
        struct inode *inode = file_inode(vma->vm_file);
        struct ntfs_inode *ni = ntfs_i(inode);
+       u64 i_size = i_size_read(inode);
        u64 from = (u64)vma->vm_pgoff << PAGE_SHIFT;
-       u64 to = min_t(u64, i_size_read(inode),
-                      from + vma->vm_end - vma->vm_start);
+       u64 to = min(i_size, from + vma->vm_end - vma->vm_start);
 
        if (ni->i_valid < to) {
                ni->i_valid = to;
                mark_inode_dirty(inode);
        }
+       ntfs_zero_tail(inode->i_mapping, ni->i_valid);
 }
 
 /* Copy of generic_file_vm_ops. */