From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Andrew Morton <akpm@linux-foundation.org>,
Doug Cook <dcook@linux.microsoft.com>,
Beau Belgrave <beaub@linux.microsoft.com>
Subject: [for-next][PATCH 07/11] tracing/user_events: Prevent same address and bit per process
Date: Wed, 26 Apr 2023 13:17:10 -0400 [thread overview]
Message-ID: <20230426171750.432594181@goodmis.org> (raw)
In-Reply-To: 20230426171703.202523909@goodmis.org
From: Beau Belgrave <beaub@linux.microsoft.com>
User processes register an address and bit pair for events. If the same
address and bit pair are registered multiple times in the same process,
it can cause undefined behavior when events are enabled/disabled.
When more than one are used, the bit could be turned off by another
event being disabled, while the original event is still enabled.
Prevent undefined behavior by checking the current mm to see if any
event has already been registered for the address and bit pair. Return
EADDRINUSE back to the user process if it's already being used.
Update ftrace self-test to ensure this occurs properly.
Link: https://lkml.kernel.org/r/20230425225107.8525-4-beaub@linux.microsoft.com
Suggested-by: Doug Cook <dcook@linux.microsoft.com>
Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
kernel/trace/trace_events_user.c | 41 +++++++++++++++++++
.../selftests/user_events/ftrace_test.c | 9 +++-
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
index 4f9ae63dfc5d..a29cd13caf55 100644
--- a/kernel/trace/trace_events_user.c
+++ b/kernel/trace/trace_events_user.c
@@ -419,6 +419,21 @@ static int user_event_enabler_write(struct user_event_mm *mm,
return 0;
}
+static bool user_event_enabler_exists(struct user_event_mm *mm,
+ unsigned long uaddr, unsigned char bit)
+{
+ struct user_event_enabler *enabler;
+ struct user_event_enabler *next;
+
+ list_for_each_entry_safe(enabler, next, &mm->enablers, link) {
+ if (enabler->addr == uaddr &&
+ (enabler->values & ENABLE_VAL_BIT_MASK) == bit)
+ return true;
+ }
+
+ return false;
+}
+
static void user_event_enabler_update(struct user_event *user)
{
struct user_event_enabler *enabler;
@@ -657,6 +672,22 @@ void user_event_mm_dup(struct task_struct *t, struct user_event_mm *old_mm)
user_event_mm_remove(t);
}
+static bool current_user_event_enabler_exists(unsigned long uaddr,
+ unsigned char bit)
+{
+ struct user_event_mm *user_mm = current_user_event_mm();
+ bool exists;
+
+ if (!user_mm)
+ return false;
+
+ exists = user_event_enabler_exists(user_mm, uaddr, bit);
+
+ user_event_mm_put(user_mm);
+
+ return exists;
+}
+
static struct user_event_enabler
*user_event_enabler_create(struct user_reg *reg, struct user_event *user,
int *write_result)
@@ -2048,6 +2079,16 @@ static long user_events_ioctl_reg(struct user_event_file_info *info,
if (ret)
return ret;
+ /*
+ * Prevent users from using the same address and bit multiple times
+ * within the same mm address space. This can cause unexpected behavior
+ * for user processes that is far easier to debug if this is explictly
+ * an error upon registering.
+ */
+ if (current_user_event_enabler_exists((unsigned long)reg.enable_addr,
+ reg.enable_bit))
+ return -EADDRINUSE;
+
name = strndup_user((const char __user *)(uintptr_t)reg.name_args,
MAX_EVENT_DESC);
diff --git a/tools/testing/selftests/user_events/ftrace_test.c b/tools/testing/selftests/user_events/ftrace_test.c
index 91272f9d6fce..7c99cef94a65 100644
--- a/tools/testing/selftests/user_events/ftrace_test.c
+++ b/tools/testing/selftests/user_events/ftrace_test.c
@@ -219,7 +219,12 @@ TEST_F(user, register_events) {
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
ASSERT_EQ(0, reg.write_index);
- /* Multiple registers should result in same index */
+ /* Multiple registers to the same addr + bit should fail */
+ ASSERT_EQ(-1, ioctl(self->data_fd, DIAG_IOCSREG, ®));
+ ASSERT_EQ(EADDRINUSE, errno);
+
+ /* Multiple registers to same name should result in same index */
+ reg.enable_bit = 30;
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
ASSERT_EQ(0, reg.write_index);
@@ -242,6 +247,8 @@ TEST_F(user, register_events) {
/* Unregister */
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSUNREG, &unreg));
+ unreg.disable_bit = 30;
+ ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSUNREG, &unreg));
/* Delete should work only after close and unregister */
close(self->data_fd);
--
2.39.2
next prev parent reply other threads:[~2023-04-26 17:18 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-26 17:17 [for-next][PATCH 00/11] tracing: Final fixes and minor updates before sending pull request Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 01/11] ring-buffer: Clearly check null ptr returned by rb_set_head_page() Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 02/11] tracing/user_events: Set event filter_type from type Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 03/11] tracing: Fix print_fields() for __dyn_loc/__rel_loc Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 04/11] seq_buf: Add seq_buf_do_printk() helper Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 05/11] tracing/user_events: Ensure write index cannot be negative Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 06/11] tracing/user_events: Ensure bit is cleared on unregister Steven Rostedt
2023-04-26 17:17 ` Steven Rostedt [this message]
2023-04-26 17:17 ` [for-next][PATCH 08/11] tracing/user_events: Limit max fault-in attempts Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 09/11] recordmcount: Fix memory leaks in the uwrite function Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 10/11] ring-buffer: Ensure proper resetting of atomic variables in ring_buffer_reset_online_cpus Steven Rostedt
2023-04-26 17:17 ` [for-next][PATCH 11/11] tracing: Add missing spaces in trace_print_hex_seq() 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=20230426171750.432594181@goodmis.org \
--to=rostedt@goodmis.org \
--cc=akpm@linux-foundation.org \
--cc=beaub@linux.microsoft.com \
--cc=dcook@linux.microsoft.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mhiramat@kernel.org \
/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.