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.
Showing the changes to include/uapi (2 of 8 files). Show all
Unified · Split
| @@ -118,6 +118,7 @@ enum bpf_map_type { · 117 unmodified lines | ||
| 118 | 118 | enum bpf_prog_type { |
| 119 | 119 | BPF_PROG_TYPE_UNSPEC, |
| 120 | 120 | BPF_PROG_TYPE_SOCKET_FILTER, |
| 121 | + BPF_PROG_TYPE_KPROBE, | |
| 121 | 122 | }; |
| 122 | 123 | |
| 123 | 124 | /* flags for BPF_MAP_UPDATE_ELEM command */ |
| @@ -151,6 +152,7 @@ union bpf_attr { · 27 unmodified lines | ||
| 151 | 152 | __u32 log_level; /* verbosity level of verifier */ |
| 152 | 153 | __u32 log_size; /* size of user buffer */ |
| 153 | 154 | __aligned_u64 log_buf; /* user supplied buffer */ |
| 155 | + __u32 kern_version; /* checked when prog_type=kprobe */ | |
| 154 | 156 | }; |
| 155 | 157 | } __attribute__((aligned(8))); |
| 156 | 158 | |
| @@ -162,6 +164,7 @@ enum bpf_func_id { · 5 unmodified lines | ||
| 162 | 164 | BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */ |
| 163 | 165 | BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */ |
| 164 | 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 | 168 | __BPF_FUNC_MAX_ID, |
| 166 | 169 | }; |
| 167 | 170 | |
| @@ -381,6 +381,7 @@ struct perf_event_attr { · 380 unmodified lines | ||
| 381 | 381 | #define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) |
| 382 | 382 | #define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) |
| 383 | 383 | #define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) |
| 384 | +#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) | |
| 384 | 385 | |
| 385 | 386 | enum perf_event_ioc_flags { |
| 386 | 387 | PERF_IOC_FLAG_GROUP = 1U << 0, |