From: Greg Kroah-Hartman Date: Mon, 29 Dec 2025 16:03:06 +0000 (+0100) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=edd8f735ba37cc4841632ba9ebe36196e4e45477;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: block-freeze-queue-when-updating-zone-resources.patch fuse-fix-io-uring-list-corruption-for-terminated-non-committed-requests.patch fuse-fix-readahead-reclaim-deadlock.patch fuse-missing-copy_finish-in-fuse-over-io-uring-argument-copies.patch iommu-mediatek-fix-use-after-free-on-probe-deferral.patch --- diff --git a/queue-6.18/block-freeze-queue-when-updating-zone-resources.patch b/queue-6.18/block-freeze-queue-when-updating-zone-resources.patch new file mode 100644 index 0000000000..9446d88397 --- /dev/null +++ b/queue-6.18/block-freeze-queue-when-updating-zone-resources.patch @@ -0,0 +1,124 @@ +From bba4322e3f303b2d656e748be758320b567f046f Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Wed, 5 Nov 2025 06:22:36 +0900 +Subject: block: freeze queue when updating zone resources + +From: Damien Le Moal + +commit bba4322e3f303b2d656e748be758320b567f046f upstream. + +Modify disk_update_zone_resources() to freeze the device queue before +updating the number of zones, zone capacity and other zone related +resources. The locking order resulting from the call to +queue_limits_commit_update_frozen() is preserved, that is, the queue +limits lock is first taken by calling queue_limits_start_update() before +freezing the queue, and the queue is unfrozen after executing +queue_limits_commit_update(), which replaces the call to +queue_limits_commit_update_frozen(). + +This change ensures that there are no in-flights I/Os when the zone +resources are updated due to a zone revalidation. In case of error when +the limits are applied, directly call disk_free_zone_resources() from +disk_update_zone_resources() while the disk queue is still frozen to +avoid needing to freeze & unfreeze the queue again in +blk_revalidate_disk_zones(), thus simplifying that function code a +little. + +Fixes: 0b83c86b444a ("block: Prevent potential deadlock in blk_revalidate_disk_zones()") +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Hannes Reinecke +Reviewed-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-zoned.c | 42 ++++++++++++++++++++++++------------------ + 1 file changed, 24 insertions(+), 18 deletions(-) + +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -1516,8 +1516,13 @@ static int disk_update_zone_resources(st + { + struct request_queue *q = disk->queue; + unsigned int nr_seq_zones, nr_conv_zones; +- unsigned int pool_size; ++ unsigned int pool_size, memflags; + struct queue_limits lim; ++ int ret = 0; ++ ++ lim = queue_limits_start_update(q); ++ ++ memflags = blk_mq_freeze_queue(q); + + disk->nr_zones = args->nr_zones; + disk->zone_capacity = args->zone_capacity; +@@ -1527,11 +1532,10 @@ static int disk_update_zone_resources(st + if (nr_conv_zones >= disk->nr_zones) { + pr_warn("%s: Invalid number of conventional zones %u / %u\n", + disk->disk_name, nr_conv_zones, disk->nr_zones); +- return -ENODEV; ++ ret = -ENODEV; ++ goto unfreeze; + } + +- lim = queue_limits_start_update(q); +- + /* + * Some devices can advertize zone resource limits that are larger than + * the number of sequential zones of the zoned block device, e.g. a +@@ -1568,7 +1572,15 @@ static int disk_update_zone_resources(st + } + + commit: +- return queue_limits_commit_update_frozen(q, &lim); ++ ret = queue_limits_commit_update(q, &lim); ++ ++unfreeze: ++ if (ret) ++ disk_free_zone_resources(disk); ++ ++ blk_mq_unfreeze_queue(q, memflags); ++ ++ return ret; + } + + static int blk_revalidate_conv_zone(struct blk_zone *zone, unsigned int idx, +@@ -1733,7 +1745,7 @@ int blk_revalidate_disk_zones(struct gen + sector_t zone_sectors = q->limits.chunk_sectors; + sector_t capacity = get_capacity(disk); + struct blk_revalidate_zone_args args = { }; +- unsigned int noio_flag; ++ unsigned int memflags, noio_flag; + int ret = -ENOMEM; + + if (WARN_ON_ONCE(!blk_queue_is_zoned(q))) +@@ -1783,20 +1795,14 @@ int blk_revalidate_disk_zones(struct gen + ret = -ENODEV; + } + +- /* +- * Set the new disk zone parameters only once the queue is frozen and +- * all I/Os are completed. +- */ + if (ret > 0) +- ret = disk_update_zone_resources(disk, &args); +- else +- pr_warn("%s: failed to revalidate zones\n", disk->disk_name); +- if (ret) { +- unsigned int memflags = blk_mq_freeze_queue(q); ++ return disk_update_zone_resources(disk, &args); + +- disk_free_zone_resources(disk); +- blk_mq_unfreeze_queue(q, memflags); +- } ++ pr_warn("%s: failed to revalidate zones\n", disk->disk_name); ++ ++ memflags = blk_mq_freeze_queue(q); ++ disk_free_zone_resources(disk); ++ blk_mq_unfreeze_queue(q, memflags); + + return ret; + } diff --git a/queue-6.18/fuse-fix-io-uring-list-corruption-for-terminated-non-committed-requests.patch b/queue-6.18/fuse-fix-io-uring-list-corruption-for-terminated-non-committed-requests.patch new file mode 100644 index 0000000000..b86cc0a2a4 --- /dev/null +++ b/queue-6.18/fuse-fix-io-uring-list-corruption-for-terminated-non-committed-requests.patch @@ -0,0 +1,41 @@ +From 95c39eef7c2b666026c69ab5b30471da94ea2874 Mon Sep 17 00:00:00 2001 +From: Joanne Koong +Date: Tue, 25 Nov 2025 10:13:47 -0800 +Subject: fuse: fix io-uring list corruption for terminated non-committed requests + +From: Joanne Koong + +commit 95c39eef7c2b666026c69ab5b30471da94ea2874 upstream. + +When a request is terminated before it has been committed, the request +is not removed from the queue's list. This leaves a dangling list entry +that leads to list corruption and use-after-free issues. + +Remove the request from the queue's list for terminated non-committed +requests. + +Signed-off-by: Joanne Koong +Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support") +Cc: stable@vger.kernel.org +Reviewed-by: Bernd Schubert +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/fuse/dev_uring.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c +index 0066c9c0a5d5..7760fe4e1f9e 100644 +--- a/fs/fuse/dev_uring.c ++++ b/fs/fuse/dev_uring.c +@@ -86,6 +86,7 @@ static void fuse_uring_req_end(struct fuse_ring_ent *ent, struct fuse_req *req, + lockdep_assert_not_held(&queue->lock); + spin_lock(&queue->lock); + ent->fuse_req = NULL; ++ list_del_init(&req->list); + if (test_bit(FR_BACKGROUND, &req->flags)) { + queue->active_background--; + spin_lock(&fc->bg_lock); +-- +2.52.0 + diff --git a/queue-6.18/fuse-fix-readahead-reclaim-deadlock.patch b/queue-6.18/fuse-fix-readahead-reclaim-deadlock.patch new file mode 100644 index 0000000000..ea8fca2f7b --- /dev/null +++ b/queue-6.18/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 +@@ -110,7 +110,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); +@@ -131,8 +133,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); + +@@ -152,13 +163,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.18/fuse-missing-copy_finish-in-fuse-over-io-uring-argument-copies.patch b/queue-6.18/fuse-missing-copy_finish-in-fuse-over-io-uring-argument-copies.patch new file mode 100644 index 0000000000..b4b2a549b1 --- /dev/null +++ b/queue-6.18/fuse-missing-copy_finish-in-fuse-over-io-uring-argument-copies.patch @@ -0,0 +1,69 @@ +From 6e0d7f7f4a43ac8868e98c87ecf48805aa8c24dd Mon Sep 17 00:00:00 2001 +From: Cheng Ding +Date: Tue, 21 Oct 2025 22:46:42 +0200 +Subject: fuse: missing copy_finish in fuse-over-io-uring argument copies + +From: Cheng Ding + +commit 6e0d7f7f4a43ac8868e98c87ecf48805aa8c24dd upstream. + +Fix a possible reference count leak of payload pages during +fuse argument copies. + +[Joanne: simplified error cleanup] + +Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support") +Cc: stable@vger.kernel.org # v6.14 +Signed-off-by: Cheng Ding +Signed-off-by: Bernd Schubert +Reviewed-by: Joanne Koong +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/fuse/dev.c | 2 +- + fs/fuse/dev_uring.c | 5 ++++- + fs/fuse/fuse_dev_i.h | 1 + + 3 files changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -846,7 +846,7 @@ void fuse_copy_init(struct fuse_copy_sta + } + + /* Unmap and put previous page of userspace buffer */ +-static void fuse_copy_finish(struct fuse_copy_state *cs) ++void fuse_copy_finish(struct fuse_copy_state *cs) + { + if (cs->currbuf) { + struct pipe_buffer *buf = cs->currbuf; +--- a/fs/fuse/dev_uring.c ++++ b/fs/fuse/dev_uring.c +@@ -599,7 +599,9 @@ static int fuse_uring_copy_from_ring(str + cs.is_uring = true; + cs.req = req; + +- return fuse_copy_out_args(&cs, args, ring_in_out.payload_sz); ++ err = fuse_copy_out_args(&cs, args, ring_in_out.payload_sz); ++ fuse_copy_finish(&cs); ++ return err; + } + + /* +@@ -650,6 +652,7 @@ static int fuse_uring_args_to_ring(struc + /* copy the payload */ + err = fuse_copy_args(&cs, num_args, args->in_pages, + (struct fuse_arg *)in_args, 0); ++ fuse_copy_finish(&cs); + if (err) { + pr_info_ratelimited("%s fuse_copy_args failed\n", __func__); + return err; +--- a/fs/fuse/fuse_dev_i.h ++++ b/fs/fuse/fuse_dev_i.h +@@ -62,6 +62,7 @@ void fuse_dev_end_requests(struct list_h + + void fuse_copy_init(struct fuse_copy_state *cs, bool write, + struct iov_iter *iter); ++void fuse_copy_finish(struct fuse_copy_state *cs); + int fuse_copy_args(struct fuse_copy_state *cs, unsigned int numargs, + unsigned int argpages, struct fuse_arg *args, + int zeroing); diff --git a/queue-6.18/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch b/queue-6.18/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch new file mode 100644 index 0000000000..26b9ac9b5d --- /dev/null +++ b/queue-6.18/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 +@@ -1211,16 +1211,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, +@@ -1228,7 +1231,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; + +@@ -1400,8 +1404,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; +@@ -1421,6 +1429,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.18/series b/queue-6.18/series index f77d28bb88..8645ffcfac 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -423,3 +423,8 @@ hwmon-w83l786ng-convert-macros-to-functions-to-avoid-toctou.patch arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch arm-dts-microchip-sama7d65-fix-uart-fifo-size-to-32.patch arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch +block-freeze-queue-when-updating-zone-resources.patch +iommu-mediatek-fix-use-after-free-on-probe-deferral.patch +fuse-fix-io-uring-list-corruption-for-terminated-non-committed-requests.patch +fuse-fix-readahead-reclaim-deadlock.patch +fuse-missing-copy_finish-in-fuse-over-io-uring-argument-copies.patch