Skip to content

Commit dd12fb6

Browse files
minchanksurenbaghdasaryan
authored andcommitted
UPSTREAM: kernfs: prevent early freeing of root node
Marek reported the warning below. ========================= WARNING: held lock freed! 5.16.0-rc2+ #10984 Not tainted ------------------------- kworker/1:0/18 is freeing memory ffff00004034e200-ffff00004034e3ff, with a lock still held there! ffff00004034e348 (&root->kernfs_rwsem){++++}-{3:3}, at: __kernfs_remove+0x310/0x37c 3 locks held by kworker/1:0/18: #0: ffff000040107938 ((wq_completion)cgroup_destroy){+.+.}-{0:0}, at: process_one_work+0x1f0/0x6f0 #1: ffff80000b55bdc0 ((work_completion)(&(&css->destroy_rwork)->work)){+.+.}-{0:0}, at: process_one_work+0x1f0/0x6f0 #2: ffff00004034e348 (&root->kernfs_rwsem){++++}-{3:3}, at: __kernfs_remove+0x310/0x37c stack backtrace: CPU: 1 PID: 18 Comm: kworker/1:0 Not tainted 5.16.0-rc2+ #10984 Hardware name: Raspberry Pi 4 Model B (DT) Workqueue: cgroup_destroy css_free_rwork_fn Call trace: dump_backtrace+0x0/0x1ac show_stack+0x18/0x24 dump_stack_lvl+0x8c/0xb8 dump_stack+0x18/0x34 debug_check_no_locks_freed+0x124/0x140 kfree+0xf0/0x3a4 kernfs_put+0x1f8/0x224 __kernfs_remove+0x1b8/0x37c kernfs_destroy_root+0x38/0x50 css_free_rwork_fn+0x288/0x3d4 process_one_work+0x288/0x6f0 worker_thread+0x74/0x470 kthread+0x188/0x194 ret_from_fork+0x10/0x20 Since kernfs moves the kernfs_rwsem lock into root, it couldn't hold the lock when the root node is tearing down. Thus, get the refcount of root node. Fixes: 393c371 ("kernfs: switch global kernfs_rwsem lock to per-fs lock") Reported-by: Marek Szyprowski <[email protected]> Tested-by: Marek Szyprowski <[email protected]> Acked-by: Tejun Heo <[email protected]> Signed-off-by: Minchan Kim <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit 555a0ce) Bug: 320903885 Change-Id: If96f85b88b662e88430c9c8d1efb436e9a80ddcf Signed-off-by: Suren Baghdasaryan <[email protected]>
1 parent f2242c1 commit dd12fb6

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

fs/kernfs/dir.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,13 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
970970
*/
971971
void kernfs_destroy_root(struct kernfs_root *root)
972972
{
973-
kernfs_remove(root->kn); /* will also free @root */
973+
/*
974+
* kernfs_remove holds kernfs_rwsem from the root so the root
975+
* shouldn't be freed during the operation.
976+
*/
977+
kernfs_get(root->kn);
978+
kernfs_remove(root->kn);
979+
kernfs_put(root->kn); /* will also free @root */
974980
}
975981

976982
/**

0 commit comments

Comments
 (0)