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: Masami Hiramatsu (Google) <mhiramat@kernel.org>
This commit is contained in:
Родитель
b26a124cbf
Коммит
d4505aa6af
|
@ -100,10 +100,15 @@ static const struct fetch_type probe_fetch_types[] = {
|
||||||
ASSIGN_FETCH_TYPE_END
|
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;
|
int i;
|
||||||
|
|
||||||
|
/* Reject the symbol/symstr for uprobes */
|
||||||
|
if (type && (flags & TPARG_FL_USER) &&
|
||||||
|
(!strcmp(type, "symbol") || !strcmp(type, "symstr")))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
type = DEFAULT_FETCH_TYPE_STR;
|
type = DEFAULT_FETCH_TYPE_STR;
|
||||||
|
|
||||||
|
@ -121,13 +126,13 @@ static const struct fetch_type *find_fetch_type(const char *type)
|
||||||
|
|
||||||
switch (bs) {
|
switch (bs) {
|
||||||
case 8:
|
case 8:
|
||||||
return find_fetch_type("u8");
|
return find_fetch_type("u8", flags);
|
||||||
case 16:
|
case 16:
|
||||||
return find_fetch_type("u16");
|
return find_fetch_type("u16", flags);
|
||||||
case 32:
|
case 32:
|
||||||
return find_fetch_type("u32");
|
return find_fetch_type("u32", flags);
|
||||||
case 64:
|
case 64:
|
||||||
return find_fetch_type("u64");
|
return find_fetch_type("u64", flags);
|
||||||
default:
|
default:
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -480,7 +485,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
|
||||||
DEREF_OPEN_BRACE);
|
DEREF_OPEN_BRACE);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else {
|
} else {
|
||||||
const struct fetch_type *t2 = find_fetch_type(NULL);
|
const struct fetch_type *t2 = find_fetch_type(NULL, flags);
|
||||||
|
|
||||||
*tmp = '\0';
|
*tmp = '\0';
|
||||||
ret = parse_probe_arg(arg, t2, &code, end, flags, offs);
|
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. */
|
/* The type of $comm must be "string", and not an array. */
|
||||||
if (parg->count || (t && strcmp(t, "string")))
|
if (parg->count || (t && strcmp(t, "string")))
|
||||||
goto out;
|
goto out;
|
||||||
parg->type = find_fetch_type("string");
|
parg->type = find_fetch_type("string", flags);
|
||||||
} else
|
} else
|
||||||
parg->type = find_fetch_type(t);
|
parg->type = find_fetch_type(t, flags);
|
||||||
if (!parg->type) {
|
if (!parg->type) {
|
||||||
trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
|
trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -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_KERNEL BIT(1)
|
||||||
#define TPARG_FL_FENTRY BIT(2)
|
#define TPARG_FL_FENTRY BIT(2)
|
||||||
#define TPARG_FL_TPOINT BIT(3)
|
#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,
|
extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i,
|
||||||
const char *argv, unsigned int flags);
|
const char *argv, unsigned int flags);
|
||||||
|
|
|
@ -691,7 +691,8 @@ static int __trace_uprobe_create(int argc, const char **argv)
|
||||||
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
|
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
|
||||||
trace_probe_log_set_index(i + 2);
|
trace_probe_log_set_index(i + 2);
|
||||||
ret = traceprobe_parse_probe_arg(&tu->tp, i, argv[i],
|
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)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
check_error 'p /bin/sh:10(10)^%return' # BAD_REFCNT_SUFFIX
|
||||||
fi
|
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
|
exit 0
|
||||||
|
|
Загрузка…
Ссылка в новой задаче