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-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180124115143.14322-8-jolsa@kernel.org>
Date:   Wed, 24 Jan 2018 12:51:29 +0100
From:   Jiri Olsa <jolsa@...nel.org>
To:     Peter Zijlstra <a.p.zijlstra@...llo.nl>,
        Ingo Molnar <mingo@...nel.org>
Cc:     lkml <linux-kernel@...r.kernel.org>,
        Namhyung Kim <namhyung@...nel.org>,
        David Ahern <dsahern@...il.com>,
        Andi Kleen <ak@...ux.intel.com>,
        Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
        Andy Lutomirski <luto@...capital.net>,
        Arnaldo Carvalho de Melo <acme@...nel.org>
Subject: [PATCH 07/21] perf: Add PERF_SAMPLE_USER_DATA_ID sample type

We need to add id to connect sample and user data
event in case one of them get lost. Adding new
PERF_SAMPLE_USER_DATA_ID for that purpose.

Samples mark with PERF_RECORD_MISC_USER_DATA carry
current user data ID, otherwise that field is 0.

This will be used in user space to connect samples
with USER DATA event and force proper link in cases
of lost events.

Link: http://lkml.kernel.org/n/tip-j8azyyhfgipc6mn8amfpy8hm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@...nel.org>
---
 include/linux/perf_event.h            |  2 ++
 include/linux/sched.h                 |  1 +
 include/uapi/linux/perf_event.h       | 14 +++++++++++++-
 kernel/events/core.c                  | 21 +++++++++++++++++++++
 tools/include/uapi/linux/perf_event.h |  3 ++-
 5 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index b716bbca6f87..225f0787d886 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -918,6 +918,8 @@ struct perf_sample_data {
 	u64				stack_user_size;
 
 	u64				phys_addr;
+
+	u64				user_data_id;
 } ____cacheline_aligned;
 
 /* default value for data source */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 101c49cdde09..a2e041acfc4e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -518,6 +518,7 @@ struct perf_user_data {
 	u64				 type;
 	int				 enabled_count;
 	struct mutex			 enabled_mutex;
+	u64				 id;
 };
 
 enum perf_event_task_context {
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index f7b152a2f004..3df8024f54f1 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -141,8 +141,9 @@ enum perf_event_sample_format {
 	PERF_SAMPLE_TRANSACTION			= 1U << 17,
 	PERF_SAMPLE_REGS_INTR			= 1U << 18,
 	PERF_SAMPLE_PHYS_ADDR			= 1U << 19,
+	PERF_SAMPLE_USER_DATA_ID		= 1U << 20,
 
-	PERF_SAMPLE_MAX = 1U << 20,		/* non-ABI */
+	PERF_SAMPLE_MAX = 1U << 21,		/* non-ABI */
 };
 
 /*
@@ -823,6 +824,7 @@ enum perf_event_type {
 	 *	{ u64			abi; # enum perf_sample_regs_abi
 	 *	  u64			regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
 	 *	{ u64			phys_addr;} && PERF_SAMPLE_PHYS_ADDR
+	 *	{ u64			user_data_id;} && PERF_SAMPLE_USER_DATA_ID
 	 * };
 	 */
 	PERF_RECORD_SAMPLE			= 9,
@@ -932,6 +934,16 @@ enum perf_event_type {
 	 * struct {
 	 *	struct perf_event_header	header;
 	 *	u64				sample_type;
+	 *
+	 *	# The sample_type value could contain following
+	 *	# PERF_SAMPLE_* bits:
+	 *	#
+	 *	#   PERF_SAMPLE_USER_DATA_ID
+	 *	#
+	 *	# and governs the data portion:
+	 *
+	 *	{ u64		user_data_id;} && PERF_SAMPLE_USER_DATA_ID
+	 *
 	 *	struct sample_id		sample_id;
 	 * };
 	 */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8162cadb6736..1edf02dcd6e8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1566,6 +1566,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
 	if (sample_type & PERF_SAMPLE_PHYS_ADDR)
 		size += sizeof(data->phys_addr);
 
+	if (sample_type & PERF_SAMPLE_USER_DATA_ID)
+		size += sizeof(data->user_data_id);
+
 	event->header_size = size;
 }
 
@@ -5931,6 +5934,9 @@ void perf_output_sample(struct perf_output_handle *handle,
 	if (sample_type & PERF_SAMPLE_PHYS_ADDR)
 		perf_output_put(handle, data->phys_addr);
 
+	if (sample_type & PERF_SAMPLE_USER_DATA_ID)
+		perf_output_put(handle, data->user_data_id);
+
 	if (!event->attr.watermark) {
 		int wakeup_events = event->attr.wakeup_events;
 
@@ -6152,6 +6158,9 @@ void perf_prepare_sample(struct perf_event_header *header,
 	if (sample_type & PERF_SAMPLE_PHYS_ADDR)
 		data->phys_addr = perf_virt_to_phys(data->addr);
 
+	if (sample_type & PERF_SAMPLE_USER_DATA_ID)
+		data->user_data_id = 0;
+
 	if (ud.allow && ud.type) {
 		struct perf_user_data *user_data = &current->perf_user_data;
 
@@ -6160,6 +6169,8 @@ void perf_prepare_sample(struct perf_event_header *header,
 
 		if (!user_data->state)
 			user_data->state = PERF_USER_DATA_STATE_ENABLE;
+
+		data->user_data_id = user_data->id;
 	}
 }
 
@@ -6367,13 +6378,21 @@ static void perf_user_data_output(struct perf_event *event, void *data)
 		return;
 
 	user->event_id.type  = event->attr.sample_type & user_data->type;
+	user->event_id.type |= event->attr.sample_type & PERF_SAMPLE_USER_DATA_ID;
 
 	perf_event_header__init_id(&user->event_id.header, &sample, event);
 
+	if (user->event_id.type & PERF_SAMPLE_USER_DATA_ID)
+		user->event_id.header.size += sizeof(u64);
+
 	if (perf_output_begin(&handle, event, user->event_id.header.size))
 		goto out;
 
 	perf_output_put(&handle, user->event_id);
+
+	if (user->event_id.type & PERF_SAMPLE_USER_DATA_ID)
+		perf_output_put(&handle, user_data->id);
+
 	perf_event__output_id_sample(event, &handle, &sample);
 	perf_output_end(&handle);
 out:
@@ -6402,6 +6421,7 @@ static void perf_user_data_event(struct perf_user_data *user_data)
 	 */
 	user_data->type  = 0;
 	user_data->state = PERF_USER_DATA_STATE_OFF;
+	user_data->id++;
 }
 
 static void perf_user_data_work(struct callback_head *work)
@@ -11124,6 +11144,7 @@ int perf_event_init_task(struct task_struct *child)
 	INIT_LIST_HEAD(&child->perf_event_list);
 	init_task_work(&child->perf_user_data.work, perf_user_data_work);
 	mutex_init(&child->perf_user_data.enabled_mutex);
+	child->perf_user_data.id = 0;
 
 	for_each_task_context_nr(ctxn) {
 		ret = perf_event_init_context(child, ctxn);
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index c77c9a2ebbbb..dea5e9c32e8a 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -141,8 +141,9 @@ enum perf_event_sample_format {
 	PERF_SAMPLE_TRANSACTION			= 1U << 17,
 	PERF_SAMPLE_REGS_INTR			= 1U << 18,
 	PERF_SAMPLE_PHYS_ADDR			= 1U << 19,
+	PERF_SAMPLE_USER_DATA_ID		= 1U << 20,
 
-	PERF_SAMPLE_MAX = 1U << 20,		/* non-ABI */
+	PERF_SAMPLE_MAX = 1U << 21,		/* non-ABI */
 };
 
 /*
-- 
2.13.6

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