From: Greg Kroah-Hartman Date: Mon, 29 Dec 2025 16:02:58 +0000 (+0100) Subject: 6.12-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8c365346f7aee5cc54df9acba4941a306b5350e;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: fuse-fix-readahead-reclaim-deadlock.patch iommu-mediatek-fix-use-after-free-on-probe-deferral.patch --- diff --git a/queue-6.12/fuse-fix-readahead-reclaim-deadlock.patch b/queue-6.12/fuse-fix-readahead-reclaim-deadlock.patch new file mode 100644 index 0000000000..28df6d3f23 --- /dev/null +++ b/queue-6.12/fuse-fix-readahead-reclaim-deadlock.patch @@ -0,0 +1,116 @@ +From bd5603eaae0aabf527bfb3ce1bb07e979ce5bd50 Mon Sep 17 00:00:00 2001 +From: Joanne Koong +Date: Fri, 10 Oct 2025 15:07:38 -0700 +Subject: fuse: fix readahead reclaim deadlock + +From: Joanne Koong + +commit bd5603eaae0aabf527bfb3ce1bb07e979ce5bd50 upstream. + +Commit e26ee4efbc79 ("fuse: allocate ff->release_args only if release is +needed") skips allocating ff->release_args if the server does not +implement open. However in doing so, fuse_prepare_release() now skips +grabbing the reference on the inode, which makes it possible for an +inode to be evicted from the dcache while there are inflight readahead +requests. This causes a deadlock if the server triggers reclaim while +servicing the readahead request and reclaim attempts to evict the inode +of the file being read ahead. Since the folio is locked during +readahead, when reclaim evicts the fuse inode and fuse_evict_inode() +attempts to remove all folios associated with the inode from the page +cache (truncate_inode_pages_range()), reclaim will block forever waiting +for the lock since readahead cannot relinquish the lock because it is +itself blocked in reclaim: + +>>> stack_trace(1504735) + folio_wait_bit_common (mm/filemap.c:1308:4) + folio_lock (./include/linux/pagemap.h:1052:3) + truncate_inode_pages_range (mm/truncate.c:336:10) + fuse_evict_inode (fs/fuse/inode.c:161:2) + evict (fs/inode.c:704:3) + dentry_unlink_inode (fs/dcache.c:412:3) + __dentry_kill (fs/dcache.c:615:3) + shrink_kill (fs/dcache.c:1060:12) + shrink_dentry_list (fs/dcache.c:1087:3) + prune_dcache_sb (fs/dcache.c:1168:2) + super_cache_scan (fs/super.c:221:10) + do_shrink_slab (mm/shrinker.c:435:9) + shrink_slab (mm/shrinker.c:626:10) + shrink_node (mm/vmscan.c:5951:2) + shrink_zones (mm/vmscan.c:6195:3) + do_try_to_free_pages (mm/vmscan.c:6257:3) + do_swap_page (mm/memory.c:4136:11) + handle_pte_fault (mm/memory.c:5562:10) + handle_mm_fault (mm/memory.c:5870:9) + do_user_addr_fault (arch/x86/mm/fault.c:1338:10) + handle_page_fault (arch/x86/mm/fault.c:1481:3) + exc_page_fault (arch/x86/mm/fault.c:1539:2) + asm_exc_page_fault+0x22/0x27 + +Fix this deadlock by allocating ff->release_args and grabbing the +reference on the inode when preparing the file for release even if the +server does not implement open. The inode reference will be dropped when +the last reference on the fuse file is dropped (see fuse_file_put() -> +fuse_release_end()). + +Fixes: e26ee4efbc79 ("fuse: allocate ff->release_args only if release is needed") +Cc: stable@vger.kernel.org +Signed-off-by: Joanne Koong +Reported-by: Omar Sandoval +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/fuse/file.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -109,7 +109,9 @@ static void fuse_file_put(struct fuse_fi + fuse_file_io_release(ff, ra->inode); + + if (!args) { +- /* Do nothing when server does not implement 'open' */ ++ /* Do nothing when server does not implement 'opendir' */ ++ } else if (args->opcode == FUSE_RELEASE && ff->fm->fc->no_open) { ++ fuse_release_end(ff->fm, args, 0); + } else if (sync) { + fuse_simple_request(ff->fm, args); + fuse_release_end(ff->fm, args, 0); +@@ -130,8 +132,17 @@ struct fuse_file *fuse_file_open(struct + struct fuse_file *ff; + int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; + bool open = isdir ? !fc->no_opendir : !fc->no_open; ++ bool release = !isdir || open; + +- ff = fuse_file_alloc(fm, open); ++ /* ++ * ff->args->release_args still needs to be allocated (so we can hold an ++ * inode reference while there are pending inflight file operations when ++ * ->release() is called, see fuse_prepare_release()) even if ++ * fc->no_open is set else it becomes possible for reclaim to deadlock ++ * if while servicing the readahead request the server triggers reclaim ++ * and reclaim evicts the inode of the file being read ahead. ++ */ ++ ff = fuse_file_alloc(fm, release); + if (!ff) + return ERR_PTR(-ENOMEM); + +@@ -151,13 +162,14 @@ struct fuse_file *fuse_file_open(struct + fuse_file_free(ff); + return ERR_PTR(err); + } else { +- /* No release needed */ +- kfree(ff->args); +- ff->args = NULL; +- if (isdir) ++ if (isdir) { ++ /* No release needed */ ++ kfree(ff->args); ++ ff->args = NULL; + fc->no_opendir = 1; +- else ++ } else { + fc->no_open = 1; ++ } + } + } + diff --git a/queue-6.12/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch b/queue-6.12/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch new file mode 100644 index 0000000000..24683ae484 --- /dev/null +++ b/queue-6.12/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch @@ -0,0 +1,91 @@ +From de83d4617f9fe059623e97acf7e1e10d209625b5 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:10 +0200 +Subject: iommu/mediatek: fix use-after-free on probe deferral + +From: Johan Hovold + +commit de83d4617f9fe059623e97acf7e1e10d209625b5 upstream. + +The driver is dropping the references taken to the larb devices during +probe after successful lookup as well as on errors. This can +potentially lead to a use-after-free in case a larb device has not yet +been bound to its driver so that the iommu driver probe defers. + +Fix this by keeping the references as expected while the iommu driver is +bound. + +Fixes: 26593928564c ("iommu/mediatek: Add error path for loop of mm_dts_parse") +Cc: stable@vger.kernel.org +Cc: Yong Wu +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Reviewed-by: Yong Wu +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/mtk_iommu.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +--- a/drivers/iommu/mtk_iommu.c ++++ b/drivers/iommu/mtk_iommu.c +@@ -1213,16 +1213,19 @@ static int mtk_iommu_mm_dts_parse(struct + } + + component_match_add(dev, match, component_compare_dev, &plarbdev->dev); +- platform_device_put(plarbdev); + } + +- if (!frst_avail_smicomm_node) +- return -EINVAL; ++ if (!frst_avail_smicomm_node) { ++ ret = -EINVAL; ++ goto err_larbdev_put; ++ } + + pcommdev = of_find_device_by_node(frst_avail_smicomm_node); + of_node_put(frst_avail_smicomm_node); +- if (!pcommdev) +- return -ENODEV; ++ if (!pcommdev) { ++ ret = -ENODEV; ++ goto err_larbdev_put; ++ } + data->smicomm_dev = &pcommdev->dev; + + link = device_link_add(data->smicomm_dev, dev, +@@ -1230,7 +1233,8 @@ static int mtk_iommu_mm_dts_parse(struct + platform_device_put(pcommdev); + if (!link) { + dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_larbdev_put; + } + return 0; + +@@ -1402,8 +1406,12 @@ out_sysfs_remove: + iommu_device_sysfs_remove(&data->iommu); + out_list_del: + list_del(&data->list); +- if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) ++ if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + device_link_remove(data->smicomm_dev, dev); ++ ++ for (i = 0; i < MTK_LARB_NR_MAX; i++) ++ put_device(data->larb_imu[i].dev); ++ } + out_runtime_disable: + pm_runtime_disable(dev); + return ret; +@@ -1423,6 +1431,9 @@ static void mtk_iommu_remove(struct plat + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + device_link_remove(data->smicomm_dev, &pdev->dev); + component_master_del(&pdev->dev, &mtk_iommu_com_ops); ++ ++ for (i = 0; i < MTK_LARB_NR_MAX; i++) ++ put_device(data->larb_imu[i].dev); + } + pm_runtime_disable(&pdev->dev); + for (i = 0; i < data->plat_data->banks_num; i++) { diff --git a/queue-6.12/series b/queue-6.12/series index 45436707ec..7b6d81391a 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -289,3 +289,5 @@ hwmon-w83791d-convert-macros-to-functions-to-avoid-toctou.patch hwmon-w83l786ng-convert-macros-to-functions-to-avoid-toctou.patch arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch x86-msi-make-irq_retrigger-functional-for-posted-msi.patch +iommu-mediatek-fix-use-after-free-on-probe-deferral.patch +fuse-fix-readahead-reclaim-deadlock.patch