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: <20130516114857.13508.31664.stgit@mhiramat-M0-7522>
Date:	Thu, 16 May 2013 20:48:57 +0900
From:	Masami Hiramatsu <masami.hiramatsu.pt@...achi.com>
To:	linux-kernel@...r.kernel.org, Steven Rostedt <rostedt@...dmis.org>
Cc:	Srikar Dronamraju <srikar@...ux.vnet.ibm.com>,
	Frederic Weisbecker <fweisbec@...il.com>,
	yrl.pp-manager.tt@...achi.com, Oleg Nesterov <oleg@...hat.com>,
	Ingo Molnar <mingo@...hat.com>,
	Tom Zanussi <tom.zanussi@...el.com>
Subject: [PATCH 4/5] tracing/kprobes: Allow user to delete kprobe events by
 wild cards

Allow user to delete multiple kprobe events by using
wild cards. This makes removing events on a specific
function easy.

e.g.)
 # echo p vfs_symlink >> kprobe_events
 # echo p vfs_symlink+5 >> kprobe_events
 # echo p vfs_read >> kprobe_events
 # cat kprobe_events
p:kprobes/p_vfs_symlink_0 vfs_symlink
p:kprobes/p_vfs_symlink_5 vfs_symlink+5
p:kprobes/p_vfs_read_0 vfs_read
 # echo -:kprobes/\*vfs_symlink_\* >> kprobe_events
 # cat kprobe_events
p:kprobes/p_vfs_read_0 vfs_read

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@...achi.com>
Cc: Steven Rostedt <rostedt@...dmis.org>
Cc: Frederic Weisbecker <fweisbec@...il.com>
Cc: Ingo Molnar <mingo@...hat.com>
---
 Documentation/trace/kprobetrace.txt |   19 ++++---
 kernel/trace/trace_kprobe.c         |   97 +++++++++++++++++++++++++----------
 2 files changed, 82 insertions(+), 34 deletions(-)

diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index d68ea5f..04f22be 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -26,9 +26,9 @@ Synopsis of kprobe_events
   r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS]		: Set a return probe
   -:[GRP/]EVENT						: Clear a probe
 
- GRP		: Group name. If omitted, use "kprobes" for it.
+ GRP		: Group name. If omitted, use "kprobes" for it.(*)
  EVENT		: Event name. If omitted, the event name is generated
-		  based on SYM+offs or MEMADDR.
+		  based on SYM+offs or MEMADDR.(*)
  MOD		: Module name which has given SYM.
  SYM[+offs]	: Symbol+offset where the probe is inserted.
  MEMADDR	: Address where the probe is inserted.
@@ -39,15 +39,16 @@ Synopsis of kprobe_events
   @SYM[+|-offs]	: Fetch memory at SYM +|- offs (SYM should be a data symbol)
   $stackN	: Fetch Nth entry of stack (N >= 0)
   $stack	: Fetch stack address.
-  $retval	: Fetch return value.(*)
-  +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
+  $retval	: Fetch return value.(**)
+  +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(***)
   NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
   FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
 		  (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield
 		  are supported.
 
-  (*) only for return probe.
-  (**) this is useful for fetching a field of data structures.
+  (*) both GRP and EVENT accept glob-style wild cards when clearing probes.
+  (**) only for return probe.
+  (***) this is useful for fetching a field of data structures.
 
 Types
 -----
@@ -143,7 +144,11 @@ REC->dfd, REC->filename, REC->flags, REC->mode
 
   echo -:myprobe >> kprobe_events
 
- This clears probe points selectively.
+ This removes a probe points selectively. Since the event name and group
+ name accept wild cards only when removing, you can clear all event as
+ below too.
+
+  echo '-:*/*' >> kprobe_events
 
  Right after definition, each event is disabled by default. For tracing these
 events, you need to enable it.
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 9f46e98..b619853 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -171,16 +171,32 @@ static void free_trace_probe(struct trace_probe *tp)
 	kfree(tp);
 }
 
