--- /dev/null
+From stable+bounces-114255-greg=kroah.com@vger.kernel.org Fri Feb 7 15:25:29 2025
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Fri, 7 Feb 2025 23:23:48 +0900
+Subject: nilfs2: do not force clear folio if buffer is referenced
+To: stable@vger.kernel.org, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Message-ID: <20250207142512.6129-3-konishi.ryusuke@gmail.com>
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+commit ca76bb226bf47ff04c782cacbd299f12ddee1ec1 upstream.
+
+Patch series "nilfs2: protect busy buffer heads from being force-cleared".
+
+This series fixes the buffer head state inconsistency issues reported by
+syzbot that occurs when the filesystem is corrupted and falls back to
+read-only, and the associated buffer head use-after-free issue.
+
+This patch (of 2):
+
+Syzbot has reported that after nilfs2 detects filesystem corruption and
+falls back to read-only, inconsistencies in the buffer state may occur.
+
+One of the inconsistencies is that when nilfs2 calls mark_buffer_dirty()
+to set a data or metadata buffer as dirty, but it detects that the buffer
+is not in the uptodate state:
+
+ WARNING: CPU: 0 PID: 6049 at fs/buffer.c:1177 mark_buffer_dirty+0x2e5/0x520
+ fs/buffer.c:1177
+ ...
+ Call Trace:
+ <TASK>
+ nilfs_palloc_commit_alloc_entry+0x4b/0x160 fs/nilfs2/alloc.c:598
+ nilfs_ifile_create_inode+0x1dd/0x3a0 fs/nilfs2/ifile.c:73
+ nilfs_new_inode+0x254/0x830 fs/nilfs2/inode.c:344
+ nilfs_mkdir+0x10d/0x340 fs/nilfs2/namei.c:218
+ vfs_mkdir+0x2f9/0x4f0 fs/namei.c:4257
+ do_mkdirat+0x264/0x3a0 fs/namei.c:4280
+ __do_sys_mkdirat fs/namei.c:4295 [inline]
+ __se_sys_mkdirat fs/namei.c:4293 [inline]
+ __x64_sys_mkdirat+0x87/0xa0 fs/namei.c:4293
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+The other is when nilfs_btree_propagate(), which propagates the dirty
+state to the ancestor nodes of a b-tree that point to a dirty buffer,
+detects that the origin buffer is not dirty, even though it should be:
+
+ WARNING: CPU: 0 PID: 5245 at fs/nilfs2/btree.c:2089
+ nilfs_btree_propagate+0xc79/0xdf0 fs/nilfs2/btree.c:2089
+ ...
+ Call Trace:
+ <TASK>
+ nilfs_bmap_propagate+0x75/0x120 fs/nilfs2/bmap.c:345
+ nilfs_collect_file_data+0x4d/0xd0 fs/nilfs2/segment.c:587
+ nilfs_segctor_apply_buffers+0x184/0x340 fs/nilfs2/segment.c:1006
+ nilfs_segctor_scan_file+0x28c/0xa50 fs/nilfs2/segment.c:1045
+ nilfs_segctor_collect_blocks fs/nilfs2/segment.c:1216 [inline]
+ nilfs_segctor_collect fs/nilfs2/segment.c:1540 [inline]
+ nilfs_segctor_do_construct+0x1c28/0x6b90 fs/nilfs2/segment.c:2115
+ nilfs_segctor_construct+0x181/0x6b0 fs/nilfs2/segment.c:2479
+ nilfs_segctor_thread_construct fs/nilfs2/segment.c:2587 [inline]
+ nilfs_segctor_thread+0x69e/0xe80 fs/nilfs2/segment.c:2701
+ kthread+0x2f0/0x390 kernel/kthread.c:389
+ ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+ </TASK>
+
+Both of these issues are caused by the callbacks that handle the
+page/folio write requests, forcibly clear various states, including the
+working state of the buffers they hold, at unexpected times when they
+detect read-only fallback.
+
+Fix these issues by checking if the buffer is referenced before clearing
+the page/folio state, and skipping the clear if it is.
+
+[konishi.ryusuke@gmail.com: adjusted for page/folio conversion]
+Link: https://lkml.kernel.org/r/20250107200202.6432-1-konishi.ryusuke@gmail.com
+Link: https://lkml.kernel.org/r/20250107200202.6432-2-konishi.ryusuke@gmail.com
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Reported-by: syzbot+b2b14916b77acf8626d7@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=b2b14916b77acf8626d7
+Reported-by: syzbot+d98fd19acd08b36ff422@syzkaller.appspotmail.com
+Link: https://syzkaller.appspot.com/bug?extid=d98fd19acd08b36ff422
+Fixes: 8c26c4e2694a ("nilfs2: fix issue with flush kernel thread after remount in RO mode because of driver's internal error or metadata corruption")
+Tested-by: syzbot+b2b14916b77acf8626d7@syzkaller.appspotmail.com
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/page.c | 35 +++++++++++++++++++++++++++++------
+ 1 file changed, 29 insertions(+), 6 deletions(-)
+
+--- a/fs/nilfs2/page.c
++++ b/fs/nilfs2/page.c
+@@ -388,24 +388,44 @@ void nilfs_clear_dirty_pages(struct addr
+ /**
+ * nilfs_clear_dirty_page - discard dirty page
+ * @page: dirty page that will be discarded
++ *
++ * nilfs_clear_dirty_page() clears working states including dirty state for
++ * the page and its buffers. If the page has buffers, clear only if it is
++ * confirmed that none of the buffer heads are busy (none have valid
++ * references and none are locked).
+ */
+ void nilfs_clear_dirty_page(struct page *page)
+ {
+ BUG_ON(!PageLocked(page));
+
+- ClearPageUptodate(page);
+- ClearPageMappedToDisk(page);
+- ClearPageChecked(page);
+-
+ if (page_has_buffers(page)) {
+- struct buffer_head *bh, *head;
++ struct buffer_head *bh, *head = page_buffers(page);
+ const unsigned long clear_bits =
+ (BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
+ BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
+ BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected) |
+ BIT(BH_Delay));
++ bool busy, invalidated = false;
+
+- bh = head = page_buffers(page);
++recheck_buffers:
++ busy = false;
++ bh = head;
++ do {
++ if (atomic_read(&bh->b_count) | buffer_locked(bh)) {
++ busy = true;
++ break;
++ }
++ } while (bh = bh->b_this_page, bh != head);
++
++ if (busy) {
++ if (invalidated)
++ return;
++ invalidate_bh_lrus();
++ invalidated = true;
++ goto recheck_buffers;
++ }
++
++ bh = head;
+ do {
+ lock_buffer(bh);
+ set_mask_bits(&bh->b_state, clear_bits, 0);
+@@ -413,6 +433,9 @@ void nilfs_clear_dirty_page(struct page
+ } while (bh = bh->b_this_page, bh != head);
+ }
+
++ ClearPageUptodate(page);
++ ClearPageMappedToDisk(page);
++ ClearPageChecked(page);
+ __nilfs_clear_page_dirty(page);
+ }
+
--- /dev/null
+From stable+bounces-114254-greg=kroah.com@vger.kernel.org Fri Feb 7 15:25:28 2025
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Fri, 7 Feb 2025 23:23:47 +0900
+Subject: nilfs2: do not output warnings when clearing dirty buffers
+To: stable@vger.kernel.org, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Message-ID: <20250207142512.6129-2-konishi.ryusuke@gmail.com>
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+commit 299910dcb4525ac0274f3efa9527876315ba4f67 upstream.
+
+After detecting file system corruption and degrading to a read-only mount,
+dirty folios and buffers in the page cache are cleared, and a large number
+of warnings are output at that time, often filling up the kernel log.
+
+In this case, since the degrading to a read-only mount is output to the
+kernel log, these warnings are not very meaningful, and are rather a
+nuisance in system management and debugging.
+
+The related nilfs2-specific page/folio routines have a silent argument
+that suppresses the warning output, but since it is not currently used
+meaningfully, remove both the silent argument and the warning output.
+
+[konishi.ryusuke@gmail.com: adjusted for page/folio conversion]
+Link: https://lkml.kernel.org/r/20240816090128.4561-1-konishi.ryusuke@gmail.com
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: ca76bb226bf4 ("nilfs2: do not force clear folio if buffer is referenced")
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/inode.c | 4 ++--
+ fs/nilfs2/mdt.c | 6 +++---
+ fs/nilfs2/page.c | 20 +++-----------------
+ fs/nilfs2/page.h | 4 ++--
+ 4 files changed, 10 insertions(+), 24 deletions(-)
+
+--- a/fs/nilfs2/inode.c
++++ b/fs/nilfs2/inode.c
+@@ -162,7 +162,7 @@ static int nilfs_writepages(struct addre
+ int err = 0;
+
+ if (sb_rdonly(inode->i_sb)) {
+- nilfs_clear_dirty_pages(mapping, false);
++ nilfs_clear_dirty_pages(mapping);
+ return -EROFS;
+ }
+
+@@ -185,7 +185,7 @@ static int nilfs_writepage(struct page *
+ * have dirty pages that try to be flushed in background.
+ * So, here we simply discard this dirty page.
+ */
+- nilfs_clear_dirty_page(page, false);
++ nilfs_clear_dirty_page(page);
+ unlock_page(page);
+ return -EROFS;
+ }
+--- a/fs/nilfs2/mdt.c
++++ b/fs/nilfs2/mdt.c
+@@ -410,7 +410,7 @@ nilfs_mdt_write_page(struct page *page,
+ * have dirty pages that try to be flushed in background.
+ * So, here we simply discard this dirty page.
+ */
+- nilfs_clear_dirty_page(page, false);
++ nilfs_clear_dirty_page(page);
+ unlock_page(page);
+ return -EROFS;
+ }
+@@ -632,10 +632,10 @@ void nilfs_mdt_restore_from_shadow_map(s
+ if (mi->mi_palloc_cache)
+ nilfs_palloc_clear_cache(inode);
+
+- nilfs_clear_dirty_pages(inode->i_mapping, true);
++ nilfs_clear_dirty_pages(inode->i_mapping);
+ nilfs_copy_back_pages(inode->i_mapping, shadow->inode->i_mapping);
+
+- nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping, true);
++ nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping);
+ nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping,
+ NILFS_I(shadow->inode)->i_assoc_inode->i_mapping);
+
+--- a/fs/nilfs2/page.c
++++ b/fs/nilfs2/page.c
+@@ -354,9 +354,8 @@ repeat:
+ /**
+ * nilfs_clear_dirty_pages - discard dirty pages in address space
+ * @mapping: address space with dirty pages for discarding
+- * @silent: suppress [true] or print [false] warning messages
+ */
+-void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
++void nilfs_clear_dirty_pages(struct address_space *mapping)
+ {
+ struct pagevec pvec;
+ unsigned int i;
+@@ -377,7 +376,7 @@ void nilfs_clear_dirty_pages(struct addr
+ * was acquired. Skip processing in that case.
+ */
+ if (likely(page->mapping == mapping))
+- nilfs_clear_dirty_page(page, silent);
++ nilfs_clear_dirty_page(page);
+
+ unlock_page(page);
+ }
+@@ -389,19 +388,11 @@ void nilfs_clear_dirty_pages(struct addr
+ /**
+ * nilfs_clear_dirty_page - discard dirty page
+ * @page: dirty page that will be discarded
+- * @silent: suppress [true] or print [false] warning messages
+ */
+-void nilfs_clear_dirty_page(struct page *page, bool silent)
++void nilfs_clear_dirty_page(struct page *page)
+ {
+- struct inode *inode = page->mapping->host;
+- struct super_block *sb = inode->i_sb;
+-
+ BUG_ON(!PageLocked(page));
+
+- if (!silent)
+- nilfs_warn(sb, "discard dirty page: offset=%lld, ino=%lu",
+- page_offset(page), inode->i_ino);
+-
+ ClearPageUptodate(page);
+ ClearPageMappedToDisk(page);
+ ClearPageChecked(page);
+@@ -417,11 +408,6 @@ void nilfs_clear_dirty_page(struct page
+ bh = head = page_buffers(page);
+ do {
+ lock_buffer(bh);
+- if (!silent)
+- nilfs_warn(sb,
+- "discard dirty block: blocknr=%llu, size=%zu",
+- (u64)bh->b_blocknr, bh->b_size);
+-
+ set_mask_bits(&bh->b_state, clear_bits, 0);
+ unlock_buffer(bh);
+ } while (bh = bh->b_this_page, bh != head);
+--- a/fs/nilfs2/page.h
++++ b/fs/nilfs2/page.h
+@@ -41,8 +41,8 @@ void nilfs_page_bug(struct page *);
+
+ int nilfs_copy_dirty_pages(struct address_space *, struct address_space *);
+ void nilfs_copy_back_pages(struct address_space *, struct address_space *);
+-void nilfs_clear_dirty_page(struct page *, bool);
+-void nilfs_clear_dirty_pages(struct address_space *, bool);
++void nilfs_clear_dirty_page(struct page *page);
++void nilfs_clear_dirty_pages(struct address_space *mapping);
+ void nilfs_mapping_init(struct address_space *mapping, struct inode *inode);
+ unsigned int nilfs_page_count_clean_buffers(struct page *, unsigned int,
+ unsigned int);
--- /dev/null
+From stable+bounces-114256-greg=kroah.com@vger.kernel.org Fri Feb 7 15:25:30 2025
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Fri, 7 Feb 2025 23:23:49 +0900
+Subject: nilfs2: protect access to buffers with no active references
+To: stable@vger.kernel.org, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Message-ID: <20250207142512.6129-4-konishi.ryusuke@gmail.com>
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+commit 367a9bffabe08c04f6d725032cce3d891b2b9e1a upstream.
+
+nilfs_lookup_dirty_data_buffers(), which iterates through the buffers
+attached to dirty data folios/pages, accesses the attached buffers without
+locking the folios/pages.
+
+For data cache, nilfs_clear_folio_dirty() may be called asynchronously
+when the file system degenerates to read only, so
+nilfs_lookup_dirty_data_buffers() still has the potential to cause use
+after free issues when buffers lose the protection of their dirty state
+midway due to this asynchronous clearing and are unintentionally freed by
+try_to_free_buffers().
+
+Eliminate this race issue by adjusting the lock section in this function.
+
+[konishi.ryusuke@gmail.com: adjusted for page/folio conversion]
+Link: https://lkml.kernel.org/r/20250107200202.6432-3-konishi.ryusuke@gmail.com
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Fixes: 8c26c4e2694a ("nilfs2: fix issue with flush kernel thread after remount in RO mode because of driver's internal error or metadata corruption")
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/segment.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/nilfs2/segment.c
++++ b/fs/nilfs2/segment.c
+@@ -732,7 +732,6 @@ static size_t nilfs_lookup_dirty_data_bu
+ }
+ if (!page_has_buffers(page))
+ create_empty_buffers(page, i_blocksize(inode), 0);
+- unlock_page(page);
+
+ bh = head = page_buffers(page);
+ do {
+@@ -742,11 +741,14 @@ static size_t nilfs_lookup_dirty_data_bu
+ list_add_tail(&bh->b_assoc_buffers, listp);
+ ndirties++;
+ if (unlikely(ndirties >= nlimit)) {
++ unlock_page(page);
+ pagevec_release(&pvec);
+ cond_resched();
+ return ndirties;
+ }
+ } while (bh = bh->b_this_page, bh != head);
++
++ unlock_page(page);
+ }
+ pagevec_release(&pvec);
+ cond_resched();
kdb-do-not-assume-write-callback-available.patch
x86-static-call-remove-early_boot_irqs_disabled-check-to-fix-xen-pvh-dom0.patch
alpha-replace-hardcoded-stack-offsets-with-autogenerated-ones.patch
+nilfs2-do-not-output-warnings-when-clearing-dirty-buffers.patch
+nilfs2-do-not-force-clear-folio-if-buffer-is-referenced.patch
+nilfs2-protect-access-to-buffers-with-no-active-references.patch