Linux Trace Kernel
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Steven Rostedt" <rostedt@goodmis.org>,
	"Linux Trace Kernel" <linux-trace-kernel@vger.kernel.org>
Subject: Re: [PATCH v5] tracefs: Add read-only eventfs filesystem at /sys/kernel/events
Date: Tue, 03 Nov 2026 18:51:19 +0000	[thread overview]
Message-ID: <sashiko-outbox-195864@kernel.org> (raw)
In-Reply-To: <20261103133517.6e54a8db@gandalf.local.home>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] tracefs: tracefs_apply_options() overwrites eventfs_ro inode ownership
- [Medium] tracefs: eventfs_ro_fill_super() sets i_nlink to 2 on dynamic eventfs root
- [Low] tracefs: mismatched kernel-doc function name for __eventfs_root_lookup()
--

commit 8a085766e708c607f0750dab297b23f146dfe8b9
Author: Anubhav Shelat <ashelat@redhat.com>

tracefs: Add read-only eventfs filesystem at /sys/kernel/events

This commit introduces a read-only eventfs pseudo-filesystem mounted at
/sys/kernel/events that exposes trace event format and id files with mode
0444 to unprivileged users. It reuses the existing eventfs_inode
lazy-lookup infrastructure and tracefs inode allocator on a separate
read-only superblock.

> diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
> index 6e3513b13cfa2..43ae382cfbbfc 100644
> --- a/fs/tracefs/event_inode.c
> +++ b/fs/tracefs/event_inode.c
> @@ -16,14 +16,96 @@
>   */
>  #include <linux/fsnotify.h>
>  #include <linux/fs.h>
> +#include <linux/fs_context.h>
>  #include <linux/namei.h>
>  #include <linux/workqueue.h>
>  #include <linux/security.h>
>  #include <linux/tracefs.h>
> +#include <linux/magic.h>
>  #include <linux/kref.h>
>  #include <linux/delay.h>
>  #include "internal.h"
>  
> +static struct vfsmount *eventfs_ro_mount;
> +static int eventfs_ro_mount_count;
> +
> +static int eventfs_ro_fill_super(struct super_block *sb, struct fs_context *fc)
> +{
> +	struct inode *inode;
> +	struct dentry *root;
> +
> +	sb->s_blocksize = PAGE_SIZE;
> +	sb->s_blocksize_bits = PAGE_SHIFT;
> +	sb->s_magic = EVENTFS_SUPER_MAGIC;
> +	sb->s_op = &eventfs_ro_super_operations;
> +	sb->s_time_gran = 1;
> +	sb->s_flags |= SB_RDONLY;
> +
> +	inode = new_inode(sb);
> +	if (!inode)
> +		return -ENOMEM;
> +
> +	inode->i_ino = 1;
> +	inode->i_mode = S_IFDIR | 0555;
> +	simple_inode_init_ts(inode);
> +	inode->i_op = &simple_dir_inode_operations;
> +	inode->i_fop = &simple_dir_operations;
> +	set_nlink(inode, 2);

[Severity: Medium]
Should the root inode keep i_nlink at 1 rather than calling
set_nlink(inode, 2) in eventfs_ro_fill_super()?

When eventfs_create_events_ro_copy() later configures this root inode as the
top-level eventfs directory with eventfs_ro_dir_inode_operations and
eventfs_ro_file_operations, its subsystem subdirectories are created
dynamically on demand in lookup_dir_entry() without incrementing the parent
directory link count.

As noted in eventfs_create_events_dir(), eventfs directories keep i_nlink == 1
so userspace tools do not trust the link count:

    /*
     * Keep all eventfs directories with i_nlink == 1.
     * Due to the dynamic nature of the dentry creations and not
     * wanting to add a pointer to the parent eventfs_inode in the
     * eventfs_inode structure, keeping the i_nlink in sync with the
     * number of directories would cause too much complexity for
     * something not worth much. Keeping directory links at 1
     * tells userspace not to trust the link number.
     */

With i_nlink set to 2 on /sys/kernel/events, won't userspace directory
traversal tools such as find and fts assume the directory has no
subdirectories (st_nlink == 2) and skip recursing into the event subsystem
directories?

[ ... ]

> @@ -308,12 +404,17 @@ void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid)
>  }
>  
>  static void update_inode_attr(struct inode *inode, umode_t mode,
> -			      struct eventfs_attr *attr, struct eventfs_root_inode *rei)
> +			      struct eventfs_attr *attr, struct eventfs_root_inode *rei,
> +			      bool ro)
>  {
> +	inode->i_mode = mode;
> +
> +	/* The read-only version does not allow updates to owership or permissions */
> +	if (ro)
> +		return;
> +
>  	if (attr && attr->mode & EVENTFS_SAVE_MODE)
>  		inode->i_mode = attr->mode & EVENTFS_MODE_MASK;
> -	else
> -		inode->i_mode = mode;
>  
>  	if (attr && attr->mode & EVENTFS_SAVE_UID)
>  		inode->i_uid = attr->uid;

[ ... ]

> @@ -407,22 +512,28 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei,
>   * @dentry: the directory to look up
>   * @pei: Pointer to the parent eventfs_inode if available
>   * @ei: the eventfs_inode that represents the directory to create
> + * @ro: boolean to denote if this lookup is for the read-only version
>   *
>   * This function will look up a dentry for a directory represented by
>   * a eventfs_inode.
>   */
>  static struct dentry *lookup_dir_entry(struct dentry *dentry,
> -	struct eventfs_inode *pei, struct eventfs_inode *ei)
> +	struct eventfs_inode *pei, struct eventfs_inode *ei, bool ro)
>  {
>  	struct inode *inode;
>  	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
>  
> -	inode = eventfs_get_inode(dentry, &ei->attr, mode, ei);
> +	inode = eventfs_get_inode(dentry, &ei->attr, mode, ei, ro);
>  	if (unlikely(!inode))
>  		return ERR_PTR(-ENOMEM);
>  
> -	inode->i_op = &eventfs_dir_inode_operations;
> -	inode->i_fop = &eventfs_file_operations;
> +	if (ro) {
> +		inode->i_op = &eventfs_ro_dir_inode_operations;
> +		inode->i_fop = &eventfs_ro_file_operations;
> +	} else {
> +		inode->i_op = &eventfs_dir_inode_operations;
> +		inode->i_fop = &eventfs_file_operations;
> +	}

[ ... ]

> @@ -521,14 +640,16 @@ lookup_file_dentry(struct dentry *dentry,
>   * @dir: in which a lookup is being done
>   * @dentry: file/dir dentry
>   * @flags: Just passed to simple_lookup()
> + * @ro: Denote if this is from a read-only eventfs
>   *
>   * Used to create dynamic file/dir with-in @dir, search with-in @ei
>   * list, if @dentry found go ahead and create the file/dir
>   */
>  
> -static struct dentry *eventfs_root_lookup(struct inode *dir,
> -					  struct dentry *dentry,
> -					  unsigned int flags)
> +static struct dentry *__eventfs_root_lookup(struct inode *dir,
> +					    struct dentry *dentry,
> +					    unsigned int flags,
> +					    bool ro)

[Severity: Low]
This isn't a bug, but since eventfs_root_lookup() was renamed to
__eventfs_root_lookup(), should the function name in the kernel-doc comment
header above it also be updated to __eventfs_root_lookup to avoid a W=1
kernel-doc warning?

[ ... ]

> diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
> index f3d6188a3b7b2..dafa0d587f04c 100644
> --- a/fs/tracefs/inode.c
> +++ b/fs/tracefs/inode.c
> @@ -423,6 +423,14 @@ static const struct super_operations tracefs_super_operations = {
>  	.show_options	= tracefs_show_options,
>  };
>  
> +const struct super_operations eventfs_ro_super_operations = {
> +	.alloc_inode    = tracefs_alloc_inode,
> +	.free_inode     = tracefs_free_inode,
> +	.destroy_inode  = tracefs_destroy_inode,
> +	.drop_inode     = tracefs_drop_inode,
> +	.statfs		= simple_statfs,
> +};

[Severity: Medium]
As reported by Sashiko on v4 [1], because eventfs_ro_super_operations uses
tracefs_alloc_inode, all inodes allocated on the read-only eventfs
superblock (including the pinned root inode configured by
eventfs_create_events_ro_copy() and any cached subdirectories or files) are
linked into the global tracefs_inodes list.

While update_inode_attr() now returns early when ro is true during lookup,
when tracefs is mounted or remounted with uid= or gid= options,
tracefs_apply_options() still walks the global tracefs_inodes list without
checking if the inode belongs to the tracefs superblock:

fs/tracefs/inode.c:tracefs_apply_options() {
    ...
	list_for_each_entry_rcu(ti, &tracefs_inodes, list) {
		if (update_uid) {
			ti->flags &= ~TRACEFS_UID_PERM_SET;
			ti->vfs_inode.i_uid = fsi->uid;
		}

		if (update_gid) {
			ti->flags &= ~TRACEFS_GID_PERM_SET;
			ti->vfs_inode.i_gid = fsi->gid;
		}

		if (ti->flags & TRACEFS_EVENT_INODE)
			eventfs_remount(ti, update_uid, update_gid);
	}
    ...
}

Won't mounting or remounting tracefs with uid= or gid= overwrite i_uid and
i_gid on the pinned /sys/kernel/events root inode and all currently cached
eventfs_ro inodes, as well as invoke eventfs_remount() a second time on the
shared eventfs_inode via the eventfs_ro root inode?

Also, in lookup_dir_entry(), mode is initialized to:

	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;

When ro is true, should lookup_dir_entry() clear S_IWUSR (or use 0555 to
match the root inode in eventfs_ro_fill_super()) so subdirectories in the
read-only eventfs mount do not report 0755 permissions?

[1] https://lore.kernel.org/r/sashiko-outbox-194145@kernel.org

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103133517.6e54a8db@gandalf.local.home?part=1

  reply	other threads:[~2026-11-03 18:51 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 18:35 [PATCH v5] tracefs: Add read-only eventfs filesystem at /sys/kernel/events Steven Rostedt
2026-11-03 18:51 ` sashiko-bot [this message]
2026-11-03 20:19   ` Steven Rostedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-195864@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox