[PATCHSET driver-core-next] kernfs: Protect kernfs_find_and_get_node_by_id() with RCU

From: Tejun Heo
Date: Tue Jan 09 2024 - 16:48:51 EST


The BPF helper bpf_cgroup_from_id() calls kernfs_find_and_get_node_by_id()
which acquires kernfs_idr_lock, which is an non-raw non-IRQ-safe lock.
kernfs_idr_lock used to be a non-irq-safe lock which could lead to deadlocks
as bpf_cgroup_from_id() can be called from any BPF programs including e.g.
the ones that attach to functions which are holding the scheduler rq lock.

To resolve the situation dad3fb67ca1c ("kernfs: convert kernfs_idr_lock to
an irq safe raw spinlock") converted kernfs_idr_lock to an irq-safe raw
spinlock. However, this was also broken as we call idr_alloc*() while
holding the lock and idr itself uses an non-irq-safe lock and also calls
into memory allocator.

Let's instead RCU protect kernfs_node and kernfs_root so that
kernfs_find_and_get_node_by_id() can use rcu_read_lock() instead of
kernfs_idr_lock. While this unfortunately increases the size of kernfs_node,
it's the most straightforward thing to do and there likely are other places
that can take advantage of RCU protection and improve scalability too.

Please see the patch descriptions for more details.

This patchset is on top of the current driver-core-next - dad3fb67ca1c
("kernfs: convert kernfs_idr_lock to an irq safe raw spinlock"), and also
available in the following git branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git kernfs-use-rcu

Thanks.

--
tejun