lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 25 Jun 2014 20:44:34 +0200
From:	Jiri Olsa <jolsa@...nel.org>
To:	linux-kernel@...r.kernel.org
Cc:	Arnaldo Carvalho de Melo <acme@...nel.org>,
	Corey Ashford <cjashfor@...ux.vnet.ibm.com>,
	Frederic Weisbecker <fweisbec@...il.com>,
	Ingo Molnar <mingo@...nel.org>,
	Paul Mackerras <paulus@...ba.org>,
	Peter Zijlstra <a.p.zijlstra@...llo.nl>,
	Jiri Olsa <jolsa@...nel.org>
Subject: [PATCH 0/1] perf: Fix race in sample output

hi,
the perf test patch below is not to be merged. It's
just to show how to hit issue fixed by patch 1/1.

thanks,
jirka


Cc: Arnaldo Carvalho de Melo <acme@...nel.org>
Cc: Corey Ashford <cjashfor@...ux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@...il.com>
Cc: Ingo Molnar <mingo@...nel.org>
Cc: Paul Mackerras <paulus@...ba.org>
Cc: Peter Zijlstra <a.p.zijlstra@...llo.nl>
Signed-off-by: Jiri Olsa <jolsa@...nel.org>
---
 tools/perf/Makefile.perf          |   1 +
 tools/perf/tests/builtin-test.c   |   4 +
 tools/perf/tests/group-read-bug.c | 169 ++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h          |   1 +
 4 files changed, 175 insertions(+)
 create mode 100644 tools/perf/tests/group-read-bug.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9670a16..909084f 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -419,6 +419,7 @@ endif
 endif
 LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
 LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
+LIB_OBJS += $(OUTPUT)tests/group-read-bug.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6f8b01b..2b2d544 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -154,6 +154,10 @@ static struct test {
 		.func = test__hists_cumulate,
 	},
 	{
+		.desc = "Test group read bug",
+		.func = test__group_read_bug,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/group-read-bug.c b/tools/perf/tests/group-read-bug.c
new file mode 100644
index 0000000..d69fabf
--- /dev/null
+++ b/tools/perf/tests/group-read-bug.c
@@ -0,0 +1,169 @@
+#include <unistd.h>
+#include <sys/syscall.h>   /* For SYS_xxx definitions */
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <pthread.h>
+#include "tests.h"
+#include "perf.h"
+#include "debug.h"
+#include "trace-event.h"
+
+static int fd_leader;
+static bool done;
+static int pid;
+
+static int create_event(int group_fd)
+{
+	struct perf_event_attr pe;
+	struct event_format* format;
+	int fd;
+
+	memset(&pe, 0, sizeof(struct perf_event_attr));
+	pe.type = PERF_TYPE_TRACEPOINT;
+	pe.size = sizeof(struct perf_event_attr);
+
+	format = trace_event__tp_format("syscalls", "sys_enter_read");
+	if (!format)
+		return TEST_FAIL;
+
+	pe.config = format->id;
+	pe.sample_period = 1;
+	pe.sample_type = PERF_SAMPLE_ID|PERF_SAMPLE_READ;
+	pe.read_format = PERF_FORMAT_ID|PERF_FORMAT_GROUP;
+
+	if (group_fd == -1)
+		pe.disabled = 1;
+
+	fd = sys_perf_event_open(&pe, pid, -1, group_fd, 0);
+	if (fd < 0) {
+		pr_debug("failed opening event %llx, errno %d\n",
+			 pe.config, errno);
+		return TEST_FAIL;
+	}
+
+	return fd;
+}
+
+static __u64 read_head(struct perf_event_mmap_page *pc)
+{
+	__u64 head = ACCESS_ONCE(pc->data_head);
+	rmb();
+	return head;
+}
+
+static void write_tail(struct perf_event_mmap_page *pc, __u64 tail)
+{
+	mb();
+	pc->data_tail = tail;
+}
+
+static void mmap_read(struct perf_event_mmap_page *pc, int mask)
+{
+	__u64 old = 0;
+	__u64 empty = 0;
+
+	while (!done) {
+		__u64 size, head;
+
+		head = read_head(pc);
+
+		if (old == head) {
+			empty++;
+			continue;
+		}
+
+		size = head - old;
+
+		pr_debug("empty %llu, head = %llu, size %llu\n", empty, head, size);
+		empty = 0;
+
+		if ((old & mask) + size != (head & mask)) {
+			size = mask + 1 - (old & mask);
+			old += size;
+		}
+
+		size = head - old;
+		old += size;
+		write_tail(pc, old);
+	}
+}
+
+static void *worker_thread(void *data __maybe_unused)
+{
+#define CNT 1000
+	int fds[CNT];
+
+	while (!done) {
+		int i;
+
+		for (i = 0; i < CNT; i++)
+			fds[i] = create_event(fd_leader);
+
+		for (i = 0; i < CNT; i++)
+			close(fds[i]);
+	}
+
+	return NULL;
+}
+
+static void *gen_thread(void *data __maybe_unused)
+{
+	pid = syscall(SYS_gettid);
+
+	while (!done) {
+		int i;
+
+		i = read(300, &i, sizeof(i));
+	}
+
+	return NULL;
+}
+
+static void signal_fn(int signo __maybe_unused)
+{
+	done = 1;
+}
+
+int test__group_read_bug(void)
+{
+	pthread_t pthread, pthread_gen;
+	int mmap_len  = page_size + (page_size  << 5);
+	int mmap_mask = mmap_len - page_size - 1;
+	void *buf;
+	int err;
+
+	signal(SIGINT,  signal_fn);
+
+	err = pthread_create(&pthread, NULL, gen_thread, NULL);
+	TEST_ASSERT_VAL("create gen", !err);
+
+	while(!pid) {
+		pr_debug("waiting for pid\n");
+		sleep(1);
+	}
+
+	fd_leader = create_event(-1);
+	TEST_ASSERT_VAL("create a leader", fd_leader >= 0);
+
+	buf = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd_leader, 0);
+	TEST_ASSERT_VAL("mmap leader", buf != MAP_FAILED);
+
+	err = ioctl(fd_leader, PERF_EVENT_IOC_ENABLE, 0);
+	TEST_ASSERT_VAL("enable leader", !err);
+
+	err = pthread_create(&pthread_gen, NULL, worker_thread, NULL);
+	TEST_ASSERT_VAL("create worker", !err);
+
+	mmap_read(buf, mmap_mask);
+
+	munmap(buf, mmap_len);
+	close(fd_leader);
+
+	pthread_join(pthread, NULL);
+	pthread_join(pthread_gen, NULL);
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index ed64790..af43c47 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -48,6 +48,7 @@ int test__mmap_thread_lookup(void);
 int test__thread_mg_share(void);
 int test__hists_output(void);
 int test__hists_cumulate(void);
+int test__group_read_bug(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