aboutsummaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
Diffstat (limited to 'samples')
-rw-r--r--samples/bpf/Makefile42
-rw-r--r--samples/bpf/README.rst66
-rw-r--r--samples/bpf/bpf_load.c26
-rw-r--r--samples/bpf/offwaketime_kern.c36
-rw-r--r--samples/bpf/test_overhead_kprobe_kern.c41
-rw-r--r--samples/bpf/test_overhead_tp_kern.c36
-rw-r--r--samples/bpf/test_overhead_user.c162
-rw-r--r--samples/bpf/test_verifier.c268
-rw-r--r--samples/bpf/tracex1_kern.c4
-rw-r--r--samples/bpf/tracex2_kern.c4
-rw-r--r--samples/bpf/tracex5_kern.c6
11 files changed, 668 insertions, 23 deletions
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index b820cc96a3bc..66897e61232c 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -19,6 +19,7 @@ hostprogs-y += lathist
19hostprogs-y += offwaketime 19hostprogs-y += offwaketime
20hostprogs-y += spintest 20hostprogs-y += spintest
21hostprogs-y += map_perf_test 21hostprogs-y += map_perf_test
22hostprogs-y += test_overhead
22 23
23test_verifier-objs := test_verifier.o libbpf.o 24test_verifier-objs := test_verifier.o libbpf.o
24test_maps-objs := test_maps.o libbpf.o 25test_maps-objs := test_maps.o libbpf.o
@@ -38,6 +39,7 @@ lathist-objs := bpf_load.o libbpf.o lathist_user.o
38offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o 39offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o
39spintest-objs := bpf_load.o libbpf.o spintest_user.o 40spintest-objs := bpf_load.o libbpf.o spintest_user.o
40map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o 41map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o
42test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o
41 43
42# Tell kbuild to always build the programs 44# Tell kbuild to always build the programs
43always := $(hostprogs-y) 45always := $(hostprogs-y)
@@ -56,6 +58,8 @@ always += lathist_kern.o
56always += offwaketime_kern.o 58always += offwaketime_kern.o
57always += spintest_kern.o 59always += spintest_kern.o
58always += map_perf_test_kern.o 60always += map_perf_test_kern.o
61always += test_overhead_tp_kern.o
62always += test_overhead_kprobe_kern.o
59 63
60HOSTCFLAGS += -I$(objtree)/usr/include 64HOSTCFLAGS += -I$(objtree)/usr/include
61 65
@@ -75,11 +79,45 @@ HOSTLOADLIBES_lathist += -lelf
75HOSTLOADLIBES_offwaketime += -lelf 79HOSTLOADLIBES_offwaketime += -lelf
76HOSTLOADLIBES_spintest += -lelf 80HOSTLOADLIBES_spintest += -lelf
77HOSTLOADLIBES_map_perf_test += -lelf -lrt 81HOSTLOADLIBES_map_perf_test += -lelf -lrt
82HOSTLOADLIBES_test_overhead += -lelf -lrt
83
84# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
85# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
86LLC ?= llc
87CLANG ?= clang
88
89# Trick to allow make to be run from this directory
90all:
91 $(MAKE) -C ../../ $$PWD/
92
93clean:
94 $(MAKE) -C ../../ M=$$PWD clean
95 @rm -f *~
96
97# Verify LLVM compiler tools are available and bpf target is supported by llc
98.PHONY: verify_cmds verify_target_bpf $(CLANG) $(LLC)
99
100verify_cmds: $(CLANG) $(LLC)
101 @for TOOL in $^ ; do \
102 if ! (which -- "$${TOOL}" > /dev/null 2>&1); then \
103 echo "*** ERROR: Cannot find LLVM tool $${TOOL}" ;\
104 exit 1; \
105 else true; fi; \
106 done
107
108verify_target_bpf: verify_cmds
109 @if ! (${LLC} -march=bpf -mattr=help > /dev/null 2>&1); then \
110 echo "*** ERROR: LLVM (${LLC}) does not support 'bpf' target" ;\
111 echo " NOTICE: LLVM version >= 3.7.1 required" ;\
112 exit 2; \
113 else true; fi
114
115$(src)/*.c: verify_target_bpf
78 116
79# asm/sysreg.h - inline assembly used by it is incompatible with llvm. 117# asm/sysreg.h - inline assembly used by it is incompatible with llvm.
80# But, there is no easy way to fix it, so just exclude it since it is 118# But, there is no easy way to fix it, so just exclude it since it is
81# useless for BPF samples. 119# useless for BPF samples.
82$(obj)/%.o: $(src)/%.c 120$(obj)/%.o: $(src)/%.c
83 clang $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) \ 121 $(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) \
84 -D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \ 122 -D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \
85 -O2 -emit-llvm -c $< -o -| llc -march=bpf -filetype=obj -o $@ 123 -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
diff --git a/samples/bpf/README.rst b/samples/bpf/README.rst
new file mode 100644
index 000000000000..a43eae3f0551
--- /dev/null
+++ b/samples/bpf/README.rst
@@ -0,0 +1,66 @@
1eBPF sample programs
2====================
3
4This directory contains a mini eBPF library, test stubs, verifier
5test-suite and examples for using eBPF.
6
7Build dependencies
8==================
9
10Compiling requires having installed:
11 * clang >= version 3.4.0
12 * llvm >= version 3.7.1
13
14Note that LLVM's tool 'llc' must support target 'bpf', list version
15and supported targets with command: ``llc --version``
16
17Kernel headers
18--------------
19
20There are usually dependencies to header files of the current kernel.
21To avoid installing devel kernel headers system wide, as a normal
22user, simply call::
23
24 make headers_install
25
26This will creates a local "usr/include" directory in the git/build top
27level directory, that the make system automatically pickup first.
28
29Compiling
30=========
31
32For building the BPF samples, issue the below command from the kernel
33top level directory::
34
35 make samples/bpf/
36
37Do notice the "/" slash after the directory name.
38
39It is also possible to call make from this directory. This will just
40hide the the invocation of make as above with the appended "/".
41
42Manually compiling LLVM with 'bpf' support
43------------------------------------------
44
45Since version 3.7.0, LLVM adds a proper LLVM backend target for the
46BPF bytecode architecture.
47
48By default llvm will build all non-experimental backends including bpf.
49To generate a smaller llc binary one can use::
50
51 -DLLVM_TARGETS_TO_BUILD="BPF"
52
53Quick sniplet for manually compiling LLVM and clang
54(build dependencies are cmake and gcc-c++)::
55
56 $ git clone http://llvm.org/git/llvm.git
57 $ cd llvm/tools
58 $ git clone --depth 1 http://llvm.org/git/clang.git
59 $ cd ..; mkdir build; cd build
60 $ cmake .. -DLLVM_TARGETS_TO_BUILD="BPF;X86"
61 $ make -j $(getconf _NPROCESSORS_ONLN)
62
63It is also possible to point make to the newly compiled 'llc' or
64'clang' command via redefining LLC or CLANG on the make command line::
65
66 make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 58f86bd11b3d..022af71c2bb5 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -49,6 +49,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
49 bool is_socket = strncmp(event, "socket", 6) == 0; 49 bool is_socket = strncmp(event, "socket", 6) == 0;
50 bool is_kprobe = strncmp(event, "kprobe/", 7) == 0; 50 bool is_kprobe = strncmp(event, "kprobe/", 7) == 0;
51 bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; 51 bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0;
52 bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0;
52 enum bpf_prog_type prog_type; 53 enum bpf_prog_type prog_type;
53 char buf[256]; 54 char buf[256];
54 int fd, efd, err, id; 55 int fd, efd, err, id;
@@ -63,6 +64,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
63 prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 64 prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
64 } else if (is_kprobe || is_kretprobe) { 65 } else if (is_kprobe || is_kretprobe) {
65 prog_type = BPF_PROG_TYPE_KPROBE; 66 prog_type = BPF_PROG_TYPE_KPROBE;
67 } else if (is_tracepoint) {
68 prog_type = BPF_PROG_TYPE_TRACEPOINT;
66 } else { 69 } else {
67 printf("Unknown event '%s'\n", event); 70 printf("Unknown event '%s'\n", event);
68 return -1; 71 return -1;
@@ -111,12 +114,23 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
111 event, strerror(errno)); 114 event, strerror(errno));
112 return -1; 115 return -1;
113 } 116 }
114 }
115 117
116 strcpy(buf, DEBUGFS); 118 strcpy(buf, DEBUGFS);
117 strcat(buf, "events/kprobes/"); 119 strcat(buf, "events/kprobes/");
118 strcat(buf, event); 120 strcat(buf, event);
119 strcat(buf, "/id"); 121 strcat(buf, "/id");
122 } else if (is_tracepoint) {
123 event += 11;
124
125 if (*event == 0) {
126 printf("event name cannot be empty\n");
127 return -1;
128 }
129 strcpy(buf, DEBUGFS);
130 strcat(buf, "events/");
131 strcat(buf, event);
132 strcat(buf, "/id");
133 }
120 134
121 efd = open(buf, O_RDONLY, 0); 135 efd = open(buf, O_RDONLY, 0);
122 if (efd < 0) { 136 if (efd < 0) {
@@ -304,6 +318,7 @@ int load_bpf_file(char *path)
304 318
305 if (memcmp(shname_prog, "kprobe/", 7) == 0 || 319 if (memcmp(shname_prog, "kprobe/", 7) == 0 ||
306 memcmp(shname_prog, "kretprobe/", 10) == 0 || 320 memcmp(shname_prog, "kretprobe/", 10) == 0 ||
321 memcmp(shname_prog, "tracepoint/", 11) == 0 ||
307 memcmp(shname_prog, "socket", 6) == 0) 322 memcmp(shname_prog, "socket", 6) == 0)
308 load_and_attach(shname_prog, insns, data_prog->d_size); 323 load_and_attach(shname_prog, insns, data_prog->d_size);
309 } 324 }
@@ -320,6 +335,7 @@ int load_bpf_file(char *path)
320 335
321 if (memcmp(shname, "kprobe/", 7) == 0 || 336 if (memcmp(shname, "kprobe/", 7) == 0 ||
322 memcmp(shname, "kretprobe/", 10) == 0 || 337 memcmp(shname, "kretprobe/", 10) == 0 ||
338 memcmp(shname, "tracepoint/", 11) == 0 ||
323 memcmp(shname, "socket", 6) == 0) 339 memcmp(shname, "socket", 6) == 0)
324 load_and_attach(shname, data->d_buf, data->d_size); 340 load_and_attach(shname, data->d_buf, data->d_size);
325 } 341 }
diff --git a/samples/bpf/offwaketime_kern.c b/samples/bpf/offwaketime_kern.c
index c0aa5a9b9c48..e7d9a0a3d45b 100644
--- a/samples/bpf/offwaketime_kern.c
+++ b/samples/bpf/offwaketime_kern.c
@@ -11,7 +11,7 @@
11#include <linux/version.h> 11#include <linux/version.h>
12#include <linux/sched.h> 12#include <linux/sched.h>
13 13
14#define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;}) 14#define _(P) ({typeof(P) val; bpf_probe_read(&val, sizeof(val), &P); val;})
15 15
16#define MINBLOCK_US 1 16#define MINBLOCK_US 1
17 17
@@ -61,7 +61,7 @@ SEC("kprobe/try_to_wake_up")
61int waker(struct pt_regs *ctx) 61int waker(struct pt_regs *ctx)
62{ 62{
63 struct task_struct *p = (void *) PT_REGS_PARM1(ctx); 63 struct task_struct *p = (void *) PT_REGS_PARM1(ctx);
64 struct wokeby_t woke = {}; 64 struct wokeby_t woke;
65 u32 pid; 65 u32 pid;
66 66
67 pid = _(p->pid); 67 pid = _(p->pid);
@@ -73,19 +73,21 @@ int waker(struct pt_regs *ctx)
73 return 0; 73 return 0;
74} 74}
75 75
76static inline int update_counts(struct pt_regs *ctx, u32 pid, u64 delta) 76static inline int update_counts(void *ctx, u32 pid, u64 delta)
77{ 77{
78 struct key_t key = {};
79 struct wokeby_t *woke; 78 struct wokeby_t *woke;
80 u64 zero = 0, *val; 79 u64 zero = 0, *val;
80 struct key_t key;
81 81
82 __builtin_memset(&key.waker, 0, sizeof(key.waker));
82 bpf_get_current_comm(&key.target, sizeof(key.target)); 83 bpf_get_current_comm(&key.target, sizeof(key.target));
83 key.tret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS); 84 key.tret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS);
85 key.wret = 0;
84 86
85 woke = bpf_map_lookup_elem(&wokeby, &pid); 87 woke = bpf_map_lookup_elem(&wokeby, &pid);
86 if (woke) { 88 if (woke) {
87 key.wret = woke->ret; 89 key.wret = woke->ret;
88 __builtin_memcpy(&key.waker, woke->name, TASK_COMM_LEN); 90 __builtin_memcpy(&key.waker, woke->name, sizeof(key.waker));
89 bpf_map_delete_elem(&wokeby, &pid); 91 bpf_map_delete_elem(&wokeby, &pid);
90 } 92 }
91 93
@@ -100,15 +102,33 @@ static inline int update_counts(struct pt_regs *ctx, u32 pid, u64 delta)
100 return 0; 102 return 0;
101} 103}
102 104
105#if 1
106/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */
107struct sched_switch_args {
108 unsigned long long pad;
109 char prev_comm[16];
110 int prev_pid;
111 int prev_prio;
112 long long prev_state;
113 char next_comm[16];
114 int next_pid;
115 int next_prio;
116};
117SEC("tracepoint/sched/sched_switch")
118int oncpu(struct sched_switch_args *ctx)
119{
120 /* record previous thread sleep time */
121 u32 pid = ctx->prev_pid;
122#else
103SEC("kprobe/finish_task_switch") 123SEC("kprobe/finish_task_switch")
104int oncpu(struct pt_regs *ctx) 124int oncpu(struct pt_regs *ctx)
105{ 125{
106 struct task_struct *p = (void *) PT_REGS_PARM1(ctx); 126 struct task_struct *p = (void *) PT_REGS_PARM1(ctx);
127 /* record previous thread sleep time */
128 u32 pid = _(p->pid);
129#endif
107 u64 delta, ts, *tsp; 130 u64 delta, ts, *tsp;
108 u32 pid;
109 131
110 /* record previous thread sleep time */
111 pid = _(p->pid);
112 ts = bpf_ktime_get_ns(); 132 ts = bpf_ktime_get_ns();
113 bpf_map_update_elem(&start, &pid, &ts, BPF_ANY); 133 bpf_map_update_elem(&start, &pid, &ts, BPF_ANY);
114 134
diff --git a/samples/bpf/test_overhead_kprobe_kern.c b/samples/bpf/test_overhead_kprobe_kern.c
new file mode 100644
index 000000000000..468a66a92ef9
--- /dev/null
+++ b/samples/bpf/test_overhead_kprobe_kern.c
@@ -0,0 +1,41 @@
1/* Copyright (c) 2016 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include <linux/version.h>
8#include <linux/ptrace.h>
9#include <uapi/linux/bpf.h>
10#include "bpf_helpers.h"
11
12#define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;})
13
14SEC("kprobe/__set_task_comm")
15int prog(struct pt_regs *ctx)
16{
17 struct signal_struct *signal;
18 struct task_struct *tsk;
19 char oldcomm[16] = {};
20 char newcomm[16] = {};
21 u16 oom_score_adj;
22 u32 pid;
23
24 tsk = (void *)PT_REGS_PARM1(ctx);
25
26 pid = _(tsk->pid);
27 bpf_probe_read(oldcomm, sizeof(oldcomm), &tsk->comm);
28 bpf_probe_read(newcomm, sizeof(newcomm), (void *)PT_REGS_PARM2(ctx));
29 signal = _(tsk->signal);
30 oom_score_adj = _(signal->oom_score_adj);
31 return 0;
32}
33
34SEC("kprobe/urandom_read")
35int prog2(struct pt_regs *ctx)
36{
37 return 0;
38}
39
40char _license[] SEC("license") = "GPL";
41u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/test_overhead_tp_kern.c b/samples/bpf/test_overhead_tp_kern.c
new file mode 100644
index 000000000000..38f5c0b9da9f
--- /dev/null
+++ b/samples/bpf/test_overhead_tp_kern.c
@@ -0,0 +1,36 @@
1/* Copyright (c) 2016 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include <uapi/linux/bpf.h>
8#include "bpf_helpers.h"
9
10/* from /sys/kernel/debug/tracing/events/task/task_rename/format */
11struct task_rename {
12 __u64 pad;
13 __u32 pid;
14 char oldcomm[16];
15 char newcomm[16];
16 __u16 oom_score_adj;
17};
18SEC("tracepoint/task/task_rename")
19int prog(struct task_rename *ctx)
20{
21 return 0;
22}
23
24/* from /sys/kernel/debug/tracing/events/random/urandom_read/format */
25struct urandom_read {
26 __u64 pad;
27 int got_bits;
28 int pool_left;
29 int input_left;
30};
31SEC("tracepoint/random/urandom_read")
32int prog2(struct urandom_read *ctx)
33{
34 return 0;
35}
36char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/test_overhead_user.c b/samples/bpf/test_overhead_user.c
new file mode 100644
index 000000000000..d291167fd3c7
--- /dev/null
+++ b/samples/bpf/test_overhead_user.c
@@ -0,0 +1,162 @@
1/* Copyright (c) 2016 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#define _GNU_SOURCE
8#include <sched.h>
9#include <stdio.h>
10#include <sys/types.h>
11#include <asm/unistd.h>
12#include <fcntl.h>
13#include <unistd.h>
14#include <assert.h>
15#include <sys/wait.h>
16#include <stdlib.h>
17#include <signal.h>
18#include <linux/bpf.h>
19#include <string.h>
20#include <time.h>
21#include <sys/resource.h>
22#include "libbpf.h"
23#include "bpf_load.h"
24
25#define MAX_CNT 1000000
26
27static __u64 time_get_ns(void)
28{
29 struct timespec ts;
30
31 clock_gettime(CLOCK_MONOTONIC, &ts);
32 return ts.tv_sec * 1000000000ull + ts.tv_nsec;
33}
34
35static void test_task_rename(int cpu)
36{
37 __u64 start_time;
38 char buf[] = "test\n";
39 int i, fd;
40
41 fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
42 if (fd < 0) {
43 printf("couldn't open /proc\n");
44 exit(1);
45 }
46 start_time = time_get_ns();
47 for (i = 0; i < MAX_CNT; i++)
48 write(fd, buf, sizeof(buf));
49 printf("task_rename:%d: %lld events per sec\n",
50 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
51 close(fd);
52}
53
54static void test_urandom_read(int cpu)
55{
56 __u64 start_time;
57 char buf[4];
58 int i, fd;
59
60 fd = open("/dev/urandom", O_RDONLY);
61 if (fd < 0) {
62 printf("couldn't open /dev/urandom\n");
63 exit(1);
64 }
65 start_time = time_get_ns();
66 for (i = 0; i < MAX_CNT; i++)
67 read(fd, buf, sizeof(buf));
68 printf("urandom_read:%d: %lld events per sec\n",
69 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
70 close(fd);
71}
72
73static void loop(int cpu, int flags)
74{
75 cpu_set_t cpuset;
76
77 CPU_ZERO(&cpuset);
78 CPU_SET(cpu, &cpuset);
79 sched_setaffinity(0, sizeof(cpuset), &cpuset);
80
81 if (flags & 1)
82 test_task_rename(cpu);
83 if (flags & 2)
84 test_urandom_read(cpu);
85}
86
87static void run_perf_test(int tasks, int flags)
88{
89 pid_t pid[tasks];
90 int i;
91
92 for (i = 0; i < tasks; i++) {
93 pid[i] = fork();
94 if (pid[i] == 0) {
95 loop(i, flags);
96 exit(0);
97 } else if (pid[i] == -1) {
98 printf("couldn't spawn #%d process\n", i);
99 exit(1);
100 }
101 }
102 for (i = 0; i < tasks; i++) {
103 int status;
104
105 assert(waitpid(pid[i], &status, 0) == pid[i]);
106 assert(status == 0);
107 }
108}
109
110static void unload_progs(void)
111{
112 close(prog_fd[0]);
113 close(prog_fd[1]);
114 close(event_fd[0]);
115 close(event_fd[1]);
116}
117
118int main(int argc, char **argv)
119{
120 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
121 char filename[256];
122 int num_cpu = 8;
123 int test_flags = ~0;
124
125 setrlimit(RLIMIT_MEMLOCK, &r);
126
127 if (argc > 1)
128 test_flags = atoi(argv[1]) ? : test_flags;
129 if (argc > 2)
130 num_cpu = atoi(argv[2]) ? : num_cpu;
131
132 if (test_flags & 0x3) {
133 printf("BASE\n");
134 run_perf_test(num_cpu, test_flags);
135 }
136
137 if (test_flags & 0xC) {
138 snprintf(filename, sizeof(filename),
139 "%s_kprobe_kern.o", argv[0]);
140 if (load_bpf_file(filename)) {
141 printf("%s", bpf_log_buf);
142 return 1;
143 }
144 printf("w/KPROBE\n");
145 run_perf_test(num_cpu, test_flags >> 2);
146 unload_progs();
147 }
148
149 if (test_flags & 0x30) {
150 snprintf(filename, sizeof(filename),
151 "%s_tp_kern.o", argv[0]);
152 if (load_bpf_file(filename)) {
153 printf("%s", bpf_log_buf);
154 return 1;
155 }
156 printf("w/TRACEPOINT\n");
157 run_perf_test(num_cpu, test_flags >> 4);
158 unload_progs();
159 }
160
161 return 0;
162}
diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c
index 4b51a9039c0d..9eba8d1d9dcc 100644
--- a/samples/bpf/test_verifier.c
+++ b/samples/bpf/test_verifier.c
@@ -309,6 +309,19 @@ static struct bpf_test tests[] = {
309 .result_unpriv = REJECT, 309 .result_unpriv = REJECT,
310 }, 310 },
311 { 311 {
312 "check valid spill/fill, skb mark",
313 .insns = {
314 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_1),
315 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -8),
316 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
317 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
318 offsetof(struct __sk_buff, mark)),
319 BPF_EXIT_INSN(),
320 },
321 .result = ACCEPT,
322 .result_unpriv = ACCEPT,
323 },
324 {
312 "check corrupted spill/fill", 325 "check corrupted spill/fill",
313 .insns = { 326 .insns = {
314 /* spill R1(ctx) into stack */ 327 /* spill R1(ctx) into stack */
@@ -1180,6 +1193,261 @@ static struct bpf_test tests[] = {
1180 .result_unpriv = REJECT, 1193 .result_unpriv = REJECT,
1181 .result = ACCEPT, 1194 .result = ACCEPT,
1182 }, 1195 },
1196 {
1197 "raw_stack: no skb_load_bytes",
1198 .insns = {
1199 BPF_MOV64_IMM(BPF_REG_2, 4),
1200 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1201 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
1202 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1203 BPF_MOV64_IMM(BPF_REG_4, 8),
1204 /* Call to skb_load_bytes() omitted. */
1205 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1206 BPF_EXIT_INSN(),
1207 },
1208 .result = REJECT,
1209 .errstr = "invalid read from stack off -8+0 size 8",
1210 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1211 },
1212 {
1213 "raw_stack: skb_load_bytes, no init",
1214 .insns = {
1215 BPF_MOV64_IMM(BPF_REG_2, 4),
1216 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1217 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
1218 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1219 BPF_MOV64_IMM(BPF_REG_4, 8),
1220 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1221 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1222 BPF_EXIT_INSN(),
1223 },
1224 .result = ACCEPT,
1225 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1226 },
1227 {
1228 "raw_stack: skb_load_bytes, init",
1229 .insns = {
1230 BPF_MOV64_IMM(BPF_REG_2, 4),
1231 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1232 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
1233 BPF_ST_MEM(BPF_DW, BPF_REG_6, 0, 0xcafe),
1234 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1235 BPF_MOV64_IMM(BPF_REG_4, 8),
1236 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1237 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1238 BPF_EXIT_INSN(),
1239 },
1240 .result = ACCEPT,
1241 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1242 },
1243 {
1244 "raw_stack: skb_load_bytes, spilled regs around bounds",
1245 .insns = {
1246 BPF_MOV64_IMM(BPF_REG_2, 4),
1247 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1248 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
1249 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
1250 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
1251 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1252 BPF_MOV64_IMM(BPF_REG_4, 8),
1253 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1254 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
1255 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
1256 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
1257 offsetof(struct __sk_buff, mark)),
1258 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
1259 offsetof(struct __sk_buff, priority)),
1260 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
1261 BPF_EXIT_INSN(),
1262 },
1263 .result = ACCEPT,
1264 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1265 },
1266 {
1267 "raw_stack: skb_load_bytes, spilled regs corruption",
1268 .insns = {
1269 BPF_MOV64_IMM(BPF_REG_2, 4),
1270 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1271 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
1272 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
1273 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1274 BPF_MOV64_IMM(BPF_REG_4, 8),
1275 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1276 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), /* fill ctx into R0 */
1277 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
1278 offsetof(struct __sk_buff, mark)),
1279 BPF_EXIT_INSN(),
1280 },
1281 .result = REJECT,
1282 .errstr = "R0 invalid mem access 'inv'",
1283 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1284 },
1285 {
1286 "raw_stack: skb_load_bytes, spilled regs corruption 2",
1287 .insns = {
1288 BPF_MOV64_IMM(BPF_REG_2, 4),
1289 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1290 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
1291 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
1292 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
1293 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
1294 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1295 BPF_MOV64_IMM(BPF_REG_4, 8),
1296 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1297 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
1298 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
1299 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill ctx into R3 */
1300 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
1301 offsetof(struct __sk_buff, mark)),
1302 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
1303 offsetof(struct __sk_buff, priority)),
1304 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
1305 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_3,
1306 offsetof(struct __sk_buff, pkt_type)),
1307 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3),
1308 BPF_EXIT_INSN(),
1309 },
1310 .result = REJECT,
1311 .errstr = "R3 invalid mem access 'inv'",
1312 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1313 },
1314 {
1315 "raw_stack: skb_load_bytes, spilled regs + data",
1316 .insns = {
1317 BPF_MOV64_IMM(BPF_REG_2, 4),
1318 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1319 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
1320 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
1321 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
1322 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
1323 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1324 BPF_MOV64_IMM(BPF_REG_4, 8),
1325 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1326 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
1327 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
1328 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill data into R3 */
1329 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
1330 offsetof(struct __sk_buff, mark)),
1331 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
1332 offsetof(struct __sk_buff, priority)),
1333 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
1334 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3),
1335 BPF_EXIT_INSN(),
1336 },
1337 .result = ACCEPT,
1338 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1339 },
1340 {
1341 "raw_stack: skb_load_bytes, invalid access 1",
1342 .insns = {
1343 BPF_MOV64_IMM(BPF_REG_2, 4),
1344 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1345 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -513),
1346 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1347 BPF_MOV64_IMM(BPF_REG_4, 8),
1348 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1349 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1350 BPF_EXIT_INSN(),
1351 },
1352 .result = REJECT,
1353 .errstr = "invalid stack type R3 off=-513 access_size=8",
1354 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1355 },
1356 {
1357 "raw_stack: skb_load_bytes, invalid access 2",
1358 .insns = {
1359 BPF_MOV64_IMM(BPF_REG_2, 4),
1360 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1361 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
1362 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1363 BPF_MOV64_IMM(BPF_REG_4, 8),
1364 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1365 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1366 BPF_EXIT_INSN(),
1367 },
1368 .result = REJECT,
1369 .errstr = "invalid stack type R3 off=-1 access_size=8",
1370 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1371 },
1372 {
1373 "raw_stack: skb_load_bytes, invalid access 3",
1374 .insns = {
1375 BPF_MOV64_IMM(BPF_REG_2, 4),
1376 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1377 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 0xffffffff),
1378 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1379 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
1380 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1381 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1382 BPF_EXIT_INSN(),
1383 },
1384 .result = REJECT,
1385 .errstr = "invalid stack type R3 off=-1 access_size=-1",
1386 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1387 },
1388 {
1389 "raw_stack: skb_load_bytes, invalid access 4",
1390 .insns = {
1391 BPF_MOV64_IMM(BPF_REG_2, 4),
1392 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1393 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
1394 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1395 BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
1396 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1397 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1398 BPF_EXIT_INSN(),
1399 },
1400 .result = REJECT,
1401 .errstr = "invalid stack type R3 off=-1 access_size=2147483647",
1402 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1403 },
1404 {
1405 "raw_stack: skb_load_bytes, invalid access 5",
1406 .insns = {
1407 BPF_MOV64_IMM(BPF_REG_2, 4),
1408 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1409 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
1410 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1411 BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
1412 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1413 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1414 BPF_EXIT_INSN(),
1415 },
1416 .result = REJECT,
1417 .errstr = "invalid stack type R3 off=-512 access_size=2147483647",
1418 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1419 },
1420 {
1421 "raw_stack: skb_load_bytes, invalid access 6",
1422 .insns = {
1423 BPF_MOV64_IMM(BPF_REG_2, 4),
1424 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1425 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
1426 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1427 BPF_MOV64_IMM(BPF_REG_4, 0),
1428 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1429 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1430 BPF_EXIT_INSN(),
1431 },
1432 .result = REJECT,
1433 .errstr = "invalid stack type R3 off=-512 access_size=0",
1434 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1435 },
1436 {
1437 "raw_stack: skb_load_bytes, large access",
1438 .insns = {
1439 BPF_MOV64_IMM(BPF_REG_2, 4),
1440 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
1441 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
1442 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
1443 BPF_MOV64_IMM(BPF_REG_4, 512),
1444 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
1445 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
1446 BPF_EXIT_INSN(),
1447 },
1448 .result = ACCEPT,
1449 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1450 },
1183}; 1451};
1184 1452
1185static int probe_filter_length(struct bpf_insn *fp) 1453static int probe_filter_length(struct bpf_insn *fp)
diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c
index 3f450a8fa1f3..107da148820f 100644
--- a/samples/bpf/tracex1_kern.c
+++ b/samples/bpf/tracex1_kern.c
@@ -23,16 +23,14 @@ int bpf_prog1(struct pt_regs *ctx)
23 /* attaches to kprobe netif_receive_skb, 23 /* attaches to kprobe netif_receive_skb,
24 * looks for packets on loobpack device and prints them 24 * looks for packets on loobpack device and prints them
25 */ 25 */
26 char devname[IFNAMSIZ] = {}; 26 char devname[IFNAMSIZ];
27 struct net_device *dev; 27 struct net_device *dev;
28 struct sk_buff *skb; 28 struct sk_buff *skb;
29 int len; 29 int len;
30 30
31 /* non-portable! works for the given kernel only */ 31 /* non-portable! works for the given kernel only */
32 skb = (struct sk_buff *) PT_REGS_PARM1(ctx); 32 skb = (struct sk_buff *) PT_REGS_PARM1(ctx);
33
34 dev = _(skb->dev); 33 dev = _(skb->dev);
35
36 len = _(skb->len); 34 len = _(skb->len);
37 35
38 bpf_probe_read(devname, sizeof(devname), dev->name); 36 bpf_probe_read(devname, sizeof(devname), dev->name);
diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c
index 6d6eefd0d465..5e11c20ce5ec 100644
--- a/samples/bpf/tracex2_kern.c
+++ b/samples/bpf/tracex2_kern.c
@@ -66,7 +66,7 @@ struct hist_key {
66 char comm[16]; 66 char comm[16];
67 u64 pid_tgid; 67 u64 pid_tgid;
68 u64 uid_gid; 68 u64 uid_gid;
69 u32 index; 69 u64 index;
70}; 70};
71 71
72struct bpf_map_def SEC("maps") my_hist_map = { 72struct bpf_map_def SEC("maps") my_hist_map = {
@@ -82,7 +82,7 @@ int bpf_prog3(struct pt_regs *ctx)
82 long write_size = PT_REGS_PARM3(ctx); 82 long write_size = PT_REGS_PARM3(ctx);
83 long init_val = 1; 83 long init_val = 1;
84 long *value; 84 long *value;
85 struct hist_key key = {}; 85 struct hist_key key;
86 86
87 key.index = log2l(write_size); 87 key.index = log2l(write_size);
88 key.pid_tgid = bpf_get_current_pid_tgid(); 88 key.pid_tgid = bpf_get_current_pid_tgid();
diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5_kern.c
index b3f4295bf288..f95f232cbab9 100644
--- a/samples/bpf/tracex5_kern.c
+++ b/samples/bpf/tracex5_kern.c
@@ -22,7 +22,7 @@ struct bpf_map_def SEC("maps") progs = {
22SEC("kprobe/seccomp_phase1") 22SEC("kprobe/seccomp_phase1")
23int bpf_prog1(struct pt_regs *ctx) 23int bpf_prog1(struct pt_regs *ctx)
24{ 24{
25 struct seccomp_data sd = {}; 25 struct seccomp_data sd;
26 26
27 bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); 27 bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx));
28 28
@@ -40,7 +40,7 @@ int bpf_prog1(struct pt_regs *ctx)
40/* we jump here when syscall number == __NR_write */ 40/* we jump here when syscall number == __NR_write */
41PROG(__NR_write)(struct pt_regs *ctx) 41PROG(__NR_write)(struct pt_regs *ctx)
42{ 42{
43 struct seccomp_data sd = {}; 43 struct seccomp_data sd;
44 44
45 bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); 45 bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx));
46 if (sd.args[2] == 512) { 46 if (sd.args[2] == 512) {
@@ -53,7 +53,7 @@ PROG(__NR_write)(struct pt_regs *ctx)
53 53
54PROG(__NR_read)(struct pt_regs *ctx) 54PROG(__NR_read)(struct pt_regs *ctx)
55{ 55{
56 struct seccomp_data sd = {}; 56 struct seccomp_data sd;
57 57
58 bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); 58 bpf_probe_read(&sd, sizeof(sd), (void *)PT_REGS_PARM1(ctx));
59 if (sd.args[2] > 128 && sd.args[2] <= 1024) { 59 if (sd.args[2] > 128 && sd.args[2] <= 1024) {