eventfs_create_events_dir() runs INIT_LIST_HEAD(&ei->children) only after
tracefs_get_inode() succeeds, but that call's failure path jumps to "fail",
which calls cleanup_ei() and then free_ei(). free_ei() reads the list with
WARN_ON_ONCE(!list_empty(&ei->children)), and alloc_root_ei() uses
kzalloc(), so children.next is NULL there and the WARN fires.

The path is reachable at runtime: mkdir /sys/kernel/tracing/instances/foo
ends up in create_event_toplevel_files() and eventfs_create_events_dir().

Move both INIT_LIST_HEAD() calls up to right after the allocation.

Fixes: f0ece16ffca7 ("eventfs: Use children field for rcu head and add memory 
barriers")
Signed-off-by: David Carlier <[email protected]>
---
 fs/tracefs/event_inode.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index 604ba3e841d2..1d9edc99ff3f 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -779,6 +779,9 @@ struct eventfs_inode *eventfs_create_events_dir(const char 
*name, struct dentry
        if (!ei)
                goto fail;
 
+       INIT_LIST_HEAD(&ei->children);
+       INIT_LIST_HEAD(&ei->list);
+
        inode = tracefs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
                goto fail;
@@ -802,9 +805,6 @@ struct eventfs_inode *eventfs_create_events_dir(const char 
*name, struct dentry
        ei->attr.uid = uid;
        ei->attr.gid = gid;
 
-       INIT_LIST_HEAD(&ei->children);
-       INIT_LIST_HEAD(&ei->list);
-
        ti = get_tracefs(inode);
        ti->flags |= TRACEFS_EVENT_INODE;
        ti->private = ei;
-- 
2.55.0


Reply via email to