Commit d4505aa6 authored by Masami Hiramatsu (Google)'s avatar Masami Hiramatsu (Google)
Browse files

tracing/probes: Reject symbol/symstr type for uprobe

Since uprobe's argument must contain the user-space data, that
should not be converted to kernel symbols. Reject if user
specifies these types on uprobe events. e.g.

 /sys/kernel/debug/tracing # echo 'p /bin/sh:10 %ax:symbol' >> uprobe_events
 sh: write error: Invalid argument
 /sys/kernel/debug/tracing # echo 'p /bin/sh:10 %ax:symstr' >> uprobe_events
 sh: write error: Invalid argument
 /sys/kernel/debug/tracing # cat error_log
 [ 1783.134883] trace_uprobe: error: Unknown type is specified
   Command: p /bin/sh:10 %ax:symbol
                             ^
 [ 1792.201120] trace_uprobe: error: Unknown type is specified
   Command: p /bin/sh:10 %ax:symstr
                             ^
Link: https://lore.kernel.org/all/166679931679.1528100.15540755370726009882.stgit@devnote3/



Signed-off-by: default avatarMasami Hiramatsu (Google) <mhiramat@kernel.org>
parent b26a124c
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -100,10 +100,15 @@ static const struct fetch_type probe_fetch_types[] = {
	ASSIGN_FETCH_TYPE_END
};

static const struct fetch_type *find_fetch_type(const char *type)
static const struct fetch_type *find_fetch_type(const char *type, unsigned long flags)
{
	int i;

	/* Reject the symbol/symstr for uprobes */
	if (type && (flags & TPARG_FL_USER) &&
	    (!strcmp(type, "symbol") || !strcmp(type, "symstr")))
		return NULL;

	if (!type)
		type = DEFAULT_FETCH_TYPE_STR;

@@ -121,13 +126,13 @@ static const struct fetch_type *find_fetch_type(const char *type)

		switch (bs) {
		case 8:
			return find_fetch_type("u8");
			return find_fetch_type("u8", flags);
		case 16:
			return find_fetch_type("u16");
			return find_fetch_type("u16", flags);
		case 32:
			return find_fetch_type("u32");
			return find_fetch_type("u32", flags);
		case 64:
			return find_fetch_type("u64");
			return find_fetch_type("u64", flags);
		default:
			goto fail;
		}
@@ -480,7 +485,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
					    DEREF_OPEN_BRACE);
			return -EINVAL;
		} else {
			const struct fetch_type *t2 = find_fetch_type(NULL);
			const struct fetch_type *t2 = find_fetch_type(NULL, flags);

			*tmp = '\0';
			ret = parse_probe_arg(arg, t2, &code, end, flags, offs);
@@ -632,9 +637,9 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
		/* The type of $comm must be "string", and not an array. */
		if (parg->count || (t && strcmp(t, "string")))
			goto out;
		parg->type = find_fetch_type("string");
		parg->type = find_fetch_type("string", flags);
	} else
		parg->type = find_fetch_type(t);
		parg->type = find_fetch_type(t, flags);
	if (!parg->type) {
		trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
		goto out;
+2 −1
Original line number Diff line number Diff line
@@ -358,7 +358,8 @@ int trace_probe_create(const char *raw_command, int (*createfn)(int, const char
#define TPARG_FL_KERNEL BIT(1)
#define TPARG_FL_FENTRY BIT(2)
#define TPARG_FL_TPOINT BIT(3)
#define TPARG_FL_MASK	GENMASK(3, 0)
#define TPARG_FL_USER   BIT(4)
#define TPARG_FL_MASK	GENMASK(4, 0)

extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i,
				const char *argv, unsigned int flags);
+2 −1
Original line number Diff line number Diff line
@@ -691,7 +691,8 @@ static int __trace_uprobe_create(int argc, const char **argv)
	for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
		trace_probe_log_set_index(i + 2);
		ret = traceprobe_parse_probe_arg(&tu->tp, i, argv[i],
					is_return ? TPARG_FL_RETURN : 0);
					(is_return ? TPARG_FL_RETURN : 0) |
					TPARG_FL_USER);
		if (ret)
			goto error;
	}
+5 −0
Original line number Diff line number Diff line
@@ -23,4 +23,9 @@ check_error 'p /bin/sh:10^%hoge' # BAD_ADDR_SUFFIX
check_error 'p /bin/sh:10(10)^%return'	# BAD_REFCNT_SUFFIX
fi

# symstr is not supported by uprobe
if grep -q ".*symstr.*" README; then
check_error 'p /bin/sh:10 $stack0:^symstr'	# BAD_TYPE
fi

exit 0