aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@plumgrid.com>2015-03-25 15:49:20 -0400
committerIngo Molnar <mingo@kernel.org>2015-04-02 07:25:49 -0400
commit2541517c32be2531e0da59dfd7efc1ce844644f5 (patch)
treea69f215a0bbc2f5db1a5d7aff83a465940e40e01 /include
parent72cbbc8994242b5b43753738c01bf07bf29cb70d (diff)
tracing, perf: Implement BPF programs attached to kprobes
BPF programs, attached to kprobes, provide a safe way to execute user-defined BPF byte-code programs without being able to crash or hang the kernel in any way. The BPF engine makes sure that such programs have a finite execution time and that they cannot break out of their sandbox. The user interface is to attach to a kprobe via the perf syscall: struct perf_event_attr attr = { .type = PERF_TYPE_TRACEPOINT, .config = event_id, ... }; event_fd = perf_event_open(&attr,...); ioctl(event_fd, PERF_EVENT_IOC_SET_BPF, prog_fd); 'prog_fd' is a file descriptor associated with BPF program previously loaded. 'event_id' is an ID of the kprobe created. Closing 'event_fd': close(event_fd); ... automatically detaches BPF program from it. BPF programs can call in-kernel helper functions to: - lookup/update/delete elements in maps - probe_read - wraper of probe_kernel_read() used to access any kernel data structures BPF programs receive 'struct pt_regs *' as an input ('struct pt_regs' is architecture dependent) and return 0 to ignore the event and 1 to store kprobe event into the ring buffer. Note, kprobes are a fundamentally _not_ a stable kernel ABI, so BPF programs attached to kprobes must be recompiled for every kernel version and user must supply correct LINUX_VERSION_CODE in attr.kern_version during bpf_prog_load() call. Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Reviewed-by: Steven Rostedt <rostedt@goodmis.org> Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: David S. Miller <davem@davemloft.net> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1427312966-8434-4-git-send-email-ast@plumgrid.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/ftrace_event.h11
-rw-r--r--include/uapi/linux/bpf.h3
-rw-r--r--include/uapi/linux/perf_event.h1
3 files changed, 15 insertions, 0 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 77325e1a1816..0aa535bc9f05 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -13,6 +13,7 @@ struct trace_array;
13struct trace_buffer; 13struct trace_buffer;
14struct tracer; 14struct tracer;
15struct dentry; 15struct dentry;
16struct bpf_prog;
16 17
17struct trace_print_flags { 18struct trace_print_flags {
18 unsigned long mask; 19 unsigned long mask;
@@ -306,6 +307,7 @@ struct ftrace_event_call {
306#ifdef CONFIG_PERF_EVENTS 307#ifdef CONFIG_PERF_EVENTS
307 int perf_refcount; 308 int perf_refcount;
308 struct hlist_head __percpu *perf_events; 309 struct hlist_head __percpu *perf_events;
310 struct bpf_prog *prog;
309 311
310 int (*perf_perm)(struct ftrace_event_call *, 312 int (*perf_perm)(struct ftrace_event_call *,
311 struct perf_event *); 313 struct perf_event *);
@@ -551,6 +553,15 @@ event_trigger_unlock_commit_regs(struct ftrace_event_file *file,
551 event_triggers_post_call(file, tt); 553 event_triggers_post_call(file, tt);
552} 554}
553 555
556#ifdef CONFIG_BPF_SYSCALL
557unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx);
558#else
559static inline unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx)
560{
561 return 1;
562}
563#endif
564
554enum { 565enum {
555 FILTER_OTHER = 0, 566 FILTER_OTHER = 0,
556 FILTER_STATIC_STRING, 567 FILTER_STATIC_STRING,
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 45da7ec7d274..b2948feeb70b 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -118,6 +118,7 @@ enum bpf_map_type {
118enum bpf_prog_type { 118enum bpf_prog_type {
119 BPF_PROG_TYPE_UNSPEC, 119 BPF_PROG_TYPE_UNSPEC,
120 BPF_PROG_TYPE_SOCKET_FILTER, 120 BPF_PROG_TYPE_SOCKET_FILTER,
121 BPF_PROG_TYPE_KPROBE,
121}; 122};
122 123
123/* flags for BPF_MAP_UPDATE_ELEM command */ 124/* flags for BPF_MAP_UPDATE_ELEM command */
@@ -151,6 +152,7 @@ union bpf_attr {
151 __u32 log_level; /* verbosity level of verifier */ 152 __u32 log_level; /* verbosity level of verifier */
152 __u32 log_size; /* size of user buffer */ 153 __u32 log_size; /* size of user buffer */
153 __aligned_u64 log_buf; /* user supplied buffer */ 154 __aligned_u64 log_buf; /* user supplied buffer */
155 __u32 kern_version; /* checked when prog_type=kprobe */
154 }; 156 };
155} __attribute__((aligned(8))); 157} __attribute__((aligned(8)));
156 158
@@ -162,6 +164,7 @@ enum bpf_func_id {
162 BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */ 164 BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
163 BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */ 165 BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
164 BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */ 166 BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
167 BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */
165 __BPF_FUNC_MAX_ID, 168 __BPF_FUNC_MAX_ID,
166}; 169};
167 170
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 3bb40ddadbe5..91803e54ee73 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -381,6 +381,7 @@ struct perf_event_attr {
381#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) 381#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
382#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) 382#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
383#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) 383#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
384#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
384 385
385enum perf_event_ioc_flags { 386enum perf_event_ioc_flags {
386 PERF_IOC_FLAG_GROUP = 1U << 0, 387 PERF_IOC_FLAG_GROUP = 1U << 0,