From: Sebastian Andrzej Siewior Date: Thu, 13 Feb 2025 14:50:21 +0000 (+0100) Subject: kernfs: Don't re-lock kernfs_root::kernfs_rwsem in kernfs_fop_readdir(). X-Git-Tag: v6.15-rc1~79^2~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9aab10a0249eab4ec77c6a5e4f66442610c12a09;p=thirdparty%2Fkernel%2Flinux.git kernfs: Don't re-lock kernfs_root::kernfs_rwsem in kernfs_fop_readdir(). The readdir operation iterates over all entries and invokes dir_emit() for every entry passing kernfs_node::name as argument. Since the name argument can change, and become invalid, the kernfs_root::kernfs_rwsem lock should not be dropped to prevent renames during the operation. The lock drop around dir_emit() has been initially introduced in commit 1e5289c97bba2 ("sysfs: Cache the last sysfs_dirent to improve readdir scalability v2") to avoid holding a global lock during a page fault. The lock drop is wrong since the support of renames and not a big burden since the lock is no longer global. Don't re-acquire kernfs_root::kernfs_rwsem while copying the name to the userpace buffer. Acked-by: Tejun Heo Signed-off-by: Sebastian Andrzej Siewior Link: https://lore.kernel.org/r/20250213145023.2820193-5-bigeasy@linutronix.de Signed-off-by: Greg Kroah-Hartman --- diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 5f0f8b95f44c0..43fbada678381 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -1869,10 +1869,10 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx) file->private_data = pos; kernfs_get(pos); - up_read(&root->kernfs_rwsem); - if (!dir_emit(ctx, name, len, ino, type)) + if (!dir_emit(ctx, name, len, ino, type)) { + up_read(&root->kernfs_rwsem); return 0; - down_read(&root->kernfs_rwsem); + } } up_read(&root->kernfs_rwsem); file->private_data = NULL;