tracing/kprobe: Add kprobe_event= boot parameter

Add kprobe_event= boot parameter to define kprobe events
at boot time.
The definition syntax is similar to tracefs/kprobe_events
interface, but use ',' and ';' instead of ' ' and '\n'
respectively. e.g.

  kprobe_event=p,vfs_read,$arg1,$arg2

This puts a probe on vfs_read with argument1 and 2, and
enable the new event.

Link: http://lkml.kernel.org/r/155851395498.15728.830529496248543583.stgit@devnote2

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
Masami Hiramatsu 2019-05-22 17:32:35 +09:00 committed by Steven Rostedt (VMware)
parent b5f8b32c93
commit 970988e19e
3 changed files with 81 additions and 0 deletions

View File

@ -2007,6 +2007,19 @@
Built with CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y, Built with CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y,
the default is off. the default is off.
kprobe_event=[probe-list]
[FTRACE] Add kprobe events and enable at boot time.
The probe-list is a semicolon delimited list of probe
definitions. Each definition is same as kprobe_events
interface, but the parameters are comma delimited.
For example, to add a kprobe event on vfs_read with
arg1 and arg2, add to the command line;
kprobe_event=p,vfs_read,$arg1,$arg2
See also Documentation/trace/kprobetrace.rst "Kernel
Boot Parameter" section.
kpti= [ARM64] Control page table isolation of user kpti= [ARM64] Control page table isolation of user
and kernel address spaces. and kernel address spaces.
Default: enabled on cores which need mitigation. Default: enabled on cores which need mitigation.

View File

@ -146,6 +146,20 @@ You can check the total number of probe hits and probe miss-hits via
The first column is event name, the second is the number of probe hits, The first column is event name, the second is the number of probe hits,
the third is the number of probe miss-hits. the third is the number of probe miss-hits.
Kernel Boot Parameter
---------------------
You can add and enable new kprobe events when booting up the kernel by
"kprobe_event=" parameter. The parameter accepts a semicolon-delimited
kprobe events, which format is similar to the kprobe_events.
The difference is that the probe definition parameters are comma-delimited
instead of space. For example, adding myprobe event on do_sys_open like below
p:myprobe do_sys_open dfd=%ax filename=%dx flags=%cx mode=+4($stack)
should be below for kernel boot parameter (just replace spaces with comma)
p:myprobe,do_sys_open,dfd=%ax,filename=%dx,flags=%cx,mode=+4($stack)
Usage examples Usage examples
-------------- --------------

View File

@ -12,6 +12,8 @@
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/error-injection.h> #include <linux/error-injection.h>
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
#include "trace_dynevent.h" #include "trace_dynevent.h"
#include "trace_kprobe_selftest.h" #include "trace_kprobe_selftest.h"
#include "trace_probe.h" #include "trace_probe.h"
@ -19,6 +21,17 @@
#define KPROBE_EVENT_SYSTEM "kprobes" #define KPROBE_EVENT_SYSTEM "kprobes"
#define KRETPROBE_MAXACTIVE_MAX 4096 #define KRETPROBE_MAXACTIVE_MAX 4096
#define MAX_KPROBE_CMDLINE_SIZE 1024
/* Kprobe early definition from command line */
static char kprobe_boot_events_buf[COMMAND_LINE_SIZE] __initdata;
static int __init set_kprobe_boot_events(char *str)
{
strlcpy(kprobe_boot_events_buf, str, COMMAND_LINE_SIZE);
return 0;
}
__setup("kprobe_event=", set_kprobe_boot_events);
static int trace_kprobe_create(int argc, const char **argv); static int trace_kprobe_create(int argc, const char **argv);
static int trace_kprobe_show(struct seq_file *m, struct dyn_event *ev); static int trace_kprobe_show(struct seq_file *m, struct dyn_event *ev);
@ -1494,6 +1507,44 @@ void destroy_local_trace_kprobe(struct trace_event_call *event_call)
} }
#endif /* CONFIG_PERF_EVENTS */ #endif /* CONFIG_PERF_EVENTS */
static __init void enable_boot_kprobe_events(void)
{
struct trace_array *tr = top_trace_array();
struct trace_event_file *file;
struct trace_kprobe *tk;
struct dyn_event *pos;
mutex_lock(&event_mutex);
for_each_trace_kprobe(tk, pos) {
list_for_each_entry(file, &tr->events, list)
if (file->event_call == &tk->tp.call)
trace_event_enable_disable(file, 1, 0);
}
mutex_unlock(&event_mutex);
}
static __init void setup_boot_kprobe_events(void)
{
char *p, *cmd = kprobe_boot_events_buf;
int ret;
strreplace(kprobe_boot_events_buf, ',', ' ');
while (cmd && *cmd != '\0') {
p = strchr(cmd, ';');
if (p)
*p++ = '\0';
ret = trace_run_command(cmd, create_or_delete_trace_kprobe);
if (ret)
pr_warn("Failed to add event(%d): %s\n", ret, cmd);
cmd = p;
}
enable_boot_kprobe_events();
}
/* Make a tracefs interface for controlling probe points */ /* Make a tracefs interface for controlling probe points */
static __init int init_kprobe_trace(void) static __init int init_kprobe_trace(void)
{ {
@ -1525,6 +1576,9 @@ static __init int init_kprobe_trace(void)
if (!entry) if (!entry)
pr_warn("Could not create tracefs 'kprobe_profile' entry\n"); pr_warn("Could not create tracefs 'kprobe_profile' entry\n");
setup_boot_kprobe_events();
return 0; return 0;
} }
fs_initcall(init_kprobe_trace); fs_initcall(init_kprobe_trace);