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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250902143504.1224726-4-jolsa@kernel.org>
Date: Tue,  2 Sep 2025 16:34:56 +0200
From: Jiri Olsa <jolsa@...nel.org>
To: Oleg Nesterov <oleg@...hat.com>,
	Masami Hiramatsu <mhiramat@...nel.org>,
	Peter Zijlstra <peterz@...radead.org>,
	Andrii Nakryiko <andrii@...nel.org>
Cc: bpf@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	linux-trace-kernel@...r.kernel.org,
	x86@...nel.org,
	Song Liu <songliubraving@...com>,
	Yonghong Song <yhs@...com>,
	John Fastabend <john.fastabend@...il.com>,
	Hao Luo <haoluo@...gle.com>,
	Steven Rostedt <rostedt@...dmis.org>,
	Ingo Molnar <mingo@...nel.org>
Subject: [PATCH perf/core 03/11] perf: Add support to attach standard unique uprobe

Adding support to attach unique probe through perf uprobe pmu.

Adding new 'unique' format attribute that allows to pass the
request to create unique uprobe the uprobe consumer.

Signed-off-by: Jiri Olsa <jolsa@...nel.org>
---
 include/linux/trace_events.h    | 2 +-
 kernel/events/core.c            | 8 ++++++--
 kernel/trace/trace_event_perf.c | 4 ++--
 kernel/trace/trace_probe.h      | 2 +-
 kernel/trace/trace_uprobe.c     | 9 +++++----
 5 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 04307a19cde3..1d35727fda27 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -877,7 +877,7 @@ extern int bpf_get_kprobe_info(const struct perf_event *event,
 #endif
 #ifdef CONFIG_UPROBE_EVENTS
 extern int  perf_uprobe_init(struct perf_event *event,
-			     unsigned long ref_ctr_offset, bool is_retprobe);
+			     unsigned long ref_ctr_offset, bool is_retprobe, bool is_unique);
 extern void perf_uprobe_destroy(struct perf_event *event);
 extern int bpf_get_uprobe_info(const struct perf_event *event,
 			       u32 *fd_type, const char **filename,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 28de3baff792..10a9341c638f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -11046,11 +11046,13 @@ EXPORT_SYMBOL_GPL(perf_tp_event);
  */
 enum perf_probe_config {
 	PERF_PROBE_CONFIG_IS_RETPROBE = 1U << 0,  /* [k,u]retprobe */
+	PERF_PROBE_CONFIG_IS_UNIQUE   = 1U << 1,  /* unique uprobe */
 	PERF_UPROBE_REF_CTR_OFFSET_BITS = 32,
 	PERF_UPROBE_REF_CTR_OFFSET_SHIFT = 64 - PERF_UPROBE_REF_CTR_OFFSET_BITS,
 };
 
 PMU_FORMAT_ATTR(retprobe, "config:0");
+PMU_FORMAT_ATTR(unique, "config:1");
 #endif
 
 #ifdef CONFIG_KPROBE_EVENTS
@@ -11114,6 +11116,7 @@ PMU_FORMAT_ATTR(ref_ctr_offset, "config:32-63");
 
 static struct attribute *uprobe_attrs[] = {
 	&format_attr_retprobe.attr,
+	&format_attr_unique.attr,
 	&format_attr_ref_ctr_offset.attr,
 	NULL,
 };
@@ -11144,7 +11147,7 @@ static int perf_uprobe_event_init(struct perf_event *event)
 {
 	int err;
 	unsigned long ref_ctr_offset;
-	bool is_retprobe;
+	bool is_retprobe, is_unique;
 
 	if (event->attr.type != perf_uprobe.type)
 		return -ENOENT;
@@ -11159,8 +11162,9 @@ static int perf_uprobe_event_init(struct perf_event *event)
 		return -EOPNOTSUPP;
 
 	is_retprobe = event->attr.config & PERF_PROBE_CONFIG_IS_RETPROBE;
+	is_unique = event->attr.config & PERF_PROBE_CONFIG_IS_UNIQUE;
 	ref_ctr_offset = event->attr.config >> PERF_UPROBE_REF_CTR_OFFSET_SHIFT;
-	err = perf_uprobe_init(event, ref_ctr_offset, is_retprobe);
+	err = perf_uprobe_init(event, ref_ctr_offset, is_retprobe, is_unique);
 	if (err)
 		return err;
 
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index a6bb7577e8c5..b4383ab21d88 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -296,7 +296,7 @@ void perf_kprobe_destroy(struct perf_event *p_event)
 
 #ifdef CONFIG_UPROBE_EVENTS
 int perf_uprobe_init(struct perf_event *p_event,
-		     unsigned long ref_ctr_offset, bool is_retprobe)
+		     unsigned long ref_ctr_offset, bool is_retprobe, bool is_unique)
 {
 	int ret;
 	char *path = NULL;
@@ -317,7 +317,7 @@ int perf_uprobe_init(struct perf_event *p_event,
 	}
 
 	tp_event = create_local_trace_uprobe(path, p_event->attr.probe_offset,
-					     ref_ctr_offset, is_retprobe);
+					     ref_ctr_offset, is_retprobe, is_unique);
 	if (IS_ERR(tp_event)) {
 		ret = PTR_ERR(tp_event);
 		goto out;
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 842383fbc03b..92870b98b296 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -469,7 +469,7 @@ extern void destroy_local_trace_kprobe(struct trace_event_call *event_call);
 
 extern struct trace_event_call *
 create_local_trace_uprobe(char *name, unsigned long offs,
-			  unsigned long ref_ctr_offset, bool is_return);
+			  unsigned long ref_ctr_offset, bool is_return, bool is_unique);
 extern void destroy_local_trace_uprobe(struct trace_event_call *event_call);
 #endif
 extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 8b0bcc0d8f41..4ecb6083f949 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -333,7 +333,7 @@ trace_uprobe_primary_from_call(struct trace_event_call *call)
  * Allocate new trace_uprobe and initialize it (including uprobes).
  */
 static struct trace_uprobe *
-alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
+alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret, bool is_unique)
 {
 	struct trace_uprobe *tu;
 	int ret;
@@ -356,6 +356,7 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
 	tu->consumer.handler = uprobe_dispatcher;
 	if (is_ret)
 		tu->consumer.ret_handler = uretprobe_dispatcher;
+	tu->consumer.is_unique = is_unique;
 	init_trace_uprobe_filter(tu->tp.event->filter);
 	return tu;
 
@@ -688,7 +689,7 @@ static int __trace_uprobe_create(int argc, const char **argv)
 	argc -= 2;
 	argv += 2;
 
-	tu = alloc_trace_uprobe(group, event, argc, is_return);
+	tu = alloc_trace_uprobe(group, event, argc, is_return, false /* unique */);
 	if (IS_ERR(tu)) {
 		ret = PTR_ERR(tu);
 		/* This must return -ENOMEM otherwise there is a bug */
@@ -1636,7 +1637,7 @@ static int unregister_uprobe_event(struct trace_uprobe *tu)
 #ifdef CONFIG_PERF_EVENTS
 struct trace_event_call *
 create_local_trace_uprobe(char *name, unsigned long offs,
-			  unsigned long ref_ctr_offset, bool is_return)
+			  unsigned long ref_ctr_offset, bool is_return, bool is_unique)
 {
 	enum probe_print_type ptype;
 	struct trace_uprobe *tu;
@@ -1658,7 +1659,7 @@ create_local_trace_uprobe(char *name, unsigned long offs,
 	 * duplicated name "DUMMY_EVENT" here.
 	 */
 	tu = alloc_trace_uprobe(UPROBE_EVENT_SYSTEM, "DUMMY_EVENT", 0,
-				is_return);
+				is_return, is_unique);
 
 	if (IS_ERR(tu)) {
 		pr_info("Failed to allocate trace_uprobe.(%d)\n",
-- 
2.51.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