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>,
Beau Belgrave <beaub@linux.microsoft.com>
Subject: [for-next][PATCH 18/25] tracing/user_events: Add ABI self-test
Date: Wed, 29 Mar 2023 15:45:34 -0400 [thread overview]
Message-ID: <20230329194552.684425169@goodmis.org> (raw)
In-Reply-To: 20230329194516.146147554@goodmis.org
From: Beau Belgrave <beaub@linux.microsoft.com>
Add ABI specific self-test to ensure enablements work in various
scenarios such as fork, VM_CLONE, and basic event enable/disable.
Ensure ABI contracts/limits are also being upheld, such as bit limits
and data size limits.
Link: https://lkml.kernel.org/r/20230328235219.203-8-beaub@linux.microsoft.com
Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
tools/testing/selftests/user_events/Makefile | 2 +-
.../testing/selftests/user_events/abi_test.c | 226 ++++++++++++++++++
2 files changed, 227 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/user_events/abi_test.c
diff --git a/tools/testing/selftests/user_events/Makefile b/tools/testing/selftests/user_events/Makefile
index 6b512b86aec3..9e95bd41b0b4 100644
--- a/tools/testing/selftests/user_events/Makefile
+++ b/tools/testing/selftests/user_events/Makefile
@@ -10,7 +10,7 @@ LDLIBS += -lrt -lpthread -lm
# This test will not compile until user_events.h is added
# back to uapi.
-TEST_GEN_PROGS = ftrace_test dyn_test perf_test
+TEST_GEN_PROGS = ftrace_test dyn_test perf_test abi_test
TEST_FILES := settings
diff --git a/tools/testing/selftests/user_events/abi_test.c b/tools/testing/selftests/user_events/abi_test.c
new file mode 100644
index 000000000000..e0323d3777a7
--- /dev/null
+++ b/tools/testing/selftests/user_events/abi_test.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * User Events ABI Test Program
+ *
+ * Copyright (c) 2022 Beau Belgrave <beaub@linux.microsoft.com>
+ */
+
+#define _GNU_SOURCE
+#include <sched.h>
+
+#include <errno.h>
+#include <linux/user_events.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+
+#include "../kselftest_harness.h"
+
+const char *data_file = "/sys/kernel/tracing/user_events_data";
+const char *enable_file = "/sys/kernel/tracing/events/user_events/__abi_event/enable";
+
+static int change_event(bool enable)
+{
+ int fd = open(enable_file, O_RDWR);
+ int ret;
+
+ if (fd < 0)
+ return -1;
+
+ if (enable)
+ ret = write(fd, "1", 1);
+ else
+ ret = write(fd, "0", 1);
+
+ close(fd);
+
+ if (ret == 1)
+ ret = 0;
+ else
+ ret = -1;
+
+ return ret;
+}
+
+static int reg_enable(long *enable, int size, int bit)
+{
+ struct user_reg reg = {0};
+ int fd = open(data_file, O_RDWR);
+ int ret;
+
+ if (fd < 0)
+ return -1;
+
+ reg.size = sizeof(reg);
+ reg.name_args = (__u64)"__abi_event";
+ reg.enable_bit = bit;
+ reg.enable_addr = (__u64)enable;
+ reg.enable_size = size;
+
+ ret = ioctl(fd, DIAG_IOCSREG, ®);
+
+ close(fd);
+
+ return ret;
+}
+
+static int reg_disable(long *enable, int bit)
+{
+ struct user_unreg reg = {0};
+ int fd = open(data_file, O_RDWR);
+ int ret;
+
+ if (fd < 0)
+ return -1;
+
+ reg.size = sizeof(reg);
+ reg.disable_bit = bit;
+ reg.disable_addr = (__u64)enable;
+
+ ret = ioctl(fd, DIAG_IOCSUNREG, ®);
+
+ close(fd);
+
+ return ret;
+}
+
+FIXTURE(user) {
+ long check;
+};
+
+FIXTURE_SETUP(user) {
+ change_event(false);
+ self->check = 0;
+}
+
+FIXTURE_TEARDOWN(user) {
+}
+
+TEST_F(user, enablement) {
+ /* Changes should be reflected immediately */
+ ASSERT_EQ(0, self->check);
+ ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0));
+ ASSERT_EQ(0, change_event(true));
+ ASSERT_EQ(1, self->check);
+ ASSERT_EQ(0, change_event(false));
+ ASSERT_EQ(0, self->check);
+
+ /* Should not change after disable */
+ ASSERT_EQ(0, change_event(true));
+ ASSERT_EQ(1, self->check);
+ ASSERT_EQ(0, reg_disable(&self->check, 0));
+ ASSERT_EQ(0, change_event(false));
+ ASSERT_EQ(1, self->check);
+ self->check = 0;
+}
+
+TEST_F(user, bit_sizes) {
+ /* Allow 0-31 bits for 32-bit */
+ ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0));
+ ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 31));
+ ASSERT_NE(0, reg_enable(&self->check, sizeof(int), 32));
+ ASSERT_EQ(0, reg_disable(&self->check, 0));
+ ASSERT_EQ(0, reg_disable(&self->check, 31));
+
+#if BITS_PER_LONG == 8
+ /* Allow 0-64 bits for 64-bit */
+ ASSERT_EQ(0, reg_enable(&self->check, sizeof(long), 63));
+ ASSERT_NE(0, reg_enable(&self->check, sizeof(long), 64));
+ ASSERT_EQ(0, reg_disable(&self->check, 63));
+#endif
+
+ /* Disallowed sizes (everything beside 4 and 8) */
+ ASSERT_NE(0, reg_enable(&self->check, 1, 0));
+ ASSERT_NE(0, reg_enable(&self->check, 2, 0));
+ ASSERT_NE(0, reg_enable(&self->check, 3, 0));
+ ASSERT_NE(0, reg_enable(&self->check, 5, 0));
+ ASSERT_NE(0, reg_enable(&self->check, 6, 0));
+ ASSERT_NE(0, reg_enable(&self->check, 7, 0));
+ ASSERT_NE(0, reg_enable(&self->check, 9, 0));
+ ASSERT_NE(0, reg_enable(&self->check, 128, 0));
+}
+
+TEST_F(user, forks) {
+ int i;
+
+ /* Ensure COW pages get updated after fork */
+ ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0));
+ ASSERT_EQ(0, self->check);
+
+ if (fork() == 0) {
+ /* Force COW */
+ self->check = 0;
+
+ /* Up to 1 sec for enablement */
+ for (i = 0; i < 10; ++i) {
+ usleep(100000);
+
+ if (self->check)
+ exit(0);
+ }
+
+ exit(1);
+ }
+
+ /* Allow generous time for COW, then enable */
+ usleep(100000);
+ ASSERT_EQ(0, change_event(true));
+
+ ASSERT_NE(-1, wait(&i));
+ ASSERT_EQ(0, WEXITSTATUS(i));
+
+ /* Ensure child doesn't disable parent */
+ if (fork() == 0)
+ exit(reg_disable(&self->check, 0));
+
+ ASSERT_NE(-1, wait(&i));
+ ASSERT_EQ(0, WEXITSTATUS(i));
+ ASSERT_EQ(1, self->check);
+ ASSERT_EQ(0, change_event(false));
+ ASSERT_EQ(0, self->check);
+}
+
+/* Waits up to 1 sec for enablement */
+static int clone_check(void *check)
+{
+ int i;
+
+ for (i = 0; i < 10; ++i) {
+ usleep(100000);
+
+ if (*(long *)check)
+ return 0;
+ }
+
+ return 1;
+}
+
+TEST_F(user, clones) {
+ int i, stack_size = 4096;
+ void *stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK,
+ -1, 0);
+
+ ASSERT_NE(MAP_FAILED, stack);
+ ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0));
+ ASSERT_EQ(0, self->check);
+
+ /* Shared VM should see enablements */
+ ASSERT_NE(-1, clone(&clone_check, stack + stack_size,
+ CLONE_VM | SIGCHLD, &self->check));
+
+ ASSERT_EQ(0, change_event(true));
+ ASSERT_NE(-1, wait(&i));
+ ASSERT_EQ(0, WEXITSTATUS(i));
+ munmap(stack, stack_size);
+ ASSERT_EQ(0, change_event(false));
+}
+
+int main(int argc, char **argv)
+{
+ return test_harness_run(argc, argv);
+}
--
2.39.1
next prev parent reply other threads:[~2023-03-29 19:46 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-29 19:45 [for-next][PATCH 00/25] tracing: Updates for 6.4 Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 01/25] fprobe: Pass entry_data to handlers Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 02/25] lib/test_fprobe: Add private entry_data testcases Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 03/25] fprobe: Add nr_maxactive to specify rethook_node pool size Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 04/25] lib/test_fprobe: Add a test case for nr_maxactive Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 05/25] fprobe: Skip exit_handler if entry_handler returns !0 Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 06/25] lib/test_fprobe: Add a testcase for skipping exit_handler Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 07/25] docs: tracing: Update fprobe documentation Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 08/25] selftests: use canonical ftrace path Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 09/25] leaking_addresses: also skip " Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 10/25] tools/kvm_stat: use " Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 11/25] tracing: Add "fields" option to show raw trace event fields Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 12/25] tracing/user_events: Split header into uapi and kernel Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 13/25] tracing/user_events: Track fork/exec/exit for mm lifetime Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 14/25] tracing/user_events: Use remote writes for event enablement Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 15/25] tracing/user_events: Fixup enable faults asyncly Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 16/25] tracing/user_events: Add ioctl for disabling addresses Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 17/25] tracing/user_events: Update self-tests to write ABI Steven Rostedt
2023-03-29 19:45 ` Steven Rostedt [this message]
2023-03-29 19:45 ` [for-next][PATCH 19/25] tracing/user_events: Use write ABI in example Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 20/25] tracing/user_events: Update documentation for ABI Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 21/25] tracing/user_events: Charge event allocs to cgroups Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 22/25] tracing/user_events: Limit global user_event count Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 23/25] tracing/user_events: Align structs with tabs for readability Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 24/25] tracing/user_events: Use print_format_fields() for trace output Steven Rostedt
2023-03-29 19:45 ` [for-next][PATCH 25/25] tracing: Unbreak user events Steven Rostedt
2023-03-29 20:29 ` 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=20230329194552.684425169@goodmis.org \
--to=rostedt@goodmis.org \
--cc=akpm@linux-foundation.org \
--cc=beaub@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.