diff options
| author | Alexei Starovoitov <ast@plumgrid.com> | 2015-03-25 15:49:20 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-04-02 07:25:49 -0400 |
| commit | 2541517c32be2531e0da59dfd7efc1ce844644f5 (patch) | |
| tree | a69f215a0bbc2f5db1a5d7aff83a465940e40e01 /kernel/bpf | |
| parent | 72cbbc8994242b5b43753738c01bf07bf29cb70d (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 'kernel/bpf')
| -rw-r--r-- | kernel/bpf/syscall.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 536edc2be307..504c10b990ef 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/file.h> | 16 | #include <linux/file.h> |
| 17 | #include <linux/license.h> | 17 | #include <linux/license.h> |
| 18 | #include <linux/filter.h> | 18 | #include <linux/filter.h> |
| 19 | #include <linux/version.h> | ||
| 19 | 20 | ||
| 20 | static LIST_HEAD(bpf_map_types); | 21 | static LIST_HEAD(bpf_map_types); |
| 21 | 22 | ||
| @@ -467,7 +468,7 @@ struct bpf_prog *bpf_prog_get(u32 ufd) | |||
| 467 | } | 468 | } |
| 468 | 469 | ||
| 469 | /* last field in 'union bpf_attr' used by this command */ | 470 | /* last field in 'union bpf_attr' used by this command */ |
| 470 | #define BPF_PROG_LOAD_LAST_FIELD log_buf | 471 | #define BPF_PROG_LOAD_LAST_FIELD kern_version |
| 471 | 472 | ||
| 472 | static int bpf_prog_load(union bpf_attr *attr) | 473 | static int bpf_prog_load(union bpf_attr *attr) |
| 473 | { | 474 | { |
| @@ -492,6 +493,10 @@ static int bpf_prog_load(union bpf_attr *attr) | |||
| 492 | if (attr->insn_cnt >= BPF_MAXINSNS) | 493 | if (attr->insn_cnt >= BPF_MAXINSNS) |
| 493 | return -EINVAL; | 494 | return -EINVAL; |
| 494 | 495 | ||
| 496 | if (type == BPF_PROG_TYPE_KPROBE && | ||
| 497 | attr->kern_version != LINUX_VERSION_CODE) | ||
| 498 | return -EINVAL; | ||
| 499 | |||
| 495 | /* plain bpf_prog allocation */ | 500 | /* plain bpf_prog allocation */ |
| 496 | prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER); | 501 | prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER); |
| 497 | if (!prog) | 502 | if (!prog) |
