]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Feb 2025 17:35:40 +0000 (18:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Feb 2025 17:35:40 +0000 (18:35 +0100)
added patches:
i3c-master-cdns-fix-use-after-free-vulnerability-in-cdns_i3c_master-driver-due-to-race-condition.patch
nilfs2-do-not-force-clear-folio-if-buffer-is-referenced.patch
nilfs2-do-not-output-warnings-when-clearing-dirty-buffers.patch
nilfs2-protect-access-to-buffers-with-no-active-references.patch

queue-6.1/i3c-master-cdns-fix-use-after-free-vulnerability-in-cdns_i3c_master-driver-due-to-race-condition.patch [new file with mode: 0644]
queue-6.1/nilfs2-do-not-force-clear-folio-if-buffer-is-referenced.patch [new file with mode: 0644]
queue-6.1/nilfs2-do-not-output-warnings-when-clearing-dirty-buffers.patch [new file with mode: 0644]
queue-6.1/nilfs2-protect-access-to-buffers-with-no-active-references.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/i3c-master-cdns-fix-use-after-free-vulnerability-in-cdns_i3c_master-driver-due-to-race-condition.patch b/queue-6.1/i3c-master-cdns-fix-use-after-free-vulnerability-in-cdns_i3c_master-driver-due-to-race-condition.patch
new file mode 100644 (file)
index 0000000..e244f61
--- /dev/null
@@ -0,0 +1,50 @@
+From 609366e7a06d035990df78f1562291c3bf0d4a12 Mon Sep 17 00:00:00 2001
+From: Kaixin Wang <kxwang23@m.fudan.edu.cn>
+Date: Wed, 11 Sep 2024 23:35:44 +0800
+Subject: i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master Driver Due to Race Condition
+
+From: Kaixin Wang <kxwang23@m.fudan.edu.cn>
+
+commit 609366e7a06d035990df78f1562291c3bf0d4a12 upstream.
+
+In the cdns_i3c_master_probe function, &master->hj_work is bound with
+cdns_i3c_master_hj. And cdns_i3c_master_interrupt can call
+cnds_i3c_master_demux_ibis function to start the work.
+
+If we remove the module which will call cdns_i3c_master_remove to
+make cleanup, it will free master->base through i3c_master_unregister
+while the work mentioned above will be used. The sequence of operations
+that may lead to a UAF bug is as follows:
+
+CPU0                                      CPU1
+
+                                     | cdns_i3c_master_hj
+cdns_i3c_master_remove               |
+i3c_master_unregister(&master->base) |
+device_unregister(&master->dev)      |
+device_release                       |
+//free master->base                  |
+                                     | i3c_master_do_daa(&master->base)
+                                     | //use master->base
+
+Fix it by ensuring that the work is canceled before proceeding with
+the cleanup in cdns_i3c_master_remove.
+
+Signed-off-by: Kaixin Wang <kxwang23@m.fudan.edu.cn>
+Link: https://lore.kernel.org/r/20240911153544.848398-1-kxwang23@m.fudan.edu.cn
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i3c/master/i3c-master-cdns.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/i3c/master/i3c-master-cdns.c
++++ b/drivers/i3c/master/i3c-master-cdns.c
+@@ -1667,6 +1667,7 @@ static int cdns_i3c_master_remove(struct
+ {
+       struct cdns_i3c_master *master = platform_get_drvdata(pdev);
++      cancel_work_sync(&master->hj_work);
+       i3c_master_unregister(&master->base);
+       clk_disable_unprepare(master->sysclk);
diff --git a/queue-6.1/nilfs2-do-not-force-clear-folio-if-buffer-is-referenced.patch b/queue-6.1/nilfs2-do-not-force-clear-folio-if-buffer-is-referenced.patch
new file mode 100644 (file)
index 0000000..8bb3cf4
--- /dev/null
@@ -0,0 +1,156 @@
+From konishi.ryusuke@gmail.com Thu Feb  6 19:16:10 2025
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Fri,  7 Feb 2025 03:14:31 +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: <20250206181559.7166-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);
+ }
diff --git a/queue-6.1/nilfs2-do-not-output-warnings-when-clearing-dirty-buffers.patch b/queue-6.1/nilfs2-do-not-output-warnings-when-clearing-dirty-buffers.patch
new file mode 100644 (file)
index 0000000..3932011
--- /dev/null
@@ -0,0 +1,149 @@
+From konishi.ryusuke@gmail.com Thu Feb  6 19:16:08 2025
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Fri,  7 Feb 2025 03:14:30 +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: <20250206181559.7166-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
+@@ -411,7 +411,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;
+       }
+@@ -634,10 +634,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);
+ unsigned int nilfs_page_count_clean_buffers(struct page *, unsigned int,
+                                           unsigned int);
+ unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
diff --git a/queue-6.1/nilfs2-protect-access-to-buffers-with-no-active-references.patch b/queue-6.1/nilfs2-protect-access-to-buffers-with-no-active-references.patch
new file mode 100644 (file)
index 0000000..c080500
--- /dev/null
@@ -0,0 +1,60 @@
+From konishi.ryusuke@gmail.com Thu Feb  6 19:16:13 2025
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Fri,  7 Feb 2025 03:14:32 +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: <20250206181559.7166-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();
index 6a78b7de95547be48eef514d5ad90974e66c8728..4d26f48a37d5980e6e74471054e5a5260960fd93 100644 (file)
@@ -562,3 +562,7 @@ iommu-return-right-value-in-iommu_sva_bind_device.patch
 arm64-tegra-fix-typo-in-tegra234-dce-fabric-compatible.patch
 mm-gup-fix-infinite-loop-within-__get_longterm_locked.patch
 alpha-replace-hardcoded-stack-offsets-with-autogenerated-ones.patch
+i3c-master-cdns-fix-use-after-free-vulnerability-in-cdns_i3c_master-driver-due-to-race-condition.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