[Devel] [PATCH vz10 09/24] kernfs: rcu_read_lock() when walking parents in ve visibility checks
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Thu Jul 23 17:36:42 MSK 2026
This is similar to "fs/kernfs, ve: fix ve_perms_map use-after-free,
annotate it __rcu" (which is even a bit stronger version, and I
already merged it).
So this can be dropped.
On 7/6/26 12:59, Konstantin Khorenko wrote:
> kernfs_ve_permission() and kernfs_d_visible() walk the parent chain with
> kernfs_parent(), which is rcu_dereference_check(kn->__parent, ...) and
> requires the kernfs rwsem/rename_lock, a zero refcount, or an RCU
> read-side critical section. They are called from the permission/lookup
> path holding only kernfs_iattr_rwsem, so on a lockdep kernel this trips:
>
> WARNING: suspicious RCU usage
> fs/kernfs/kernfs-internal.h:131 suspicious rcu_dereference_check() usage!
> kernfs_ve_permission <- kernfs_iop_permission <- inode_permission
>
> Wrap the parent walks in rcu_read_lock(); kernfs nodes are RCU-freed so
> this is both correct (guards against concurrent reparent/free) and
> silences the splat.
>
> Fixes: cd9dd4ead86a ("ve/kernfs: implement ve-based permissions")
> Feature: sysfs: per-CT entries visibility and permissions configuration
> https://virtuozzo.atlassian.net/browse/VSTOR-137234
> Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
> ---
> fs/kernfs/ve.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/fs/kernfs/ve.c b/fs/kernfs/ve.c
> index beaa278b014e..e83ee5bec3bf 100644
> --- a/fs/kernfs/ve.c
> +++ b/fs/kernfs/ve.c
> @@ -64,11 +64,15 @@ int kernfs_ve_permission(struct kernfs_node *kn,
> return 0;
>
> /* Entries with namespace tag and their sub-entries always visible */
> + rcu_read_lock();
> while (tmp_kn) {
> - if (tmp_kn->ns)
> + if (tmp_kn->ns) {
> + rcu_read_unlock();
> return 0;
> + }
> tmp_kn = kernfs_parent(tmp_kn);
> }
> + rcu_read_unlock();
>
> if (kernfs_type(kn) == KERNFS_LINK)
> kn = kn->symlink.target_kn;
> @@ -108,11 +112,15 @@ bool kernfs_d_visible(struct kernfs_node *kn, struct kernfs_super_info *info)
> return true;
>
> /* Entries with namespace tag and their sub-entries always visible */
> + rcu_read_lock();
> while (tmp_kn) {
> - if (tmp_kn->ns)
> + if (tmp_kn->ns) {
> + rcu_read_unlock();
> return true;
> + }
> tmp_kn = kernfs_parent(tmp_kn);
> }
> + rcu_read_unlock();
>
> /* Symlinks are visible if target kn is visible */
> if (kernfs_type(kn) == KERNFS_LINK)
--
Best regards, Pavel Tikhomirov
Senior Software Developer, Virtuozzo.
More information about the Devel
mailing list