All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Sasha Levin <sashal@kernel.org>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Al Viro <viro@zeniv.linux.org.uk>,
	Christian Brauner <brauner@kernel.org>
Subject: [v6.7][PATCH 05/23] eventfs: Do ctx->pos update for all iterations in eventfs_iterate()
Date: Sat, 03 Feb 2024 20:16:20 -0500	[thread overview]
Message-ID: <20240204011827.696890375@goodmis.org> (raw)
In-Reply-To: 20240204011615.703023949@goodmis.org

From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

The ctx->pos was only updated when it added an entry, but the "skip to
current pos" check (c--) happened for every loop regardless of if the
entry was added or not. This inconsistency caused readdir to be incorrect.

It was due to:

	for (i = 0; i < ei->nr_entries; i++) {

		if (c > 0) {
			c--;
			continue;
		}

		mutex_lock(&eventfs_mutex);
		/* If ei->is_freed then just bail here, nothing more to do */
		if (ei->is_freed) {
			mutex_unlock(&eventfs_mutex);
			goto out;
		}
		r = entry->callback(name, &mode, &cdata, &fops);
		mutex_unlock(&eventfs_mutex);

		[..]
		ctx->pos++;
	}

But this can cause the iterator to return a file that was already read.
That's because of the way the callback() works. Some events may not have
all files, and the callback can return 0 to tell eventfs to skip the file
for this directory.

for instance, we have:

 # ls /sys/kernel/tracing/events/ftrace/function
format  hist  hist_debug  id  inject

and

 # ls /sys/kernel/tracing/events/sched/sched_switch/
enable  filter  format  hist  hist_debug  id  inject  trigger

Where the function directory is missing "enable", "filter" and
"trigger". That's because the callback() for events has:

static int event_callback(const char *name, umode_t *mode, void **data,
			  const struct file_operations **fops)
{
	struct trace_event_file *file = *data;
	struct trace_event_call *call = file->event_call;

[..]

	/*
	 * Only event directories that can be enabled should have
	 * triggers or filters, with the exception of the "print"
	 * event that can have a "trigger" file.
	 */
	if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) {
		if (call->class->reg && strcmp(name, "enable") == 0) {
			*mode = TRACE_MODE_WRITE;
			*fops = &ftrace_enable_fops;
			return 1;
		}

		if (strcmp(name, "filter") == 0) {
			*mode = TRACE_MODE_WRITE;
			*fops = &ftrace_event_filter_fops;
			return 1;
		}
	}

	if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) ||
	    strcmp(trace_event_name(call), "print") == 0) {
		if (strcmp(name, "trigger") == 0) {
			*mode = TRACE_MODE_WRITE;
			*fops = &event_trigger_fops;
			return 1;
		}
	}
[..]
	return 0;
}

Where the function event has the TRACE_EVENT_FL_IGNORE_ENABLE set.

This means that the entries array elements for "enable", "filter" and
"trigger" when called on the function event will have the callback return
0 and not 1, to tell eventfs to skip these files for it.

Because the "skip to current ctx->pos" check happened for all entries, but
the ctx->pos++ only happened to entries that exist, it would confuse the
reading of a directory. Which would cause:

 # ls /sys/kernel/tracing/events/ftrace/function/
format  hist  hist  hist_debug  hist_debug  id  inject  inject

The missing "enable", "filter" and "trigger" caused ls to show "hist",
"hist_debug" and "inject" twice.

Update the ctx->pos for every iteration to keep its update and the "skip"
update consistent. This also means that on error, the ctx->pos needs to be
decremented if it was incremented without adding something.

Link: https://lore.kernel.org/all/20240104150500.38b15a62@gandalf.local.home/
Link: https://lore.kernel.org/linux-trace-kernel/20240104220048.172295263@goodmis.org

Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: 493ec81a8fb8e ("eventfs: Stop using dcache_readdir() for getdents()")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 fs/tracefs/event_inode.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index 0aca6910efb3..c73fb1f7ddbc 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -760,6 +760,8 @@ static int eventfs_iterate(struct file *file, struct dir_context *ctx)
 			continue;
 		}
 
+		ctx->pos++;
+
 		if (ei_child->is_freed)
 			continue;
 
@@ -767,13 +769,12 @@ static int eventfs_iterate(struct file *file, struct dir_context *ctx)
 
 		dentry = create_dir_dentry(ei, ei_child, ei_dentry);
 		if (!dentry)
