Skip to content

Commit af9b3fa

Browse files
committed
Merge tag 'trace-probes-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull trace probes updates from Steven Rostedt: - New "symstr" type for dynamic events that writes the name of the function+offset into the ring buffer and not just the address - Prevent kernel symbol processing on addresses in user space probes (uprobes). - And minor fixes and clean ups * tag 'trace-probes-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing/probes: Reject symbol/symstr type for uprobe tracing/probes: Add symstr type for dynamic events kprobes: kretprobe events missing on 2-core KVM guest kprobes: Fix check for probe enabled in kill_kprobe() test_kprobes: Fix implicit declaration error of test_kprobes tracing: Fix race where eprobes can be called before the event
2 parents 7a5189c + d4505aa commit af9b3fa

File tree

9 files changed

+124
-52
lines changed

9 files changed

+124
-52
lines changed

Documentation/trace/kprobes.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ For example, if the function is non-recursive and is called with a
131131
spinlock held, maxactive = 1 should be enough. If the function is
132132
non-recursive and can never relinquish the CPU (e.g., via a semaphore
133133
or preemption), NR_CPUS should be enough. If maxactive <= 0, it is
134-
set to a default value. If CONFIG_PREEMPT is enabled, the default
135-
is max(10, 2*NR_CPUS). Otherwise, the default is NR_CPUS.
134+
set to a default value: max(10, 2*NR_CPUS).
136135

137136
It's not a disaster if you set maxactive too low; you'll just miss
138137
some probes. In the kretprobe struct, the nmissed field is set to

Documentation/trace/kprobetrace.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ Synopsis of kprobe_events
5858
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
5959
FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
6060
(u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
61-
(x8/x16/x32/x64), "string", "ustring" and bitfield
62-
are supported.
61+
(x8/x16/x32/x64), "string", "ustring", "symbol", "symstr"
62+
and bitfield are supported.
6363

6464
(\*1) only for the probe on function entry (offs == 0).
6565
(\*2) only for return probe.
@@ -96,6 +96,10 @@ offset, and container-size (usually 32). The syntax is::
9696

9797
Symbol type('symbol') is an alias of u32 or u64 type (depends on BITS_PER_LONG)
9898
which shows given pointer in "symbol+offset" style.
99+
On the other hand, symbol-string type ('symstr') converts the given address to
100+
"symbol+offset/symbolsize" style and stores it as a null-terminated string.
101+
With 'symstr' type, you can filter the event with wildcard pattern of the
102+
symbols, and you don't need to solve symbol name by yourself.
99103
For $comm, the default type is "string"; any other type is invalid.
100104

101105
.. _user_mem_access:

kernel/kprobes.c

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,13 +2213,9 @@ int register_kretprobe(struct kretprobe *rp)
22132213
rp->kp.post_handler = NULL;
22142214

22152215
/* Pre-allocate memory for max kretprobe instances */
2216-
if (rp->maxactive <= 0) {
2217-
#ifdef CONFIG_PREEMPTION
2216+
if (rp->maxactive <= 0)
22182217
rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus());
2219-
#else
2220-
rp->maxactive = num_possible_cpus();
2221-
#endif
2222-
}
2218+
22232219
#ifdef CONFIG_KRETPROBE_ON_RETHOOK
22242220
rp->rh = rethook_alloc((void *)rp, kretprobe_rethook_handler);
22252221
if (!rp->rh)
@@ -2364,6 +2360,14 @@ static void kill_kprobe(struct kprobe *p)
23642360

23652361
lockdep_assert_held(&kprobe_mutex);
23662362

2363+
/*
2364+
* The module is going away. We should disarm the kprobe which
2365+
* is using ftrace, because ftrace framework is still available at
2366+
* 'MODULE_STATE_GOING' notification.
2367+
*/
2368+
if (kprobe_ftrace(p) && !kprobe_disabled(p) && !kprobes_all_disarmed)
2369+
disarm_kprobe_ftrace(p);
2370+
23672371
p->flags |= KPROBE_FLAG_GONE;
23682372
if (kprobe_aggrprobe(p)) {
23692373
/*
@@ -2380,14 +2384,6 @@ static void kill_kprobe(struct kprobe *p)
23802384
* the original probed function (which will be freed soon) any more.
23812385
*/
23822386
arch_remove_kprobe(p);
2383-
2384-
/*
2385-
* The module is going away. We should disarm the kprobe which
2386-
* is using ftrace, because ftrace framework is still available at
2387-
* 'MODULE_STATE_GOING' notification.
2388-
*/
2389-
if (kprobe_ftrace(p) && !kprobe_disabled(p) && !kprobes_all_disarmed)
2390-
disarm_kprobe_ftrace(p);
23912387
}
23922388

