From 1475faff6b2973cce0ee872934cb0f0329200692 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 12 Aug 2023 08:20:04 +0200 Subject: [PATCH] 4.14-stable patches added patches: dmaengine-pl330-return-dma_paused-when-transaction-is-paused.patch nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch radix-tree-test-suite-fix-incorrect-allocation-size-for-pthreads.patch --- ...ma_paused-when-transaction-is-paused.patch | 98 ++++++++++++++ ...lfs_root-in-dirtying-inodes-via-iput.patch | 120 ++++++++++++++++++ ...correct-allocation-size-for-pthreads.patch | 41 ++++++ queue-4.14/series | 3 + 4 files changed, 262 insertions(+) create mode 100644 queue-4.14/dmaengine-pl330-return-dma_paused-when-transaction-is-paused.patch create mode 100644 queue-4.14/nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch create mode 100644 queue-4.14/radix-tree-test-suite-fix-incorrect-allocation-size-for-pthreads.patch diff --git a/queue-4.14/dmaengine-pl330-return-dma_paused-when-transaction-is-paused.patch b/queue-4.14/dmaengine-pl330-return-dma_paused-when-transaction-is-paused.patch new file mode 100644 index 00000000000..407f5ab2691 --- /dev/null +++ b/queue-4.14/dmaengine-pl330-return-dma_paused-when-transaction-is-paused.patch @@ -0,0 +1,98 @@ +From 8cda3ececf07d374774f6a13e5a94bc2dc04c26c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= +Date: Fri, 26 May 2023 13:54:34 +0300 +Subject: dmaengine: pl330: Return DMA_PAUSED when transaction is paused +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +commit 8cda3ececf07d374774f6a13e5a94bc2dc04c26c upstream. + +pl330_pause() does not set anything to indicate paused condition which +causes pl330_tx_status() to return DMA_IN_PROGRESS. This breaks 8250 +DMA flush after the fix in commit 57e9af7831dc ("serial: 8250_dma: Fix +DMA Rx rearm race"). The function comment for pl330_pause() claims +pause is supported but resume is not which is enough for 8250 DMA flush +to work as long as DMA status reports DMA_PAUSED when appropriate. + +Add PAUSED state for descriptor and mark BUSY descriptors with PAUSED +in pl330_pause(). Return DMA_PAUSED from pl330_tx_status() when the +descriptor is PAUSED. + +Reported-by: Richard Tresidder +Tested-by: Richard Tresidder +Fixes: 88987d2c7534 ("dmaengine: pl330: add DMA_PAUSE feature") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/linux-serial/f8a86ecd-64b1-573f-c2fa-59f541083f1a@electromag.com.au/ +Signed-off-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20230526105434.14959-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/pl330.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -404,6 +404,12 @@ enum desc_status { + */ + BUSY, + /* ++ * Pause was called while descriptor was BUSY. Due to hardware ++ * limitations, only termination is possible for descriptors ++ * that have been paused. ++ */ ++ PAUSED, ++ /* + * Sitting on the channel work_list but xfer done + * by PL330 core + */ +@@ -1926,7 +1932,7 @@ static inline void fill_queue(struct dma + list_for_each_entry(desc, &pch->work_list, node) { + + /* If already submitted */ +- if (desc->status == BUSY) ++ if (desc->status == BUSY || desc->status == PAUSED) + continue; + + ret = pl330_submit_req(pch->thread, desc); +@@ -2191,6 +2197,7 @@ static int pl330_pause(struct dma_chan * + { + struct dma_pl330_chan *pch = to_pchan(chan); + struct pl330_dmac *pl330 = pch->dmac; ++ struct dma_pl330_desc *desc; + unsigned long flags; + + pm_runtime_get_sync(pl330->ddma.dev); +@@ -2200,6 +2207,10 @@ static int pl330_pause(struct dma_chan * + _stop(pch->thread); + spin_unlock(&pl330->lock); + ++ list_for_each_entry(desc, &pch->work_list, node) { ++ if (desc->status == BUSY) ++ desc->status = PAUSED; ++ } + spin_unlock_irqrestore(&pch->lock, flags); + pm_runtime_mark_last_busy(pl330->ddma.dev); + pm_runtime_put_autosuspend(pl330->ddma.dev); +@@ -2290,7 +2301,7 @@ pl330_tx_status(struct dma_chan *chan, d + else if (running && desc == running) + transferred = + pl330_get_current_xferred_count(pch, desc); +- else if (desc->status == BUSY) ++ else if (desc->status == BUSY || desc->status == PAUSED) + /* + * Busy but not running means either just enqueued, + * or finished and not yet marked done +@@ -2307,6 +2318,9 @@ pl330_tx_status(struct dma_chan *chan, d + case DONE: + ret = DMA_COMPLETE; + break; ++ case PAUSED: ++ ret = DMA_PAUSED; ++ break; + case PREP: + case BUSY: + ret = DMA_IN_PROGRESS; diff --git a/queue-4.14/nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch b/queue-4.14/nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch new file mode 100644 index 00000000000..dd9b9aa033a --- /dev/null +++ b/queue-4.14/nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch @@ -0,0 +1,120 @@ +From f8654743a0e6909dc634cbfad6db6816f10f3399 Mon Sep 17 00:00:00 2001 +From: Ryusuke Konishi +Date: Sat, 29 Jul 2023 04:13:18 +0900 +Subject: nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput + +From: Ryusuke Konishi + +commit f8654743a0e6909dc634cbfad6db6816f10f3399 upstream. + +During unmount process of nilfs2, nothing holds nilfs_root structure after +nilfs2 detaches its writer in nilfs_detach_log_writer(). Previously, +nilfs_evict_inode() could cause use-after-free read for nilfs_root if +inodes are left in "garbage_list" and released by nilfs_dispose_list at +the end of nilfs_detach_log_writer(), and this bug was fixed by commit +9b5a04ac3ad9 ("nilfs2: fix use-after-free bug of nilfs_root in +nilfs_evict_inode()"). + +However, it turned out that there is another possibility of UAF in the +call path where mark_inode_dirty_sync() is called from iput(): + +nilfs_detach_log_writer() + nilfs_dispose_list() + iput() + mark_inode_dirty_sync() + __mark_inode_dirty() + nilfs_dirty_inode() + __nilfs_mark_inode_dirty() + nilfs_load_inode_block() --> causes UAF of nilfs_root struct + +This can happen after commit 0ae45f63d4ef ("vfs: add support for a +lazytime mount option"), which changed iput() to call +mark_inode_dirty_sync() on its final reference if i_state has I_DIRTY_TIME +flag and i_nlink is non-zero. + +This issue appears after commit 28a65b49eb53 ("nilfs2: do not write dirty +data after degenerating to read-only") when using the syzbot reproducer, +but the issue has potentially existed before. + +Fix this issue by adding a "purging flag" to the nilfs structure, setting +that flag while disposing the "garbage_list" and checking it in +__nilfs_mark_inode_dirty(). + +Unlike commit 9b5a04ac3ad9 ("nilfs2: fix use-after-free bug of nilfs_root +in nilfs_evict_inode()"), this patch does not rely on ns_writer to +determine whether to skip operations, so as not to break recovery on +mount. The nilfs_salvage_orphan_logs routine dirties the buffer of +salvaged data before attaching the log writer, so changing +__nilfs_mark_inode_dirty() to skip the operation when ns_writer is NULL +will cause recovery write to fail. The purpose of using the cleanup-only +flag is to allow for narrowing of such conditions. + +Link: https://lkml.kernel.org/r/20230728191318.33047-1-konishi.ryusuke@gmail.com +Signed-off-by: Ryusuke Konishi +Reported-by: syzbot+74db8b3087f293d3a13a@syzkaller.appspotmail.com +Closes: https://lkml.kernel.org/r/000000000000b4e906060113fd63@google.com +Fixes: 0ae45f63d4ef ("vfs: add support for a lazytime mount option") +Tested-by: Ryusuke Konishi +Cc: # 4.0+ +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/nilfs2/inode.c | 8 ++++++++ + fs/nilfs2/segment.c | 2 ++ + fs/nilfs2/the_nilfs.h | 2 ++ + 3 files changed, 12 insertions(+) + +--- a/fs/nilfs2/inode.c ++++ b/fs/nilfs2/inode.c +@@ -1121,9 +1121,17 @@ int nilfs_set_file_dirty(struct inode *i + + int __nilfs_mark_inode_dirty(struct inode *inode, int flags) + { ++ struct the_nilfs *nilfs = inode->i_sb->s_fs_info; + struct buffer_head *ibh; + int err; + ++ /* ++ * Do not dirty inodes after the log writer has been detached ++ * and its nilfs_root struct has been freed. ++ */ ++ if (unlikely(nilfs_purging(nilfs))) ++ return 0; ++ + err = nilfs_load_inode_block(inode, &ibh); + if (unlikely(err)) { + nilfs_msg(inode->i_sb, KERN_WARNING, +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -2859,6 +2859,7 @@ void nilfs_detach_log_writer(struct supe + nilfs_segctor_destroy(nilfs->ns_writer); + nilfs->ns_writer = NULL; + } ++ set_nilfs_purging(nilfs); + + /* Force to free the list of dirty files */ + spin_lock(&nilfs->ns_inode_lock); +@@ -2871,4 +2872,5 @@ void nilfs_detach_log_writer(struct supe + up_write(&nilfs->ns_segctor_sem); + + nilfs_dispose_list(nilfs, &garbage_list, 1); ++ clear_nilfs_purging(nilfs); + } +--- a/fs/nilfs2/the_nilfs.h ++++ b/fs/nilfs2/the_nilfs.h +@@ -37,6 +37,7 @@ enum { + THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ + THE_NILFS_GC_RUNNING, /* gc process is running */ + THE_NILFS_SB_DIRTY, /* super block is dirty */ ++ THE_NILFS_PURGING, /* disposing dirty files for cleanup */ + }; + + /** +@@ -216,6 +217,7 @@ THE_NILFS_FNS(INIT, init) + THE_NILFS_FNS(DISCONTINUED, discontinued) + THE_NILFS_FNS(GC_RUNNING, gc_running) + THE_NILFS_FNS(SB_DIRTY, sb_dirty) ++THE_NILFS_FNS(PURGING, purging) + + /* + * Mount option operations diff --git a/queue-4.14/radix-tree-test-suite-fix-incorrect-allocation-size-for-pthreads.patch b/queue-4.14/radix-tree-test-suite-fix-incorrect-allocation-size-for-pthreads.patch new file mode 100644 index 00000000000..44287354804 --- /dev/null +++ b/queue-4.14/radix-tree-test-suite-fix-incorrect-allocation-size-for-pthreads.patch @@ -0,0 +1,41 @@ +From cac7ea57a06016e4914848b707477fb07ee4ae1c Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Thu, 27 Jul 2023 17:09:30 +0100 +Subject: radix tree test suite: fix incorrect allocation size for pthreads + +From: Colin Ian King + +commit cac7ea57a06016e4914848b707477fb07ee4ae1c upstream. + +Currently the pthread allocation for each array item is based on the size +of a pthread_t pointer and should be the size of the pthread_t structure, +so the allocation is under-allocating the correct size. Fix this by using +the size of each element in the pthreads array. + +Static analysis cppcheck reported: +tools/testing/radix-tree/regression1.c:180:2: warning: Size of pointer +'threads' used instead of size of its data. [pointerSize] + +Link: https://lkml.kernel.org/r/20230727160930.632674-1-colin.i.king@gmail.com +Fixes: 1366c37ed84b ("radix tree test harness") +Signed-off-by: Colin Ian King +Cc: Konstantin Khlebnikov +Cc: Matthew Wilcox (Oracle) +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/radix-tree/regression1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/testing/radix-tree/regression1.c ++++ b/tools/testing/radix-tree/regression1.c +@@ -198,7 +198,7 @@ void regression1_test(void) + nr_threads = 2; + pthread_barrier_init(&worker_barrier, NULL, nr_threads); + +- threads = malloc(nr_threads * sizeof(pthread_t *)); ++ threads = malloc(nr_threads * sizeof(*threads)); + + for (i = 0; i < nr_threads; i++) { + arg = i; diff --git a/queue-4.14/series b/queue-4.14/series index 434d3f46546..c3a3f19836e 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -1,3 +1,6 @@ sparc-fix-up-arch_cpu_finalize_init-build-breakage.patch mmc-moxart-read-scr-register-without-changing-byte-order.patch ipv6-adjust-ndisc_is_useropt-to-also-return-true-for-pio.patch +dmaengine-pl330-return-dma_paused-when-transaction-is-paused.patch +radix-tree-test-suite-fix-incorrect-allocation-size-for-pthreads.patch +nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch -- 2.47.3