-			goto out;
+			goto out_dec;
 		ino = dentry->d_inode->i_ino;
 		dput(dentry);
 
 		if (!dir_emit(ctx, name, strlen(name), ino, DT_DIR))
-			goto out;
-		ctx->pos++;
+			goto out_dec;
 	}
 
 	for (i = 0; i < ei->nr_entries; i++) {
@@ -784,6 +785,8 @@ static int eventfs_iterate(struct file *file, struct dir_context *ctx)
 			continue;
 		}
 
+		ctx->pos++;
+
 		entry = &ei->entries[i];
 		name = entry->name;
 
@@ -791,7 +794,7 @@ static int eventfs_iterate(struct file *file, struct dir_context *ctx)
 		/* If ei->is_freed then just bail here, nothing more to do */
 		if (ei->is_freed) {
 			mutex_unlock(&eventfs_mutex);
-			goto out;
+			goto out_dec;
 		}
 		r = entry->callback(name, &mode, &cdata, &fops);
 		mutex_unlock(&eventfs_mutex);
@@ -800,19 +803,23 @@ static int eventfs_iterate(struct file *file, struct dir_context *ctx)
 
 		dentry = create_file_dentry(ei, i, ei_dentry, name, mode, cdata, fops);
 		if (!dentry)
-			goto out;
+			goto out_dec;
 		ino = dentry->d_inode->i_ino;
 		dput(dentry);
 
 		if (!dir_emit(ctx, name, strlen(name), ino, DT_REG))
-			goto out;
-		ctx->pos++;
+			goto out_dec;
 	}
 	ret = 1;
  out:
 	srcu_read_unlock(&eventfs_srcu, idx);
 
 	return ret;
+
+ out_dec:
+	/* Incremented ctx->pos without adding something, reset it */
+	ctx->pos--;
+	goto out;
 }
 
 /**
-- 
2.43.0



  parent reply	other threads:[~2024-02-04  1:18 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-04  1:16 [v6.7][PATCH 00/23] eventfs: Linus's updates for 6.7 Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 01/23] eventfs: Remove "lookup" parameter from create_dir/file_dentry() Steven Rostedt
2024-02-04  1:19   ` kernel test robot
2024-02-04  1:16 ` [v6.7][PATCH 02/23] eventfs: Stop using dcache_readdir() for getdents() Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 03/23] tracefs/eventfs: Use root and instance inodes as default ownership Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 04/23] eventfs: Have eventfs_iterate() stop immediately if ei->is_freed is set Steven Rostedt
2024-02-04  1:16 ` Steven Rostedt [this message]
2024-02-04  1:16 ` [v6.7][PATCH 06/23] eventfs: Read ei->entries before ei->children in eventfs_iterate() Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 07/23] eventfs: Shortcut eventfs_iterate() by skipping entries already read Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 08/23] eventfs: Have the inodes all for files and directories all be the same Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 09/23] eventfs: Do not create dentries nor inodes in iterate_shared Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 10/23] eventfs: Use kcalloc() instead of kzalloc() Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 11/23] eventfs: Save directory inodes in the eventfs_inode structure Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 12/23] tracefs: remove stale update_gid code Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 13/23] tracefs: Zero out the tracefs_inode when allocating it Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 14/23] eventfs: Initialize the tracefs inode properly Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 15/23] tracefs: Avoid using the ei->dentry pointer unnecessarily Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 16/23] tracefs: dentry lookup crapectomy Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 17/23] eventfs: Remove unused d_parent pointer field Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 18/23] eventfs: Clean up dentry ops and add revalidate function Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 19/23] eventfs: Get rid of dentry pointers without refcounts Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 20/23] eventfs: Warn if an eventfs_inode is freed without is_freed being set Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 21/23] eventfs: Restructure eventfs_inode structure to be more condensed Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 22/23] eventfs: Remove fsnotify*() functions from lookup() Steven Rostedt
2024-02-04  1:16 ` [v6.7][PATCH 23/23] eventfs: Keep all directory links at 1 Steven Rostedt
2024-02-04  1:25 ` [v6.7][PATCH 00/23] eventfs: Linus's updates for 6.7 Steven Rostedt
2024-02-05 13:14   ` Greg Kroah-Hartman

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=20240204011827.696890375@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=akpm@linux-foundation.org \
    --cc=brauner@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.