23932389
/* Disable one kprobe */

kernel/trace/trace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5617,7 +5617,7 @@ static const char readme_msg[] =
56175617
"\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
56185618
"\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
56195619
"\t b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
5620-
"\t <type>\\[<array-size>\\]\n"
5620+
"\t symstr, <type>\\[<array-size>\\]\n"
56215621
#ifdef CONFIG_HIST_TRIGGERS
56225622
"\t field: <stype> <name>;\n"
56235623
"\t stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n"

kernel/trace/trace_probe.c

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\"";
7676
/* Fetch type information table */
7777
static const struct fetch_type probe_fetch_types[] = {
7878
/* Special types */
79-
__ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1,
79+
__ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1, 1,
8080
"__data_loc char[]"),
81-
__ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1,
81+
__ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1, 1,
82+
"__data_loc char[]"),
83+
__ASSIGN_FETCH_TYPE("symstr", string, string, sizeof(u32), 1, 1,
8284
"__data_loc char[]"),
8385
/* Basic types */
8486
ASSIGN_FETCH_TYPE(u8, u8, 0),
@@ -98,10 +100,15 @@ static const struct fetch_type probe_fetch_types[] = {
98100
ASSIGN_FETCH_TYPE_END
99101
};
100102

101-
static const struct fetch_type *find_fetch_type(const char *type)
103+
static const struct fetch_type *find_fetch_type(const char *type, unsigned long flags)
102104
{
103105
int i;
104106

107+
/* Reject the symbol/symstr for uprobes */
108+
if (type && (flags & TPARG_FL_USER) &&
109+
(!strcmp(type, "symbol") || !strcmp(type, "symstr")))
110+
return NULL;
111+
105112
if (!type)
106113
type = DEFAULT_FETCH_TYPE_STR;
107114

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

120127
switch (bs) {
121128
case 8:
122-
return find_fetch_type("u8");
129+
return find_fetch_type("u8", flags);
123130
case 16:
124-
return find_fetch_type("u16");
131+
return find_fetch_type("u16", flags);
125132
case 32:
126-
return find_fetch_type("u32");
133+
return find_fetch_type("u32", flags);
127134
case 64:
128-
return find_fetch_type("u64");
135+
return find_fetch_type("u64", flags);
129136
default:
130137
goto fail;
131138
}
@@ -478,7 +485,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
478485
DEREF_OPEN_BRACE);
479486
return -EINVAL;
480487
} else {
481-
const struct fetch_type *t2 = find_fetch_type(NULL);
488+
const struct fetch_type *t2 = find_fetch_type(NULL, flags);
482489

483490
*tmp = '\0';
484491
ret = parse_probe_arg(arg, t2, &code, end, flags, offs);
@@ -630,9 +637,9 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
630637
/* The type of $comm must be "string", and not an array. */
631638
if (parg->count || (t && strcmp(t, "string")))
632639
goto out;
633-
parg->type = find_fetch_type("string");
640+
parg->type = find_fetch_type("string", flags);
634641
} else
635-
parg->type = find_fetch_type(t);
642+
parg->type = find_fetch_type(t, flags);
636643
if (!parg->type) {
637644
trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
638645
goto out;
@@ -662,23 +669,35 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
662669

663670
ret = -EINVAL;
664671
/* Store operation */
665-
if (!strcmp(parg->type->name, "string") ||
666-
!strcmp(parg->type->name, "ustring")) {
667-
if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF &&
668-
code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM &&
669-
code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) {
670-
trace_probe_log_err(offset + (t ? (t - arg) : 0),
671-
BAD_STRING);
672-
goto fail;
672+
if (parg->type->is_string) {
673+
if (!strcmp(parg->type->name, "symstr")) {
674+
if (code->op != FETCH_OP_REG && code->op != FETCH_OP_STACK &&
675+
code->op != FETCH_OP_RETVAL && code->op != FETCH_OP_ARG &&
676+
code->op != FETCH_OP_DEREF && code->op != FETCH_OP_TP_ARG) {
677+
trace_probe_log_err(offset + (t ? (t - arg) : 0),
678+
BAD_SYMSTRING);
679+
goto fail;
680+
}
681+
} else {
682+
if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF &&
683+
code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM &&
684+
code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) {
685+
trace_probe_log_err(offset + (t ? (t - arg) : 0),
686+
BAD_STRING);
687+
goto fail;
688+
}
673689
}
674-
if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM ||
690+
if (!strcmp(parg->type->name, "symstr") ||
691+
(code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM ||
675692
code->op == FETCH_OP_DATA) || code->op == FETCH_OP_TP_ARG ||
676693
parg->count) {
677694
/*
678695
* IMM, DATA and COMM is pointing actual address, those
679696
* must be kept, and if parg->count != 0, this is an
680697
* array of string pointers instead of string address
681698
* itself.
699+
* For the symstr, it doesn't need to dereference, thus
700+
* it just get the value.
682701
*/
683702
code++;
684703
if (code->op != FETCH_OP_NOP) {
@@ -690,6 +709,8 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
690709
if (!strcmp(parg->type->name, "ustring") ||
691710
code->op == FETCH_OP_UDEREF)
692711
code->op = FETCH_OP_ST_USTRING;
712+
else if (!strcmp(parg->type->name, "symstr"))
713+
code->op = FETCH_OP_ST_SYMSTR;
693714
else
694715
code->op = FETCH_OP_ST_STRING;
695716
code->size = parg->type->size;
@@ -919,17 +940,15 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
919940
for (i = 0; i < tp->nr_args; i++) {
920941
parg = tp->args + i;
921942
if (parg->count) {
922-
if ((strcmp(parg->type->name, "string") == 0) ||
923-
(strcmp(parg->type->name, "ustring") == 0))
943+
if (parg->type->is_string)
924944
fmt = ", __get_str(%s[%d])";
925945
else
926946
fmt = ", REC->%s[%d]";
927947
for (j = 0; j < parg->count; j++)
928948
pos += snprintf(buf + pos, LEN_OR_ZERO,
929949
fmt, parg->name, j);
930950
} else {
931-
if ((strcmp(parg->type->name, "string") == 0) ||
932-
(strcmp(parg->type->name, "ustring") == 0))
951+
if (parg->type->is_string)
933952
fmt = ", __get_str(%s)";
934953
else
935954
fmt = ", REC->%s";

kernel/trace/trace_probe.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ enum fetch_op {
9898
FETCH_OP_ST_UMEM, /* Mem: .offset, .size */
9999
FETCH_OP_ST_STRING, /* String: .offset, .size */
100100
FETCH_OP_ST_USTRING, /* User String: .offset, .size */
101+
FETCH_OP_ST_SYMSTR, /* Kernel Symbol String: .offset, .size */
101102
// Stage 4 (modify) op
102103
FETCH_OP_MOD_BF, /* Bitfield: .basesize, .lshift, .rshift */
103104
// Stage 5 (loop) op
@@ -133,7 +134,8 @@ struct fetch_insn {
133134
struct fetch_type {
134135
const char *name; /* Name of type */
135136
size_t size; /* Byte size of type */
136-
int is_signed; /* Signed flag */
137+
bool is_signed; /* Signed flag */
138+
bool is_string; /* String flag */
137139
print_type_func_t print; /* Print functions */
138140
const char *fmt; /* Format string */
139141
const char *fmttype; /* Name in format file */
@@ -177,16 +179,19 @@ DECLARE_BASIC_PRINT_TYPE_FUNC(symbol);
177179
#define _ADDR_FETCH_TYPE(t) __ADDR_FETCH_TYPE(t)
178180
#define ADDR_FETCH_TYPE _ADDR_FETCH_TYPE(BITS_PER_LONG)
179181

180-
#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \
181-
{.name = _name, \
182+
#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, str, _fmttype) \
183+
{.name = _name, \
182184
.size = _size, \
183-
.is_signed = sign, \
185+
.is_signed = (bool)sign, \
186+
.is_string = (bool)str, \
184187
.print = PRINT_TYPE_FUNC_NAME(ptype), \
185188
.fmt = PRINT_TYPE_FMT_NAME(ptype), \
186189
.fmttype = _fmttype, \
187190
}
191+
192+
/* Non string types can use these macros */
188193
#define _ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \
189-
__ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, #_fmttype)
194+
__ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, 0, #_fmttype)
190195
#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \
191196
_ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, ptype)
192197

@@ -353,7 +358,8 @@ int trace_probe_create(const char *raw_command, int (*createfn)(int, const char
353358
#define TPARG_FL_KERNEL BIT(1)
354359
#define TPARG_FL_FENTRY BIT(2)
355360
#define TPARG_FL_TPOINT BIT(3)
356-
#define TPARG_FL_MASK GENMASK(3, 0)
361+
#define TPARG_FL_USER BIT(4)
362+
#define TPARG_FL_MASK GENMASK(4, 0)
357363

358364
extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i,
359365
const char *argv, unsigned int flags);
@@ -431,6 +437,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
431437
C(ARRAY_TOO_BIG, "Array number is too big"), \
432438
C(BAD_TYPE, "Unknown type is specified"), \
433439
C(BAD_STRING, "String accepts only memory argument"), \
440+
C(BAD_SYMSTRING, "Symbol String doesn't accept data/userdata"), \
434441
C(BAD_BITFIELD, "Invalid bitfield"), \
435442
C(ARG_NAME_TOO_LONG, "Argument name is too long"), \
436443
C(NO_ARG_NAME, "Argument name is not specified"), \

kernel/trace/trace_probe_tmpl.h

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,37 @@ probe_mem_read(void *dest, void *src, size_t size);
6767
static nokprobe_inline int
6868
probe_mem_read_user(void *dest, void *src, size_t size);
6969

70+
static nokprobe_inline int
71+
fetch_store_symstrlen(unsigned long addr)
72+
{
73+
char namebuf[KSYM_SYMBOL_LEN];
74+
int ret;
75+
76+
ret = sprint_symbol(namebuf, addr);
77+
if (ret < 0)
78+
return 0;
79+
80+
return ret + 1;
81+
}
82+
83+
/*
84+
* Fetch a null-terminated symbol string + offset. Caller MUST set *(u32 *)buf
85+
* with max length and relative data location.
86+
*/
87+
static nokprobe_inline int
88+
fetch_store_symstring(unsigned long addr, void *dest, void *base)
89+
{
90+
int maxlen = get_loc_len(*(u32 *)dest);
91+
void *__dest;
92+
93+
if (unlikely(!maxlen))
94+
return -ENOMEM;
95+
96+
__dest = get_loc_data(dest, base);
97+
98+
return sprint_symbol(__dest, addr);
99+
}
100+
70101
/* From the 2nd stage, routine is same */
71102
static nokprobe_inline int
72103
process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
@@ -99,16 +130,22 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
99130
stage3:
100131
/* 3rd stage: store value to buffer */
101132
if (unlikely(!dest)) {
102-
if (code->op == FETCH_OP_ST_STRING) {
133+
switch (code->op) {
134+
case FETCH_OP_ST_STRING:
103135
ret = fetch_store_strlen(val + code->offset);
104136
code++;
105137
goto array;
106-
} else if (code->op == FETCH_OP_ST_USTRING) {
138+
case FETCH_OP_ST_USTRING:
107139
ret += fetch_store_strlen_user(val + code->offset);
108140
code++;
109141
goto array;
110-
} else
142+
case FETCH_OP_ST_SYMSTR:
143+
ret += fetch_store_symstrlen(val + code->offset);
144+
code++;
145+
goto array;
146+
default:
111147
return -EILSEQ;
148+
}
112149
}
113150

114151
switch (code->op) {
@@ -129,6 +166,10 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
129166
loc = *(u32 *)dest;
130167
ret = fetch_store_string_user(val + code->offset, dest, base);
131168
break;
169+
case FETCH_OP_ST_SYMSTR:
170+
loc = *(u32 *)dest;
171+
ret = fetch_store_symstring(val + code->offset, dest, base);
172+
break;
132173
default:
133174
return -EILSEQ;
134175
}

kernel/trace/trace_uprobe.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,8 @@ static int __trace_uprobe_create(int argc, const char **argv)
691691
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
692692
trace_probe_log_set_index(i + 2);
693693
ret = traceprobe_parse_probe_arg(&tu->tp, i, argv[i],
694-
is_return ? TPARG_FL_RETURN : 0);
694+
(is_return ? TPARG_FL_RETURN : 0) |
695+
TPARG_FL_USER);
695696
if (ret)
696697
goto error;
697698
}

tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,9 @@ check_error 'p /bin/sh:10^%hoge' # BAD_ADDR_SUFFIX
2323
check_error 'p /bin/sh:10(10)^%return' # BAD_REFCNT_SUFFIX
2424
fi
2525

26+
# symstr is not supported by uprobe
27+
if grep -q ".*symstr.*" README; then
28+
check_error 'p /bin/sh:10 $stack0:^symstr' # BAD_TYPE
29+
fi
30+
2631
exit 0

0 commit comments

Comments
 (0)