Skip to content

Commit 6483624

Browse files
Tom Zanussirostedt
Tom Zanussi
authored andcommitted
tracing: Add kprobe event command generation test module
Add a test module that checks the basic functionality of the in-kernel kprobe event command generation API by creating kprobe events from a module. Link: http://lkml.kernel.org/r/97e502b204f9dba948e3fa3a4315448298218787.1580323897.git.zanussi@kernel.org Acked-by: Masami Hiramatsu <[email protected]> Signed-off-by: Tom Zanussi <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 29a1548 commit 6483624

File tree

3 files changed

+238
-0
lines changed

3 files changed

+238
-0
lines changed

kernel/trace/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,18 @@ config SYNTH_EVENT_GEN_TEST
787787

788788
If unsure, say N.
789789

790+
config KPROBE_EVENT_GEN_TEST
791+
tristate "Test module for in-kernel kprobe event generation"
792+
depends on KPROBE_EVENTS
793+
help
794+
This option creates a test module to check the base
795+
functionality of in-kernel kprobe event definition.
796+
797+
To test, insert the module, and then check the trace buffer
798+
for the generated kprobe events.
799+
800+
If unsure, say N.
801+
790802
config TRACE_EVAL_MAP_FILE
791803
bool "Show eval mappings for trace events"
792804
depends on TRACING

kernel/trace/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ obj-$(CONFIG_TRACING) += trace_printk.o
4545
obj-$(CONFIG_TRACING_MAP) += tracing_map.o
4646
obj-$(CONFIG_PREEMPTIRQ_DELAY_TEST) += preemptirq_delay_test.o
4747
obj-$(CONFIG_SYNTH_EVENT_GEN_TEST) += synth_event_gen_test.o
48+
obj-$(CONFIG_KPROBE_EVENT_GEN_TEST) += kprobe_event_gen_test.o
4849
obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
4950
obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
5051
obj-$(CONFIG_PREEMPTIRQ_TRACEPOINTS) += trace_preemptirq.o

