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: <c4218c9a114c287fec9f0984f180f72c7f3c954b.1464916142.git.osandov@fb.com>
Date:	Thu,  2 Jun 2016 18:11:03 -0700
From:	Omar Sandoval <osandov@...ndov.com>
To:	Steven Rostedt <rostedt@...dmis.org>,
	Ingo Molnar <mingo@...hat.com>,
	Masami Hiramatsu <mhiramat@...nel.org>,
	Namhyung Kim <namhyung@...il.com>
Cc:	linux-kernel@...r.kernel.org, kernel-team@...com,
	Omar Sandoval <osandov@...com>
Subject: [PATCH v2 3/3] tracing: make "string" the default type for [ku]probe event $comm

From: Omar Sandoval <osandov@...com>

You'd only ever want $comm as a string, but the default is still u64.
Push the type parsing later so we can decide based on the actual
fetcharg and make "string" the default for $comm.

Signed-off-by: Omar Sandoval <osandov@...com>
---
 Documentation/trace/kprobetrace.txt  |   6 +--
 Documentation/trace/uprobetracer.txt |   6 +--
 kernel/trace/trace_probe.c           | 102 +++++++++++++++++++++++------------
 3 files changed, 75 insertions(+), 39 deletions(-)

diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index 0bf746656d06..da3b437d4e5e 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -40,7 +40,7 @@ Synopsis of kprobe_events
   $stackN	: Fetch Nth entry of stack (N >= 0)
   $stack	: Fetch stack address.
   $retval	: Fetch return value.(*)
-  $comm		: Fetch current task comm.(***)
+  $comm		: Fetch current task comm.
   +|-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
@@ -49,7 +49,6 @@ Synopsis of kprobe_events
 
   (*) only for return probe.
   (**) this is useful for fetching a field of data structures.
-  (***) you probably want this as a string, i.e., $comm:string
 
 Types
 -----
@@ -65,7 +64,8 @@ offset, and container-size (usually 32). The syntax is;
 
  b<bit-width>@<bit-offset>/<container-size>
 
-For $comm, the type must be either "string" or "string_size".
+For $comm, the type must be either "string" or "string_size". The default is
+"string".
 
 
 Per-Probe Event Filtering
diff --git a/Documentation/trace/uprobetracer.txt b/Documentation/trace/uprobetracer.txt
index 34754da46860..5daa61cf431a 100644
--- a/Documentation/trace/uprobetracer.txt
+++ b/Documentation/trace/uprobetracer.txt
@@ -36,7 +36,7 @@ Synopsis of uprobe_tracer
    $stackN	: Fetch Nth entry of stack (N >= 0)
    $stack	: Fetch stack address.
    $retval	: Fetch return value.(*)
-   $comm	: Fetch current task comm.(***)
+   $comm	: Fetch current task comm.
    +|-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
@@ -45,7 +45,6 @@ Synopsis of uprobe_tracer
 
   (*) only for return probe.
   (**) this is useful for fetching a field of data structures.
-  (***) you probably want this as a string, i.e., $comm:string
 
 Types
 -----
@@ -60,7 +59,8 @@ offset, and container-size (usually 32). The syntax is;
 
  b<bit-width>@<bit-offset>/<container-size>
 
-For $comm, the type must be either "string" or "string_size".
+For $comm, the type must be either "string" or "string_size". The default is
+"string".
 
 
 Event Profiling
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 3900b6e4a05d..6b0a553308f9 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -296,6 +296,26 @@ static void fetch_user_stack_address(struct pt_regs *regs, void *dummy, void *de
 }
 NOKPROBE_SYMBOL(fetch_user_stack_address);
 