-static struct trace_probe *find_trace_probe(const char *event,
-					    const char *group)
+/**
+ * find_trace_probes - find matched trace_probe and return the number of it
+ * @event: event name (glob pattern)
+ * @group: group(subsystem) name (glob pattern)
+ * @buf:   the address of an array of trace_probe *
+ * @size:  the size of @buf array
+ *
+ * Search trace_probe matched with given name (pattern) and returns
+ * the number of it. If @buf is not NULL, it records the address of
+ * the matched trace_probe on it.
+ */
+static int
+find_trace_probes(const char *event, const char *group,
+		  struct trace_probe **buf, int size)
 {
 	struct trace_probe *tp;
+	int count = 0;
 
 	list_for_each_entry(tp, &probe_list, list)
-		if (strcmp(tp->call.name, event) == 0 &&
-		    strcmp(tp->call.class->system, group) == 0)
-			return tp;
-	return NULL;
+		if (strglobmatch(event, tp->call.name) &&
+		    strglobmatch(group, tp->call.class->system)) {
+			if (buf && count < size)
+				buf[count] = tp;
+			count++;
+		}
+	return count;
 }
 
 static int trace_probe_nr_files(struct trace_probe *tp)
@@ -414,8 +430,9 @@ static int register_trace_probe(struct trace_probe *tp)
 	mutex_lock(&probe_lock);
 
 	/* Delete old (same name) event if exist */
-	old_tp = find_trace_probe(tp->call.name, tp->call.class->system);
-	if (old_tp) {
+	ret = find_trace_probes(tp->call.name, tp->call.class->system,
+				&old_tp, 1);
+	if (ret) {
 		ret = unregister_trace_probe(old_tp);
 		if (ret < 0)
 			goto end;
@@ -475,6 +492,49 @@ static struct notifier_block trace_probe_module_nb = {
 	.priority = 1	/* Invoked after kprobe module callback */
 };
 
+static int delete_trace_probe(const char *event, const char *group)
+{
+	struct trace_probe **tps;
+	int nr_tps, i, ret = 0;
+
+	if (!event) {
+		pr_info("Delete command needs an event name.\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&probe_lock);
+
+	nr_tps = find_trace_probes(event, group, NULL, 0);
+	if (nr_tps == 0) {
+		pr_info("Event %s/%s doesn't matched.\n", group, event);
+		ret = -ENOENT;
+		goto out_unlock;
+	}
+
+	tps = kzalloc(nr_tps * sizeof(*tps), GFP_KERNEL);
+	if (!tps) {
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	find_trace_probes(event, group, tps, nr_tps);
+
+	for (i = 0; i < nr_tps; i++) {
+		ret = unregister_trace_probe(tps[i]);
+		if (ret < 0) {
+			pr_info("Failed to delete event: %d\n", ret);
+			continue;	/* Greedy cleanup */
+		}
+		free_trace_probe(tps[i]);
+	}
+	ret = 0;
+	kfree(tps);
+
+ out_unlock:
+	mutex_unlock(&probe_lock);
+	return ret;
+}
+
 static int create_trace_probe(int argc, char **argv)
 {
 	/*
@@ -536,25 +596,8 @@ static int create_trace_probe(int argc, char **argv)
 	if (!group)
 		group = KPROBE_EVENT_SYSTEM;
 
-	if (is_delete) {
-		if (!event) {
-			pr_info("Delete command needs an event name.\n");
-			return -EINVAL;
-		}
-		mutex_lock(&probe_lock);
-		tp = find_trace_probe(event, group);
-		if (!tp) {
-			mutex_unlock(&probe_lock);
-			pr_info("Event %s/%s doesn't exist.\n", group, event);
-			return -ENOENT;
-		}
-		/* delete an event */
-		ret = unregister_trace_probe(tp);
-		if (ret == 0)
-			free_trace_probe(tp);
-		mutex_unlock(&probe_lock);
-		return ret;
-	}
+	if (is_delete)
+		return delete_trace_probe(event, group);
 
 	if (argc < 2) {
 		pr_info("Probe point is not specified.\n");

--
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