kernel/trace/kprobe_event_gen_test.c

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Test module for in-kernel kprobe event creation and generation.
4+
*
5+
* Copyright (C) 2019 Tom Zanussi <[email protected]>
6+
*/
7+
8+
#include <linux/module.h>
9+
#include <linux/trace_events.h>
10+
11+
/*
12+
* This module is a simple test of basic functionality for in-kernel
13+
* kprobe/kretprobe event creation. The first test uses
14+
* kprobe_event_gen_cmd_start(), kprobe_event_add_fields() and
15+
* kprobe_event_gen_cmd_end() to create a kprobe event, which is then
16+
* enabled in order to generate trace output. The second creates a
17+
* kretprobe event using kretprobe_event_gen_cmd_start() and
18+
* kretprobe_event_gen_cmd_end(), and is also then enabled.
19+
*
20+
* To test, select CONFIG_KPROBE_EVENT_GEN_TEST and build the module.
21+
* Then:
22+
*
23+
* # insmod kernel/trace/kprobe_event_gen_test.ko
24+
* # cat /sys/kernel/debug/tracing/trace
25+
*
26+
* You should see many instances of the "gen_kprobe_test" and
27+
* "gen_kretprobe_test" events in the trace buffer.
28+
*
29+
* To remove the events, remove the module:
30+
*
31+
* # rmmod kprobe_event_gen_test
32+
*
33+
*/
34+
35+
static struct trace_event_file *gen_kprobe_test;
36+
static struct trace_event_file *gen_kretprobe_test;
37+
38+
/*
39+
* Test to make sure we can create a kprobe event, then add more
40+
* fields.
41+
*/
42+
static int __init test_gen_kprobe_cmd(void)
43+
{
44+
struct dynevent_cmd cmd;
45+
char *buf;
46+
int ret;
47+
48+
/* Create a buffer to hold the generated command */
49+
buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
50+
if (!buf)
51+
return -ENOMEM;
52+
53+
/* Before generating the command, initialize the cmd object */
54+
kprobe_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN);
55+
56+
/*
57+
* Define the gen_kprobe_test event with the first 2 kprobe
58+
* fields.
59+
*/
60+
ret = kprobe_event_gen_cmd_start(&cmd, "gen_kprobe_test",
61+
"do_sys_open",
62+
"dfd=%ax", "filename=%dx");
63+
if (ret)
64+
goto free;
65+
66+
/* Use kprobe_event_add_fields to add the rest of the fields */
67+
68+
ret = kprobe_event_add_fields(&cmd, "flags=%cx", "mode=+4($stack)");
69+
if (ret)
70+
goto free;
71+
72+
/*
73+
* This actually creates the event.
74+
*/
75+
ret = kprobe_event_gen_cmd_end(&cmd);
76+
if (ret)
77+
goto free;
78+
79+
/*
80+
* Now get the gen_kprobe_test event file. We need to prevent
81+
* the instance and event from disappearing from underneath
82+
* us, which trace_get_event_file() does (though in this case
83+
* we're using the top-level instance which never goes away).
84+
*/
85+
gen_kprobe_test = trace_get_event_file(NULL, "kprobes",
86+
"gen_kprobe_test");
87+
if (IS_ERR(gen_kprobe_test)) {
88+
ret = PTR_ERR(gen_kprobe_test);
89+
goto delete;
90+
}
91+
92+
/* Enable the event or you won't see anything */
93+
ret = trace_array_set_clr_event(gen_kprobe_test->tr,
94+
"kprobes", "gen_kprobe_test", true);
95+
if (ret) {
96+
trace_put_event_file(gen_kprobe_test);
97+
goto delete;
98+
}
99+
out:
100+
return ret;
101+
delete:
102+
/* We got an error after creating the event, delete it */
103+
ret = kprobe_event_delete("gen_kprobe_test");
104+
free:
105+
kfree(buf);
106+
107+
goto out;
108+
}
109+
110+
/*
111+
* Test to make sure we can create a kretprobe event.
112+
*/
113+
static int __init test_gen_kretprobe_cmd(void)
114+
{
115+
struct dynevent_cmd cmd;
116+
char *buf;
117+
int ret;
118+
119+
/* Create a buffer to hold the generated command */
120+
buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
121+
if (!buf)
122+
return -ENOMEM;
123+
124+
/* Before generating the command, initialize the cmd object */
125+
kprobe_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN);
126+
127+
/*
128+
* Define the kretprobe event.
129+
*/
130+
ret = kretprobe_event_gen_cmd_start(&cmd, "gen_kretprobe_test",
131+
"do_sys_open",
132+
"$retval");
133+
if (ret)
134+
goto free;
135+
136+
/*
137+
* This actually creates the event.
138+
*/
139+
ret = kretprobe_event_gen_cmd_end(&cmd);
140+
if (ret)
141+
goto free;
142+
143+
/*
144+
* Now get the gen_kretprobe_test event file. We need to
145+
* prevent the instance and event from disappearing from
146+
* underneath us, which trace_get_event_file() does (though in
147+
* this case we're using the top-level instance which never
148+
* goes away).
149+
*/
150+
gen_kretprobe_test = trace_get_event_file(NULL, "kprobes",
151+
"gen_kretprobe_test");
152+
if (IS_ERR(gen_kretprobe_test)) {
153+
ret = PTR_ERR(gen_kretprobe_test);
154+
goto delete;
155+
}
156+
157+
/* Enable the event or you won't see anything */
158+
ret = trace_array_set_clr_event(gen_kretprobe_test->tr,
159+
"kprobes", "gen_kretprobe_test", true);
160+
if (ret) {
161+
trace_put_event_file(gen_kretprobe_test);
162+
goto delete;
163+
}
164+
out:
165+
return ret;
166+
delete:
167+
/* We got an error after creating the event, delete it */
168+
ret = kprobe_event_delete("gen_kretprobe_test");
169+
free:
170+
kfree(buf);
171+
172+
goto out;
173+
}
174+
175+
static int __init kprobe_event_gen_test_init(void)
176+
{
177+
int ret;
178+
179+
ret = test_gen_kprobe_cmd();
180+
if (ret)
181+
return ret;
182+
183+
ret = test_gen_kretprobe_cmd();
184+
if (ret) {
185+
WARN_ON(trace_array_set_clr_event(gen_kretprobe_test->tr,
186+
"kprobes",
187+
"gen_kretprobe_test", false));
188+
trace_put_event_file(gen_kretprobe_test);
189+
WARN_ON(kprobe_event_delete("gen_kretprobe_test"));
190+
}
191+
192+
return ret;
193+
}
194+
195+
static void __exit kprobe_event_gen_test_exit(void)
196+
{
197+
/* Disable the event or you can't remove it */
198+
WARN_ON(trace_array_set_clr_event(gen_kprobe_test->tr,
199+
"kprobes",
200+
"gen_kprobe_test", false));
201+
202+
/* Now give the file and instance back */
203+
trace_put_event_file(gen_kprobe_test);
204+
205+
/* Now unregister and free the event */
206+
WARN_ON(kprobe_event_delete("gen_kprobe_test"));
207+
208+
/* Disable the event or you can't remove it */
209+
WARN_ON(trace_array_set_clr_event(gen_kprobe_test->tr,
210+
"kprobes",
211+
"gen_kretprobe_test", false));
212+
213+
/* Now give the file and instance back */
214+
trace_put_event_file(gen_kretprobe_test);
215+
216+
/* Now unregister and free the event */
217+
WARN_ON(kprobe_event_delete("gen_kretprobe_test"));
218+
}
219+
220+
module_init(kprobe_event_gen_test_init)
221+
module_exit(kprobe_event_gen_test_exit)
222+
223+
MODULE_AUTHOR("Tom Zanussi");
224+
MODULE_DESCRIPTION("kprobe event generation test");
225+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)