eventfs: Simplify the permissions logic
Steven Rostedt
maintainercover eventfs: Simplify the permissions logic
While debugging the failure of the ownership test failing on the second run again, I ended up greatly simplifying the eventfs code with respect to the permissions, only to discover that the bug was elsewhere[1].
But because of the great diff-stat that this produced, not to mention the simplifying of the code, I'm going to try to get this into this merge window.
[1] https://lore.kernel.org/linux-trace-kernel/[email protected]/
Steven Rostedt (Google) (4):
eventfs: Consolidate the eventfs_inode update in eventfs_get_inode()
eventfs: Remove getattr and permission callbacks
eventfs: Cleanup permissions in creation of inodes
eventfs: Do not use attributes for events directory
----
fs/tracefs/event_inode.c | 172 +++++++++++++---------------------------------- 1 file changed, 46 insertions(+), 126 deletions(-)
Steven Rostedt
maintainerPATCH 1/4 eventfs: Consolidate the eventfs_inode update in eventfs_get_inode()
From: "Steven Rostedt (Google)" <[email protected]>
To simplify the code, create a eventfs_get_inode() that is used when an eventfs file or directory is created. Have the internal tracefs_inode updated the appropriate flags in this function and update the inode's mode as well.
--- fs/tracefs/event_inode.c | 42 ++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 19 deletions(-)
fs/tracefs/event_inode.c +23 -19
@@ -394,6 +394,25 @@ static void update_inode_attr(struct dentry *dentry, struct inode *inode, inode->i_gid = attr->gid; } +static struct inode *eventfs_get_inode (struct dentry *dentry,struct eventfs_attr *attr, +umode_t mode,struct eventfs_inode *ei) +{ +struct tracefs_inode *ti; +struct inode *inode; + + inode =tracefs_get_inode (dentry->d_sb); +if (!inode) +return NULL ; + + ti =get_tracefs (inode); + ti->private = ei; + ti->flags |=TRACEFS_EVENT_INODE ; + +update_inode_attr (dentry, inode, attr, mode); + +return inode; +} +/** * lookup_file - look up a file in the tracefs filesystem * @parent_ei: Pointer to the eventfs_inode that represents parent of the file
@@ -414,7 +433,6 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,void *data, const struct file_operations *fop) { - struct tracefs_inode *ti; struct inode *inode;if (!(mode &S_IFMT ))
@@ -423,13 +441,11 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,if (WARN_ON_ONCE (!S_ISREG (mode)))return ERR_PTR (-EIO ); - inode =tracefs_get_inode (dentry->d_sb); +/* Only directories have ti->private set to an ei, not files */ + inode =eventfs_get_inode (dentry, attr, mode,NULL );if (unlikely (!inode))return ERR_PTR (-ENOMEM ); -/* If the user updated the directory's attributes, use them */ -update_inode_attr (dentry, inode, attr, mode); - inode->i_op = &eventfs_file_inode_operations; inode->i_fop = fop; inode->i_private = data;
@@ -437,9 +453,6 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,/* All files will have the same inode number */ inode->i_ino =EVENTFS_FILE_INODE_INO ; - ti =get_tracefs (inode); - ti->flags |=TRACEFS_EVENT_INODE ; -// Files have their parent's ei as their fsdata dentry->d_fsdata =get_ei (parent_ei);
@@ -459,28 +472,19 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,static struct dentry *lookup_dir_entry (struct dentry *dentry,struct eventfs_inode *pei,struct eventfs_inode *ei) { -struct tracefs_inode *ti;struct inode *inode; +umode_t mode =S_IFDIR |S_IRWXU |S_IRUGO |S_IXUGO ; - inode =tracefs_get_inode (dentry->d_sb); + inode =eventfs_get_inode (dentry, &ei->attr, mode, ei);if (unlikely (!inode))return ERR_PTR (-ENOMEM ); -/* If the user updated the directory's attributes, use them */ -update_inode_attr (dentry, inode, &ei->attr, -S_IFDIR |S_IRWXU |S_IRUGO |S_IXUGO ); - inode->i_op = &eventfs_dir_inode_operations; inode->i_fop = &eventfs_file_operations;/* All directories will have the same inode number */ inode->i_ino =eventfs_dir_ino (ei); - ti =get_tracefs (inode); - ti->flags |=TRACEFS_EVENT_INODE ; -/* Only directories have ti->private set to an ei, not files */ - ti->private = ei; - dentry->d_fsdata =get_ei (ei);d_add (dentry, inode);
Signature · 1 line
2.43.0
Steven Rostedt
maintainerPATCH 2/4 eventfs: Remove getattr and permission callbacks
In reply to Steven RostedtFrom: "Steven Rostedt (Google)" <[email protected]>
Now that inodes have their permissions updated on remount, the only other places to update the inode permissions are when they are created and in the setattr callback. The getattr and permission callbacks are not needed as the inodes should already be set at their proper settings.
Remove the callbacks, as it not only simplifies the code, but also allows more flexibility to fix the inconsistencies with various corner cases (like changing the permission of an instance directory).
--- fs/tracefs/event_inode.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-)
fs/tracefs/event_inode.c +0 -40
@@ -250,49 +250,9 @@ static void update_events_attr(struct eventfs_inode *ei, struct super_block *sb) ei->attr.gid = parent->i_gid; } -static void set_top_events_ownership (struct inode *inode) -{ -struct tracefs_inode *ti =get_tracefs (inode); -struct eventfs_inode *ei = ti->private; - -/* The top events directory doesn't get automatically updated */ -if (!ei || !ei->is_events) -return ; - -update_events_attr (ei, inode->i_sb); - -if (!(ei->attr.mode &EVENTFS_SAVE_UID )) - inode->i_uid = ei->attr.uid; - -if (!(ei->attr.mode &EVENTFS_SAVE_GID )) - inode->i_gid = ei->attr.gid; -} - -static int eventfs_get_attr (struct mnt_idmap *idmap, -const struct path *path,struct kstat *stat, -u32 request_mask,unsigned int flags) -{ -struct dentry *dentry = path->dentry; -struct inode *inode =d_backing_inode (dentry); - -set_top_events_ownership (inode); - -generic_fillattr (idmap, request_mask, inode, stat); -return 0 ; -} - -static int eventfs_permission (struct mnt_idmap *idmap, -struct inode *inode,int mask) -{ -set_top_events_ownership (inode); -return generic_permission (idmap, inode, mask); -} -static const struct inode_operations eventfs_dir_inode_operations = { .lookup = eventfs_root_lookup, .setattr = eventfs_set_attr, - .getattr = eventfs_get_attr, - .permission = eventfs_permission, };static const struct inode_operations eventfs_file_inode_operations = {
Signature · 1 line
2.43.0
Steven Rostedt
maintainerPATCH 3/4 eventfs: Cleanup permissions in creation of inodes
In reply to Steven RostedtFrom: "Steven Rostedt (Google)" <[email protected]>
The permissions being set during the creation of the inodes was updating eventfs_inode attributes as well. Those attributes should only be touched by the setattr or remount operations, not during the creation of inodes. The eventfs_inode attributes should only be used to set the inodes and should not be modified during the inode creation.
Simplify the code and fix the situation by:
1) Removing the eventfs_find_events() and doing a simple lookup for the events descriptor in eventfs_get_inode()
2) Remove update_events_attr() as the attributes should only be used to update the inode and should not be modified here.
3) Add update_inode_attr() that uses the attributes to determine what the inode permissions should be.
4) As the parent_inode of the eventfs_root_inode structure is no longer needed, remove it.
Now on creation, the inode gets the proper permissions without causing side effects to the ei->attr field.
--- fs/tracefs/event_inode.c | 90 ++++++++++------------------------------ 1 file changed, 23 insertions(+), 67 deletions(-)
fs/tracefs/event_inode.c +23 -67
@@ -37,7 +37,6 @@ static DEFINE_MUTEX(eventfs_mutex);struct eventfs_root_inode {struct eventfs_inode ei; -struct inode *parent_inode;struct dentry *events_dir; };
@@ -229,27 +228,6 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,return ret; } -static void update_events_attr (struct eventfs_inode *ei,struct super_block *sb) -{ -struct eventfs_root_inode *rei; -struct inode *parent; - - rei =get_root_inode (ei); - -/* Use the parent inode permissions unless root set its permissions */ - parent = rei->parent_inode; - -if (rei->ei.attr.mode &EVENTFS_SAVE_UID ) - ei->attr.uid = rei->ei.attr.uid; -else - ei->attr.uid = parent->i_uid; - -if (rei->ei.attr.mode &EVENTFS_SAVE_GID ) - ei->attr.gid = rei->ei.attr.gid; -else - ei->attr.gid = parent->i_gid; -} -static const struct inode_operations eventfs_dir_inode_operations = { .lookup = eventfs_root_lookup, .setattr = eventfs_set_attr,
@@ -303,60 +281,30 @@ void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid) } } -/* Return the evenfs_inode of the "events" directory */ -static struct eventfs_inode *eventfs_find_events (struct dentry *dentry) +static void update_inode_attr (struct inode *inode,umode_t mode, +struct eventfs_attr *attr,struct eventfs_root_inode *rei) { -struct eventfs_inode *ei; - -do { -// The parent is stable because we do not do renames - dentry = dentry->d_parent; -// ... and directories always have d_fsdata - ei = dentry->d_fsdata; - -/* -* If the ei is being freed, the ownership of the children -* doesn't matter. -*/ -if (ei->is_freed) -return NULL ; - -// Walk upwards until you find the events inode - }while (!ei->is_events); - -update_events_attr (ei, dentry->d_sb); - -return ei; -} - -static void update_inode_attr (struct dentry *dentry,struct inode *inode, -struct eventfs_attr *attr,umode_t mode) -{ -struct eventfs_inode *events_ei =eventfs_find_events (dentry); - -if (!events_ei) -return ; - - inode->i_mode = mode; - inode->i_uid = events_ei->attr.uid; - inode->i_gid = events_ei->attr.gid; - -if (!attr) -return ; - -if (attr->mode &EVENTFS_SAVE_MODE ) +if (attr && attr->mode &EVENTFS_SAVE_MODE ) inode->i_mode = attr->mode &EVENTFS_MODE_MASK ; +else + inode->i_mode = mode; -if (attr->mode &EVENTFS_SAVE_UID ) +if (attr && attr->mode &EVENTFS_SAVE_UID ) inode->i_uid = attr->uid; +else + inode->i_uid = rei->ei.attr.uid; -if (attr->mode &EVENTFS_SAVE_GID ) +if (attr && attr->mode &EVENTFS_SAVE_GID ) inode->i_gid = attr->gid; +else + inode->i_gid = rei->ei.attr.gid; }static struct inode *eventfs_get_inode (struct dentry *dentry,struct eventfs_attr *attr,umode_t mode,struct eventfs_inode *ei) { +struct eventfs_root_inode *rei; +struct eventfs_inode *pei;struct tracefs_inode *ti;struct inode *inode;
@@ -368,7 +316,16 @@ static struct inode *eventfs_get_inode(struct dentry *dentry, struct eventfs_att ti->private = ei; ti->flags |=TRACEFS_EVENT_INODE ; -update_inode_attr (dentry, inode, attr, mode); +/* Find the top dentry that holds the "events" directory */ +do { + dentry = dentry->d_parent; +/* Directories always have d_fsdata */ + pei = dentry->d_fsdata; + }while (!pei->is_events); + + rei =get_root_inode (pei); + +update_inode_attr (inode, mode, attr, rei);return inode; }
@@ -805,7 +762,6 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry// Note: we have a ref to the dentry from tracefs_start_creating() rei =get_root_inode (ei); rei->events_dir = dentry; - rei->parent_inode =d_inode (dentry->d_sb->s_root); ei->entries = entries; ei->nr_entries = size;
Signature · 1 line
2.43.0
Steven Rostedt
maintainerPATCH 4/4 eventfs: Do not use attributes for events directory
In reply to Steven RostedtFrom: "Steven Rostedt (Google)" <[email protected]>
The top "events" directory has a static inode (it's created when it is and removed when the directory is removed). There's no need to use the events ei->attr to determine its permissions. But it is used for saving the permissions of the "events" directory for when it is created, as that is needed for the default permissions for the files and directories underneath it.
For example:
# cd /sys/kernel/tracing # mkdir instances/foo # chown 1001 instances/foo/events
The files under instances/foo/events should still have the same owner as instances/foo (which the instances/foo/events ei->attr will hold), but the events directory now has owner 1001.
--- fs/tracefs/event_inode.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
fs/tracefs/event_inode.c +7 -7
@@ -210,7 +210,9 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,* determined by the parent directory. */ if (dentry->d_inode->i_mode &S_IFDIR ) { -update_attr (&ei->attr, iattr); +/* Just use the inode permissions for the events directory */ +if (!ei->is_events) +update_attr (&ei->attr, iattr); }else { name = dentry->d_name.name;
@@ -771,14 +773,12 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry uid =d_inode (dentry->d_parent)->i_uid; gid =d_inode (dentry->d_parent)->i_gid; - ei->attr.uid = uid; - ei->attr.gid = gid; -/* -* When the "events" directory is created, it takes on the -* permissions of its parent. But can be reset on remount. +* The ei->attr will be used as the default values for the +* files beneath this directory. */ - ei->attr.mode |=EVENTFS_SAVE_UID |EVENTFS_SAVE_GID ; + ei->attr.uid = uid; + ei->attr.gid = gid;INIT_LIST_HEAD (&ei->children);INIT_LIST_HEAD (&ei->list);
Signature · 1 line
2.43.0