Skip to content

Commit 5159938

Browse files
committed
Merge tag 'probes-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull probes updates from Masami Hiramatsu: - uprobes: make trace_uprobe->nhit counter a per-CPU one This makes uprobe event's hit counter per-CPU for improving scalability on multi-core environment - kprobes: Remove obsoleted declaration for init_test_probes Remove unused init_test_probes() from header - Raw tracepoint probe supports raw tracepoint events on modules: - add a function for iterating over all tracepoints in all modules - add a function for iterating over tracepoints in a module - support raw tracepoint events on modules - support raw tracepoints on future loaded modules - add a test for tracepoint events on modules" * tag 'probes-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: sefltests/tracing: Add a test for tracepoint events on modules tracing/fprobe: Support raw tracepoints on future loaded modules tracing/fprobe: Support raw tracepoint events on modules tracepoint: Support iterating tracepoints in a loading module tracepoint: Support iterating over tracepoints on modules kprobes: Remove obsoleted declaration for init_test_probes uprobes: turn trace_uprobe's nhit counter to be per-CPU one
2 parents 0181f8c + 4e78dd6 commit 5159938

File tree

8 files changed

+275
-62
lines changed

8 files changed

+275
-62
lines changed

include/linux/kprobes.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,6 @@ extern unsigned long __stop_kprobe_blacklist[];
269269

270270
extern struct kretprobe_blackpoint kretprobe_blacklist[];
271271

272-
#ifdef CONFIG_KPROBES_SANITY_TEST
273-
extern int init_test_probes(void);
274-
#else /* !CONFIG_KPROBES_SANITY_TEST */
275-
static inline int init_test_probes(void)
276-
{
277-
return 0;
278-
}
279-
#endif /* CONFIG_KPROBES_SANITY_TEST */
280-
281272
extern int arch_prepare_kprobe(struct kprobe *p);
282273
extern void arch_arm_kprobe(struct kprobe *p);
283274
extern void arch_disarm_kprobe(struct kprobe *p);

