From: Greg Kroah-Hartman Date: Sun, 14 Sep 2025 12:31:51 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v6.1.153~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8591cd70c70bae5fadf6339791c27901573b17e4;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: kernfs-fix-uaf-in-polling-when-open-file-is-released.patch --- diff --git a/queue-6.1/kernfs-fix-uaf-in-polling-when-open-file-is-released.patch b/queue-6.1/kernfs-fix-uaf-in-polling-when-open-file-is-released.patch new file mode 100644 index 0000000000..e86bb05cd8 --- /dev/null +++ b/queue-6.1/kernfs-fix-uaf-in-polling-when-open-file-is-released.patch @@ -0,0 +1,280 @@ +From 3c9ba2777d6c86025e1ba4186dc5cd930e40ec5f Mon Sep 17 00:00:00 2001 +From: Chen Ridong +Date: Fri, 22 Aug 2025 07:07:14 +0000 +Subject: kernfs: Fix UAF in polling when open file is released + +From: Chen Ridong + +commit 3c9ba2777d6c86025e1ba4186dc5cd930e40ec5f upstream. + +A use-after-free (UAF) vulnerability was identified in the PSI (Pressure +Stall Information) monitoring mechanism: + +BUG: KASAN: slab-use-after-free in psi_trigger_poll+0x3c/0x140 +Read of size 8 at addr ffff3de3d50bd308 by task systemd/1 + +psi_trigger_poll+0x3c/0x140 +cgroup_pressure_poll+0x70/0xa0 +cgroup_file_poll+0x8c/0x100 +kernfs_fop_poll+0x11c/0x1c0 +ep_item_poll.isra.0+0x188/0x2c0 + +Allocated by task 1: +cgroup_file_open+0x88/0x388 +kernfs_fop_open+0x73c/0xaf0 +do_dentry_open+0x5fc/0x1200 +vfs_open+0xa0/0x3f0 +do_open+0x7e8/0xd08 +path_openat+0x2fc/0x6b0 +do_filp_open+0x174/0x368 + +Freed by task 8462: +cgroup_file_release+0x130/0x1f8 +kernfs_drain_open_files+0x17c/0x440 +kernfs_drain+0x2dc/0x360 +kernfs_show+0x1b8/0x288 +cgroup_file_show+0x150/0x268 +cgroup_pressure_write+0x1dc/0x340 +cgroup_file_write+0x274/0x548 + +Reproduction Steps: +1. Open test/cpu.pressure and establish epoll monitoring +2. Disable monitoring: echo 0 > test/cgroup.pressure +3. Re-enable monitoring: echo 1 > test/cgroup.pressure + +The race condition occurs because: +1. When cgroup.pressure is disabled (echo 0 > cgroup.pressure), it: + - Releases PSI triggers via cgroup_file_release() + - Frees of->priv through kernfs_drain_open_files() +2. While epoll still holds reference to the file and continues polling +3. Re-enabling (echo 1 > cgroup.pressure) accesses freed of->priv + +epolling disable/enable cgroup.pressure +fd=open(cpu.pressure) +while(1) +... +epoll_wait +kernfs_fop_poll +kernfs_get_active = true echo 0 > cgroup.pressure +... cgroup_file_show + kernfs_show + // inactive kn + kernfs_drain_open_files + cft->release(of); + kfree(ctx); + ... +kernfs_get_active = false + echo 1 > cgroup.pressure + kernfs_show + kernfs_activate_one(kn); +kernfs_fop_poll +kernfs_get_active = true +cgroup_file_poll +psi_trigger_poll +// UAF +... +end: close(fd) + +To address this issue, introduce kernfs_get_active_of() for kernfs open +files to obtain active references. This function will fail if the open file +has been released. Replace kernfs_get_active() with kernfs_get_active_of() +to prevent further operations on released file descriptors. + +Fixes: 34f26a15611a ("sched/psi: Per-cgroup PSI accounting disable/re-enable interface") +Cc: stable +Reported-by: Zhang Zhaotian +Signed-off-by: Chen Ridong +Acked-by: Tejun Heo +Link: https://lore.kernel.org/r/20250822070715.1565236-2-chenridong@huaweicloud.com +[ Drop llseek bits ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/kernfs/file.c | 54 ++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 36 insertions(+), 18 deletions(-) + +--- a/fs/kernfs/file.c ++++ b/fs/kernfs/file.c +@@ -70,6 +70,24 @@ static struct kernfs_open_node *of_on(st + !list_empty(&of->list)); + } + ++/* Get active reference to kernfs node for an open file */ ++static struct kernfs_open_file *kernfs_get_active_of(struct kernfs_open_file *of) ++{ ++ /* Skip if file was already released */ ++ if (unlikely(of->released)) ++ return NULL; ++ ++ if (!kernfs_get_active(of->kn)) ++ return NULL; ++ ++ return of; ++} ++ ++static void kernfs_put_active_of(struct kernfs_open_file *of) ++{ ++ return kernfs_put_active(of->kn); ++} ++ + /** + * kernfs_deref_open_node_locked - Get kernfs_open_node corresponding to @kn + * +@@ -139,7 +157,7 @@ static void kernfs_seq_stop_active(struc + + if (ops->seq_stop) + ops->seq_stop(sf, v); +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + } + + static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) +@@ -152,7 +170,7 @@ static void *kernfs_seq_start(struct seq + * the ops aren't called concurrently for the same open file. + */ + mutex_lock(&of->mutex); +- if (!kernfs_get_active(of->kn)) ++ if (!kernfs_get_active_of(of)) + return ERR_PTR(-ENODEV); + + ops = kernfs_ops(of->kn); +@@ -238,7 +256,7 @@ static ssize_t kernfs_file_read_iter(str + * the ops aren't called concurrently for the same open file. + */ + mutex_lock(&of->mutex); +- if (!kernfs_get_active(of->kn)) { ++ if (!kernfs_get_active_of(of)) { + len = -ENODEV; + mutex_unlock(&of->mutex); + goto out_free; +@@ -252,7 +270,7 @@ static ssize_t kernfs_file_read_iter(str + else + len = -EINVAL; + +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + mutex_unlock(&of->mutex); + + if (len < 0) +@@ -323,7 +341,7 @@ static ssize_t kernfs_fop_write_iter(str + * the ops aren't called concurrently for the same open file. + */ + mutex_lock(&of->mutex); +- if (!kernfs_get_active(of->kn)) { ++ if (!kernfs_get_active_of(of)) { + mutex_unlock(&of->mutex); + len = -ENODEV; + goto out_free; +@@ -335,7 +353,7 @@ static ssize_t kernfs_fop_write_iter(str + else + len = -EINVAL; + +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + mutex_unlock(&of->mutex); + + if (len > 0) +@@ -357,13 +375,13 @@ static void kernfs_vma_open(struct vm_ar + if (!of->vm_ops) + return; + +- if (!kernfs_get_active(of->kn)) ++ if (!kernfs_get_active_of(of)) + return; + + if (of->vm_ops->open) + of->vm_ops->open(vma); + +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + } + + static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf) +@@ -375,14 +393,14 @@ static vm_fault_t kernfs_vma_fault(struc + if (!of->vm_ops) + return VM_FAULT_SIGBUS; + +- if (!kernfs_get_active(of->kn)) ++ if (!kernfs_get_active_of(of)) + return VM_FAULT_SIGBUS; + + ret = VM_FAULT_SIGBUS; + if (of->vm_ops->fault) + ret = of->vm_ops->fault(vmf); + +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + return ret; + } + +@@ -395,7 +413,7 @@ static vm_fault_t kernfs_vma_page_mkwrit + if (!of->vm_ops) + return VM_FAULT_SIGBUS; + +- if (!kernfs_get_active(of->kn)) ++ if (!kernfs_get_active_of(of)) + return VM_FAULT_SIGBUS; + + ret = 0; +@@ -404,7 +422,7 @@ static vm_fault_t kernfs_vma_page_mkwrit + else + file_update_time(file); + +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + return ret; + } + +@@ -418,14 +436,14 @@ static int kernfs_vma_access(struct vm_a + if (!of->vm_ops) + return -EINVAL; + +- if (!kernfs_get_active(of->kn)) ++ if (!kernfs_get_active_of(of)) + return -EINVAL; + + ret = -EINVAL; + if (of->vm_ops->access) + ret = of->vm_ops->access(vma, addr, buf, len, write); + +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + return ret; + } + +@@ -504,7 +522,7 @@ static int kernfs_fop_mmap(struct file * + mutex_lock(&of->mutex); + + rc = -ENODEV; +- if (!kernfs_get_active(of->kn)) ++ if (!kernfs_get_active_of(of)) + goto out_unlock; + + ops = kernfs_ops(of->kn); +@@ -539,7 +557,7 @@ static int kernfs_fop_mmap(struct file * + } + vma->vm_ops = &kernfs_vm_ops; + out_put: +- kernfs_put_active(of->kn); ++ kernfs_put_active_of(of); + out_unlock: + mutex_unlock(&of->mutex); + +@@ -894,7 +912,7 @@ static __poll_t kernfs_fop_poll(struct f + struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry); + __poll_t ret; + +- if (!kernfs_get_active(kn)) ++ if (!kernfs_get_active_of(of)) + return DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI; + + if (kn->attr.ops->poll) +@@ -902,7 +920,7 @@ static __poll_t kernfs_fop_poll(struct f + else + ret = kernfs_generic_poll(of, wait); + +- kernfs_put_active(kn); ++ kernfs_put_active_of(of); + return ret; + } + diff --git a/queue-6.1/series b/queue-6.1/series index 9d7b0603fd..0b61671619 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -38,3 +38,4 @@ mtd-nand-raw-atmel-fix-comment-in-timings-preparation.patch mtd-nand-raw-atmel-respect-tar-tclr-in-read-setup-timing.patch mm-khugepaged-convert-hpage_collapse_scan_pmd-to-use-folios.patch mm-khugepaged-fix-the-address-passed-to-notifier-on-testing-young.patch +kernfs-fix-uaf-in-polling-when-open-file-is-released.patch