Skip to content

Commit e5104cb

Browse files
rostedtgregkh
authored andcommitted
tracefs: Clear EVENT_INODE flag in tracefs_drop_inode()
commit 0bcfd9a upstream. When the inode is being dropped from the dentry, the TRACEFS_EVENT_INODE flag needs to be cleared to prevent a remount from calling eventfs_remount() on the tracefs_inode private data. There's a race between the inode is dropped (and the dentry freed) to where the inode is actually freed. If a remount happens between the two, the eventfs_inode could be accessed after it is freed (only the dentry keeps a ref count on it). Currently the TRACEFS_EVENT_INODE flag is cleared from the dentry iput() function. But this is incorrect, as it is possible that the inode has another reference to it. The flag should only be cleared when the inode is really being dropped and has no more references. That happens in the drop_inode callback of the inode, as that gets called when the last reference of the inode is released. Remove the tracefs_d_iput() function and move its logic to the more appropriate tracefs_drop_inode() callback function. Link: https://lore.kernel.org/linux-trace-kernel/[email protected] Cc: [email protected] Cc: Masami Hiramatsu <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Masahiro Yamada <[email protected]> Fixes: baa23a8 ("tracefs: Reset permissions on remount if permissions are options") Signed-off-by: Steven Rostedt (Google) <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4e84ead commit e5104cb

File tree

1 file changed

+17
-16
lines changed

1 file changed

+17
-16
lines changed

fs/tracefs/inode.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -439,10 +439,26 @@ static int tracefs_show_options(struct seq_file *m, struct dentry *root)
439439
return 0;
440440
}
441441

442+
static int tracefs_drop_inode(struct inode *inode)
443+
{
444+
struct tracefs_inode *ti = get_tracefs(inode);
445+
446+
/*
447+
* This inode is being freed and cannot be used for
448+
* eventfs. Clear the flag so that it doesn't call into
449+
* eventfs during the remount flag updates. The eventfs_inode
450+
* gets freed after an RCU cycle, so the content will still
451+
* be safe if the iteration is going on now.
452+
*/
453+
ti->flags &= ~TRACEFS_EVENT_INODE;
454+
455+
return 1;
456+
}
457+
442458
static const struct super_operations tracefs_super_operations = {
443459
.alloc_inode = tracefs_alloc_inode,
444460
.free_inode = tracefs_free_inode,
445-
.drop_inode = generic_delete_inode,
461+
.drop_inode = tracefs_drop_inode,
446462
.statfs = simple_statfs,
447463
.remount_fs = tracefs_remount,
448464
.show_options = tracefs_show_options,
@@ -469,22 +485,7 @@ static int tracefs_d_revalidate(struct dentry *dentry, unsigned int flags)
469485
return !(ei && ei->is_freed);
470486
}
471487

472-
static void tracefs_d_iput(struct dentry *dentry, struct inode *inode)
473-
{
474-
struct tracefs_inode *ti = get_tracefs(inode);
475-
476-
/*
477-
* This inode is being freed and cannot be used for
478-
* eventfs. Clear the flag so that it doesn't call into
479-
* eventfs during the remount flag updates. The eventfs_inode
480-
* gets freed after an RCU cycle, so the content will still
481-
* be safe if the iteration is going on now.
482-
*/
483-
ti->flags &= ~TRACEFS_EVENT_INODE;
484-
}
485-
486488
static const struct dentry_operations tracefs_dentry_operations = {
487-
.d_iput = tracefs_d_iput,
488489
.d_revalidate = tracefs_d_revalidate,
489490
.d_release = tracefs_d_release,
490491
};

0 commit comments

Comments
 (0)