include/linux/tracepoint.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ struct tp_module {
6464
bool trace_module_has_bad_taint(struct module *mod);
6565
extern int register_tracepoint_module_notifier(struct notifier_block *nb);
6666
extern int unregister_tracepoint_module_notifier(struct notifier_block *nb);
67+
void for_each_module_tracepoint(void (*fct)(struct tracepoint *,
68+
struct module *, void *),
69+
void *priv);
70+
void for_each_tracepoint_in_module(struct module *,
71+
void (*fct)(struct tracepoint *,
72+
struct module *, void *),
73+
void *priv);
6774
#else
6875
static inline bool trace_module_has_bad_taint(struct module *mod)
6976
{
@@ -79,6 +86,19 @@ int unregister_tracepoint_module_notifier(struct notifier_block *nb)
7986
{
8087
return 0;
8188
}
89+
static inline
90+
void for_each_module_tracepoint(void (*fct)(struct tracepoint *,
91+
struct module *, void *),
92+
void *priv)
93+
{
94+
}
95+
static inline
96+
void for_each_tracepoint_in_module(struct module *mod,
97+
void (*fct)(struct tracepoint *,
98+
struct module *, void *),
99+
void *priv)
100+
{
101+
}
82102
#endif /* CONFIG_MODULES */
83103

84104
/*

kernel/trace/trace_fprobe.c

Lines changed: 130 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define FPROBE_EVENT_SYSTEM "fprobes"
2222
#define TRACEPOINT_EVENT_SYSTEM "tracepoints"
2323
#define RETHOOK_MAXACTIVE_MAX 4096
24+
#define TRACEPOINT_STUB ERR_PTR(-ENOENT)
2425

2526
static int trace_fprobe_create(const char *raw_command);
2627
static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev);
@@ -385,6 +386,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
385386
const char *event,
386387
const char *symbol,
387388
struct tracepoint *tpoint,
389+
struct module *mod,
388390
int maxactive,
389391
int nargs, bool is_return)
390392
{
@@ -405,6 +407,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
405407
tf->fp.entry_handler = fentry_dispatcher;
406408

407409
tf->tpoint = tpoint;
410+
tf->mod = mod;
408411
tf->fp.nr_maxactive = maxactive;
409412

410413
ret = trace_probe_init(&tf->tp, event, group, false, nargs);
@@ -672,6 +675,24 @@ static int unregister_fprobe_event(struct trace_fprobe *tf)
672675
return trace_probe_unregister_event_call(&tf->tp);
673676
}
674677

678+
static int __regsiter_tracepoint_fprobe(struct trace_fprobe *tf)
679+
{
680+
struct tracepoint *tpoint = tf->tpoint;
681+
unsigned long ip = (unsigned long)tpoint->probestub;
682+
int ret;
683+
684+
/*
685+
* Here, we do 2 steps to enable fprobe on a tracepoint.
686+
* At first, put __probestub_##TP function on the tracepoint
687+
* and put a fprobe on the stub function.
688+
*/
689+
ret = tracepoint_probe_register_prio_may_exist(tpoint,
690+
tpoint->probestub, NULL, 0);
691+
if (ret < 0)
692+
return ret;
693+
return register_fprobe_ips(&tf->fp, &ip, 1);
694+
}
695+
675696
/* Internal register function - just handle fprobe and flags */
676697
static int __register_trace_fprobe(struct trace_fprobe *tf)
677698
{
@@ -698,18 +719,12 @@ static int __register_trace_fprobe(struct trace_fprobe *tf)
698719
tf->fp.flags |= FPROBE_FL_DISABLED;
699720

700721
if (trace_fprobe_is_tracepoint(tf)) {
701-
struct tracepoint *tpoint = tf->tpoint;
702-
unsigned long ip = (unsigned long)tpoint->probestub;
703-
/*
704-
* Here, we do 2 steps to enable fprobe on a tracepoint.
705-
* At first, put __probestub_##TP function on the tracepoint
706-
* and put a fprobe on the stub function.
707-
*/
708-
ret = tracepoint_probe_register_prio_may_exist(tpoint,
709-
tpoint->probestub, NULL, 0);
710-
if (ret < 0)
711-
return ret;
712-
return register_fprobe_ips(&tf->fp, &ip, 1);
722+
723+
/* This tracepoint is not loaded yet */
724+
if (tf->tpoint == TRACEPOINT_STUB)
725+
return 0;
726+
727+
return __regsiter_tracepoint_fprobe(tf);
713728
}
714729

715730
/* TODO: handle filter, nofilter or symbol list */
@@ -862,20 +877,106 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
862877
return ret;
863878
}
864879

880+
struct __find_tracepoint_cb_data {
881+
const char *tp_name;
882+
struct tracepoint *tpoint;
883+
struct module *mod;
884+
};
885+
886+
static void __find_tracepoint_module_cb(struct tracepoint *tp, struct module *mod, void *priv)
887+
{
888+
struct __find_tracepoint_cb_data *data = priv;
889+
890+
if (!data->tpoint && !strcmp(data->tp_name, tp->name)) {
891+
data->tpoint = tp;
892+
if (!data->mod) {
893+
data->mod = mod;
894+
if (!try_module_get(data->mod)) {
895+
data->tpoint = NULL;
896+
data->mod = NULL;
897+
}
898+
}
899+
}
900+
}
901+
902+
static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
903+
{
904+
struct __find_tracepoint_cb_data *data = priv;
905+
906+
if (!data->tpoint && !strcmp(data->tp_name, tp->name))
907+
data->tpoint = tp;
908+
}
909+
910+
/*
911+
* Find a tracepoint from kernel and module. If the tracepoint is in a module,
912+
* this increments the module refcount to prevent unloading until the
913+
* trace_fprobe is registered to the list. After registering the trace_fprobe
914+
* on the trace_fprobe list, the module refcount is decremented because
915+
* tracepoint_probe_module_cb will handle it.
916+
*/
917+
static struct tracepoint *find_tracepoint(const char *tp_name,
918+
struct module **tp_mod)
919+
{
920+
struct __find_tracepoint_cb_data data = {
921+
.tp_name = tp_name,
922+
.mod = NULL,
923+
};
924+
925+
for_each_kernel_tracepoint(__find_tracepoint_cb, &data);
926+
927+
if (!data.tpoint && IS_ENABLED(CONFIG_MODULES)) {
928+
for_each_module_tracepoint(__find_tracepoint_module_cb, &data);
929+
*tp_mod = data.mod;
930+
}
931+
932+
return data.tpoint;
933+
}
934+
865935
#ifdef CONFIG_MODULES
936+
static void reenable_trace_fprobe(struct trace_fprobe *tf)
937+
{
938+
struct trace_probe *tp = &tf->tp;
939+
940+
list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
941+
__enable_trace_fprobe(tf);
942+
}
943+
}
944+
945+
static struct tracepoint *find_tracepoint_in_module(struct module *mod,
946+
const char *tp_name)
947+
{
948+
struct __find_tracepoint_cb_data data = {
949+
.tp_name = tp_name,
950+
.mod = mod,
951+
};
952+
953+
for_each_tracepoint_in_module(mod, __find_tracepoint_module_cb, &data);
954+
return data.tpoint;
955+
}
956+
866957
static int __tracepoint_probe_module_cb(struct notifier_block *self,
867958
unsigned long val, void *data)
868959
{
869960
struct tp_module *tp_mod = data;
961+
struct tracepoint *tpoint;
870962
struct trace_fprobe *tf;
871963
struct dyn_event *pos;
872964

873-
if (val != MODULE_STATE_GOING)
965+
if (val != MODULE_STATE_GOING && val != MODULE_STATE_COMING)
874966
return NOTIFY_DONE;
875967

876968
mutex_lock(&event_mutex);
877969
for_each_trace_fprobe(tf, pos) {
878-
if (tp_mod->mod == tf->mod) {
970+
if (val == MODULE_STATE_COMING && tf->tpoint == TRACEPOINT_STUB) {
971+
tpoint = find_tracepoint_in_module(tp_mod->mod, tf->symbol);
972+
if (tpoint) {
973+
tf->tpoint = tpoint;
974+
tf->mod = tp_mod->mod;
975+
if (!WARN_ON_ONCE(__regsiter_tracepoint_fprobe(tf)) &&
976+
trace_probe_is_enabled(&tf->tp))
977+
reenable_trace_fprobe(tf);
978+
}
979+
} else if (val == MODULE_STATE_GOING && tp_mod->mod == tf->mod) {
879980
tracepoint_probe_unregister(tf->tpoint,
880981
tf->tpoint->probestub, NULL);
881982
tf->tpoint = NULL;
@@ -892,30 +993,6 @@ static struct notifier_block tracepoint_module_nb = {
892993
};
893994
#endif /* CONFIG_MODULES */
894995

895-
struct __find_tracepoint_cb_data {
896-
const char *tp_name;
897-
struct tracepoint *tpoint;
898-
};
899-
900-
static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
901-
{
902-
struct __find_tracepoint_cb_data *data = priv;
903-
904-
if (!data->tpoint && !strcmp(data->tp_name, tp->name))
905-
data->tpoint = tp;
906-
}
907-
908-
static struct tracepoint *find_tracepoint(const char *tp_name)
909-
{
910-
struct __find_tracepoint_cb_data data = {
911-
.tp_name = tp_name,
912-
};
913-
914-
for_each_kernel_tracepoint(__find_tracepoint_cb, &data);
915-
916-
return data.tpoint;
917-
}
918-
919996
static int parse_symbol_and_return(int argc, const char *argv[],
920997
char **symbol, bool *is_return,
921998
bool is_tracepoint)
@@ -996,6 +1073,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
9961073
char abuf[MAX_BTF_ARGS_LEN];
9971074
char *dbuf = NULL;
9981075
bool is_tracepoint = false;
1076+
struct module *tp_mod = NULL;
9991077
struct tracepoint *tpoint = NULL;
10001078
struct traceprobe_parse_context ctx = {
10011079
.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
@@ -1080,15 +1158,20 @@ static int __trace_fprobe_create(int argc, const char *argv[])
10801158

10811159
if (is_tracepoint) {
10821160
ctx.flags |= TPARG_FL_TPOINT;
1083-
tpoint = find_tracepoint(symbol);
1084-
if (!tpoint) {
1161+
tpoint = find_tracepoint(symbol, &tp_mod);
1162+
if (tpoint) {
1163+
ctx.funcname = kallsyms_lookup(
1164+
(unsigned long)tpoint->probestub,
1165+
NULL, NULL, NULL, sbuf);
1166+
} else if (IS_ENABLED(CONFIG_MODULES)) {
1167+
/* This *may* be loaded afterwards */
1168+
tpoint = TRACEPOINT_STUB;
1169+
ctx.funcname = symbol;
1170+
} else {
10851171
trace_probe_log_set_index(1);
10861172
trace_probe_log_err(0, NO_TRACEPOINT);
10871173
goto parse_error;
10881174
}
1089-
ctx.funcname = kallsyms_lookup(
1090-
(unsigned long)tpoint->probestub,
1091-
NULL, NULL, NULL, sbuf);
10921175
} else
10931176
ctx.funcname = symbol;
10941177

@@ -1110,19 +1193,15 @@ static int __trace_fprobe_create(int argc, const char *argv[])
11101193
goto out;
11111194

11121195
/* setup a probe */
1113-
tf = alloc_trace_fprobe(group, event, symbol, tpoint, maxactive,
1114-
argc, is_return);
1196+
tf = alloc_trace_fprobe(group, event, symbol, tpoint, tp_mod,
1197+
maxactive, argc, is_return);
11151198
if (IS_ERR(tf)) {
11161199
ret = PTR_ERR(tf);
11171200
/* This must return -ENOMEM, else there is a bug */
11181201
WARN_ON_ONCE(ret != -ENOMEM);
11191202
goto out; /* We know tf is not allocated */
11201203
}
11211204

1122-
if (is_tracepoint)
1123-
tf->mod = __module_text_address(
1124-
(unsigned long)tf->tpoint->probestub);
1125-
11261205
/* parse arguments */
11271206
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
11281207
trace_probe_log_set_index(i + 2);
@@ -1155,6 +1234,8 @@ static int __trace_fprobe_create(int argc, const char *argv[])
11551234
}
11561235

11571236
out:
1237+
if (tp_mod)
1238+
module_put(tp_mod);
11581239
traceprobe_finish_parse(&ctx);
11591240
trace_probe_log_clear();
11601241
kfree(new_argv);

0 commit comments

Comments
 (0)