+static int parse_fetch_type(const char *t, ssize_t *size,
+			    const struct fetch_type **tp,
+			    const struct fetch_type *ftbl,
+			    const char *default_t)
+{
+	if (!t)
+		t = default_t;
+
+	*tp = find_fetch_type(t, ftbl);
+	if (!*tp) {
+		pr_info("Unsupported type: %s\n", t);
+		return -EINVAL;
+	}
+
+	if (size)
+		*size += (*tp)->size;
+
+	return 0;
+}
+
 static fetch_func_t get_fetch_size_function(const struct fetch_type *type,
 					    fetch_func_t orig_fn,
 					    const struct fetch_type *ftbl)
@@ -339,21 +359,28 @@ int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset)
 
 #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
 
-static int parse_probe_vars(char *arg, const struct fetch_type *t,
-			    struct fetch_param *f, bool is_return,
-			    bool is_kprobe)
+static int parse_probe_vars(char *arg, const char *t, ssize_t *size,
+			    const struct fetch_type **tp, struct fetch_param *f,
+			    bool is_return, bool is_kprobe,
+			    const struct fetch_type *ftbl)
 {
 	int ret = 0;
 	unsigned long param;
 
 	if (strcmp(arg, "retval") == 0) {
+		ret = parse_fetch_type(t, size, tp, ftbl, NULL);
+		if (ret)
+			return ret;
 		if (is_return)
-			f->fn = t->fetch[FETCH_MTD_retval];
+			f->fn = (*tp)->fetch[FETCH_MTD_retval];
 		else
 			ret = -EINVAL;
 	} else if (strncmp(arg, "stack", 5) == 0) {
+		ret = parse_fetch_type(t, size, tp, ftbl, NULL);
+		if (ret)
+			return ret;
 		if (arg[5] == '\0') {
-			if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR))
+			if (strcmp((*tp)->name, DEFAULT_FETCH_TYPE_STR))
 				return -EINVAL;
 
 			if (is_kprobe)
@@ -365,16 +392,19 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
 			if (ret || (is_kprobe && param > PARAM_MAX_STACK))
 				ret = -EINVAL;
 			else {
-				f->fn = t->fetch[FETCH_MTD_stack];
+				f->fn = (*tp)->fetch[FETCH_MTD_stack];
 				f->data = (void *)param;
 			}
 		} else
 			ret = -EINVAL;
 	} else if (strcmp(arg, "comm") == 0) {
-		if (strcmp(t->name, "string") != 0 &&
-		    strcmp(t->name, "string_size") != 0)
+		ret = parse_fetch_type(t, size, tp, ftbl, "string");
+		if (ret)
+			return ret;
+		if (strcmp((*tp)->name, "string") != 0 &&
+		    strcmp((*tp)->name, "string_size") != 0)
 			return -EINVAL;
-		f->fn = t->fetch[FETCH_MTD_comm];
+		f->fn = (*tp)->fetch[FETCH_MTD_comm];
 	} else
 		ret = -EINVAL;
 
@@ -382,9 +412,10 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
 }
 
 /* Recursive argument parser */
-static int parse_probe_arg(char *arg, const struct fetch_type *t,
-		     struct fetch_param *f, bool is_return, bool is_kprobe,
-		     const struct fetch_type *ftbl)
+static int parse_probe_arg(char *arg, const char *t, ssize_t *size,
+			   const struct fetch_type **tp,
+			   struct fetch_param *f, bool is_return,
+			   bool is_kprobe, const struct fetch_type *ftbl)
 {
 	unsigned long param;
 	long offset;
@@ -393,25 +424,32 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
 
 	switch (arg[0]) {
 	case '$':
-		ret = parse_probe_vars(arg + 1, t, f, is_return, is_kprobe);
+		ret = parse_probe_vars(arg + 1, t, size, tp, f, is_return,
+				       is_kprobe, ftbl);
 		break;
 
 	case '%':	/* named register */
+		ret = parse_fetch_type(t, size, tp, ftbl, NULL);
+		if (ret)
+			break;
 		ret = regs_query_register_offset(arg + 1);
 		if (ret >= 0) {
-			f->fn = t->fetch[FETCH_MTD_reg];
+			f->fn = (*tp)->fetch[FETCH_MTD_reg];
 			f->data = (void *)(unsigned long)ret;
 			ret = 0;
 		}
 		break;
 
 	case '@':	/* memory, file-offset or symbol */
+		ret = parse_fetch_type(t, size, tp, ftbl, NULL);
+		if (ret)
+			break;
 		if (isdigit(arg[1])) {
 			ret = kstrtoul(arg + 1, 0, &param);
 			if (ret)
 				break;
 
-			f->fn = t->fetch[FETCH_MTD_memory];
+			f->fn = (*tp)->fetch[FETCH_MTD_memory];
 			f->data = (void *)param;
 		} else if (arg[1] == '+') {
 			/* kprobes don't support file offsets */
@@ -422,7 +460,7 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
 			if (ret)
 				break;
 
-			f->fn = t->fetch[FETCH_MTD_file_offset];
+			f->fn = (*tp)->fetch[FETCH_MTD_file_offset];
 			f->data = (void *)offset;
 		} else {
 			/* uprobes don't support symbols */
@@ -435,13 +473,16 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
 
 			f->data = alloc_symbol_cache(arg + 1, offset);
 			if (f->data)
-				f->fn = t->fetch[FETCH_MTD_symbol];
+				f->fn = (*tp)->fetch[FETCH_MTD_symbol];
 		}
 		break;
 
 	case '+':	/* deref memory */
 		arg++;	/* Skip '+', because kstrtol() rejects it. */
 	case '-':
+		ret = parse_fetch_type(t, size, tp, ftbl, NULL);
+		if (ret)
+			break;
 		tmp = strchr(arg, '(');
 		if (!tmp)
 			break;
@@ -459,7 +500,6 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
 			struct deref_fetch_param	*dprm;
 			const struct fetch_type		*t2;
 
-			t2 = find_fetch_type(NULL, ftbl);
 			*tmp = '\0';
 			dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL);
 
@@ -467,22 +507,24 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
 				return -ENOMEM;
 
 			dprm->offset = offset;
-			dprm->fetch = t->fetch[FETCH_MTD_memory];
-			dprm->fetch_size = get_fetch_size_function(t,
-							dprm->fetch, ftbl);
-			ret = parse_probe_arg(arg, t2, &dprm->orig, is_return,
-							is_kprobe, ftbl);
+			dprm->fetch = (*tp)->fetch[FETCH_MTD_memory];
+			dprm->fetch_size = get_fetch_size_function((*tp),
+								   dprm->fetch,
+								   ftbl);
+			ret = parse_probe_arg(arg, NULL, NULL, &t2, &dprm->orig,
+					      is_return, is_kprobe, ftbl);
 			if (ret)
 				kfree(dprm);
 			else {
-				f->fn = t->fetch[FETCH_MTD_deref];
+				f->fn = (*tp)->fetch[FETCH_MTD_deref];
 				f->data = (void *)dprm;
 			}
 		}
 		break;
 	}
 	if (!ret && !f->fn) {	/* Parsed, but do not find fetch method */
-		pr_info("%s type has no corresponding fetch method.\n", t->name);
+		pr_info("%s type has no corresponding fetch method.\n",
+			(*tp)->name);
 		ret = -EINVAL;
 	}
 
@@ -549,15 +591,9 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
 		arg[t - parg->comm] = '\0';
 		t++;
 	}
-	parg->type = find_fetch_type(t, ftbl);
-	if (!parg->type) {
-		pr_info("Unsupported type: %s\n", t);
-		return -EINVAL;
-	}
 	parg->offset = *size;
-	*size += parg->type->size;
-	ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return,
-			      is_kprobe, ftbl);
+	ret = parse_probe_arg(arg, t, size, &parg->type, &parg->fetch,
+			      is_return, is_kprobe, ftbl);
 
 	if (ret >= 0 && t != NULL)
 		ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
-- 
2.8.3

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