Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <tj@kernel.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lore.kernel.org/r/20250213145023.2820193-5-bigeasy@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sebastian Andrzej Siewior and committed by
Greg Kroah-Hartman
9aab10a0 5b2fabf7

+3 -3
+3 -3
fs/kernfs/dir.c
··· 1869 1869 file->private_data = pos; 1870 1870 kernfs_get(pos); 1871 1871 1872 - up_read(&root->kernfs_rwsem); 1873 - if (!dir_emit(ctx, name, len, ino, type)) 1872 + if (!dir_emit(ctx, name, len, ino, type)) { 1873 + up_read(&root->kernfs_rwsem); 1874 1874 return 0; 1875 - down_read(&root->kernfs_rwsem); 1875 + } 1876 1876 } 1877 1877 up_read(&root->kernfs_rwsem); 1878 1878 file->private_data = NULL;