]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 2 Jan 2024 14:34:03 +0000 (15:34 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 2 Jan 2024 14:34:03 +0000 (15:34 +0100)
added patches:
mm-filemap-avoid-buffered-read-write-race-to-read-inconsistent-data.patch

queue-5.15/mm-filemap-avoid-buffered-read-write-race-to-read-inconsistent-data.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/mm-filemap-avoid-buffered-read-write-race-to-read-inconsistent-data.patch b/queue-5.15/mm-filemap-avoid-buffered-read-write-race-to-read-inconsistent-data.patch
new file mode 100644 (file)
index 0000000..cbfdc03
--- /dev/null
@@ -0,0 +1,106 @@
+From e2c27b803bb664748e090d99042ac128b3f88d92 Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Wed, 13 Dec 2023 14:23:24 +0800
+Subject: mm/filemap: avoid buffered read/write race to read inconsistent data
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit e2c27b803bb664748e090d99042ac128b3f88d92 upstream.
+
+The following concurrency may cause the data read to be inconsistent with
+the data on disk:
+
+             cpu1                           cpu2
+------------------------------|------------------------------
+                               // Buffered write 2048 from 0
+                               ext4_buffered_write_iter
+                                generic_perform_write
+                                 copy_page_from_iter_atomic
+                                 ext4_da_write_end
+                                  ext4_da_do_write_end
+                                   block_write_end
+                                    __block_commit_write
+                                     folio_mark_uptodate
+// Buffered read 4096 from 0          smp_wmb()
+ext4_file_read_iter                   set_bit(PG_uptodate, folio_flags)
+ generic_file_read_iter            i_size_write // 2048
+  filemap_read                     unlock_page(page)
+   filemap_get_pages
+    filemap_get_read_batch
+    folio_test_uptodate(folio)
+     ret = test_bit(PG_uptodate, folio_flags)
+     if (ret)
+      smp_rmb();
+      // Ensure that the data in page 0-2048 is up-to-date.
+
+                               // New buffered write 2048 from 2048
+                               ext4_buffered_write_iter
+                                generic_perform_write
+                                 copy_page_from_iter_atomic
+                                 ext4_da_write_end
+                                  ext4_da_do_write_end
+                                   block_write_end
+                                    __block_commit_write
+                                     folio_mark_uptodate
+                                      smp_wmb()
+                                      set_bit(PG_uptodate, folio_flags)
+                                   i_size_write // 4096
+                                   unlock_page(page)
+
+   isize = i_size_read(inode) // 4096
+   // Read the latest isize 4096, but without smp_rmb(), there may be
+   // Load-Load disorder resulting in the data in the 2048-4096 range
+   // in the page is not up-to-date.
+   copy_page_to_iter
+   // copyout 4096
+
+In the concurrency above, we read the updated i_size, but there is no read
+barrier to ensure that the data in the page is the same as the i_size at
+this point, so we may copy the unsynchronized page out.  Hence adding the
+missing read memory barrier to fix this.
+
+This is a Load-Load reordering issue, which only occurs on some weak
+mem-ordering architectures (e.g.  ARM64, ALPHA), but not on strong
+mem-ordering architectures (e.g.  X86).  And theoretically the problem
+doesn't only happen on ext4, filesystems that call filemap_read() but
+don't hold inode lock (e.g.  btrfs, f2fs, ubifs ...) will have this
+problem, while filesystems with inode lock (e.g.  xfs, nfs) won't have
+this problem.
+
+Link: https://lkml.kernel.org/r/20231213062324.739009-1-libaokun1@huawei.com
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: Andreas Dilger <adilger.kernel@dilger.ca>
+Cc: Christoph Hellwig <hch@infradead.org>
+Cc: Dave Chinner <david@fromorbit.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Cc: Theodore Ts'o <tytso@mit.edu>
+Cc: yangerkun <yangerkun@huawei.com>
+Cc: Yu Kuai <yukuai3@huawei.com>
+Cc: Zhang Yi <yi.zhang@huawei.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/filemap.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -2649,6 +2649,15 @@ ssize_t filemap_read(struct kiocb *iocb,
+               end_offset = min_t(loff_t, isize, iocb->ki_pos + iter->count);
+               /*
++               * Pairs with a barrier in
++               * block_write_end()->mark_buffer_dirty() or other page
++               * dirtying routines like iomap_write_end() to ensure
++               * changes to page contents are visible before we see
++               * increased inode size.
++               */
++              smp_rmb();
++
++              /*
+                * Once we start copying data, we don't want to be touching any
+                * cachelines that might be contended:
+                */
index 37f1c82b636293a5f031ae04cd164688c90f4b69..667253f8b8e20390a2226f0bf6e51c020f37685a 100644 (file)
@@ -83,3 +83,4 @@ smb-client-fix-oob-in-smb2_query_info_init.patch
 smb-client-fix-oob-in-smbcalcsize.patch
 bluetooth-af_bluetooth-fix-use-after-free-in-bt_sock.patch
 device-property-add-const-qualifier-to-device_get_ma.patch
+mm-filemap-avoid-buffered-read-write-race-to-read-inconsistent-data.patch