diff options
Diffstat (limited to 'samples')
-rw-r--r-- | samples/bpf/Makefile | 42 | ||||
-rw-r--r-- | samples/bpf/README.rst | 66 | ||||
-rw-r--r-- | samples/bpf/bpf_load.c | 26 | ||||
-rw-r--r-- | samples/bpf/offwaketime_kern.c | 36 | ||||
-rw-r--r-- | samples/bpf/test_overhead_kprobe_kern.c | 41 | ||||
-rw-r--r-- | samples/bpf/test_overhead_tp_kern.c | 36 | ||||
-rw-r--r-- | samples/bpf/test_overhead_user.c | 162 | ||||
-rw-r--r-- | samples/bpf/test_verifier.c | 268 | ||||
-rw-r--r-- | samples/bpf/tracex1_kern.c | 4 | ||||
-rw-r--r-- | samples/bpf/tracex2_kern.c | 4 | ||||
-rw-r--r-- | samples/bpf/tracex5_kern.c | 6 |
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 | |||
19 | hostprogs-y += offwaketime | 19 | hostprogs-y += offwaketime |
20 | hostprogs-y += spintest | 20 | hostprogs-y += spintest |
21 | hostprogs-y += map_perf_test | 21 | hostprogs-y += map_perf_test |
22 | hostprogs-y += test_overhead | ||
22 | 23 | ||
23 | test_verifier-objs := test_verifier.o libbpf.o | 24 | test_verifier-objs := test_verifier.o libbpf.o |
24 | test_maps-objs := test_maps.o libbpf.o | 25 | test_maps-objs := test_maps.o libbpf.o |
@@ -38,6 +39,7 @@ lathist-objs := bpf_load.o libbpf.o lathist_user.o | |||
38 | offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o | 39 | offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o |
39 | spintest-objs := bpf_load.o libbpf.o spintest_user.o | 40 | spintest-objs := bpf_load.o libbpf.o spintest_user.o |
40 | map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o | 41 | map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o |
42 | test_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 |
43 | always := $(hostprogs-y) | 45 | always := $(hostprogs-y) |
@@ -56,6 +58,8 @@ always += lathist_kern.o | |||
56 | always += offwaketime_kern.o | 58 | always += offwaketime_kern.o |
57 | always += spintest_kern.o | 59 | always += spintest_kern.o |
58 | always += map_perf_test_kern.o | 60 | always += map_perf_test_kern.o |
61 | always += test_overhead_tp_kern.o | ||
62 | always += test_overhead_kprobe_kern.o | ||
59 | 63 | ||
60 | HOSTCFLAGS += -I$(objtree)/usr/include | 64 | HOSTCFLAGS += -I$(objtree)/usr/include |
61 | 65 | ||
@@ -75,11 +79,45 @@ HOSTLOADLIBES_lathist += -lelf | |||
75 | HOSTLOADLIBES_offwaketime += -lelf | 79 | HOSTLOADLIBES_offwaketime += -lelf |
76 | HOSTLOADLIBES_spintest += -lelf | 80 | HOSTLOADLIBES_spintest += -lelf |
77 | HOSTLOADLIBES_map_perf_test += -lelf -lrt | 81 | HOSTLOADLIBES_map_perf_test += -lelf -lrt |
82 | HOSTLOADLIBES_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 | ||
86 | LLC ?= llc | ||
87 | CLANG ?= clang | ||
88 | |||
89 | # Trick to allow make to be run from this directory | ||
90 | all: | ||
91 | $(MAKE) -C ../../ $$PWD/ | ||
92 | |||
93 | clean: | ||
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 | |||
100 | verify_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 | |||
108 | verify_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 @@ | |||
1 | eBPF sample programs | ||
2 | ==================== | ||
3 | |||
4 | This directory contains a mini eBPF library, test stubs, verifier | ||
5 | test-suite and examples for using eBPF. | ||
6 | |||
7 | Build dependencies | ||
8 | ================== | ||
9 | |||
10 | Compiling requires having installed: | ||
11 | * clang >= version 3.4.0 | ||
12 | * llvm >= version 3.7.1 | ||
13 | |||
14 | Note that LLVM's tool 'llc' must support target 'bpf', list version | ||
15 | and supported targets with command: ``llc --version`` | ||
16 | |||
17 | Kernel headers | ||
18 | -------------- | ||
19 | |||
20 | There are usually dependencies to header files of the current kernel. | ||
21 | To avoid installing devel kernel headers system wide, as a normal | ||
22 | user, simply call:: | ||
23 | |||
24 | make headers_install | ||
25 | |||
26 | This will creates a local "usr/include" directory in the git/build top | ||
27 | level directory, that the make system automatically pickup first. | ||
28 | |||
29 | Compiling | ||
30 | ========= | ||
31 | |||
32 | For building the BPF samples, issue the below command from the kernel | ||
33 | top level directory:: | ||
34 | |||
35 | make samples/bpf/ | ||
36 | |||
37 | Do notice the "/" slash after the directory name. | ||
38 | |||
39 | It is also possible to call make from this directory. This will just | ||
40 | hide the the invocation of make as above with the appended "/". | ||
41 | |||
42 | Manually compiling LLVM with 'bpf' support | ||
43 | ------------------------------------------ | ||
44 | |||
45 | Since version 3.7.0, LLVM adds a proper LLVM backend target for the | ||
46 | BPF bytecode architecture. | ||
47 | |||
48 | By default llvm will build all non-experimental backends including bpf. | ||
49 | To generate a smaller llc binary one can use:: | ||
50 | |||
51 | -DLLVM_TARGETS_TO_BUILD="BPF" | ||
52 | |||
53 | Quick 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 | |||
63 | It 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") | |||
61 | int waker(struct pt_regs *ctx) | 61 | int 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 | ||
76 | static inline int update_counts(struct pt_regs *ctx, u32 pid, u64 delta) | 76 | static 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 */ | ||
107 | struct 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 | }; | ||
117 | SEC("tracepoint/sched/sched_switch") | ||
118 | int oncpu(struct sched_switch_args *ctx) | ||
119 | { | ||
120 | /* record previous thread sleep time */ | ||
121 | u32 pid = ctx->prev_pid; | ||
122 | #else | ||
103 | SEC("kprobe/finish_task_switch") | 123 | SEC("kprobe/finish_task_switch") |
104 | int oncpu(struct pt_regs *ctx) | 124 | int 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 | |||
14 | SEC("kprobe/__set_task_comm") | ||
15 | int 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 | |||
34 | SEC("kprobe/urandom_read") | ||
35 | int prog2(struct pt_regs *ctx) | ||
36 | { | ||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | char _license[] SEC("license") = "GPL"; | ||
41 | u32 _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 */ | ||
11 | struct task_rename { | ||
12 | __u64 pad; | ||
13 | __u32 pid; | ||
14 | char oldcomm[16]; | ||
15 | char newcomm[16]; | ||
16 | __u16 oom_score_adj; | ||
17 | }; | ||
18 | SEC("tracepoint/task/task_rename") | ||
19 | int prog(struct task_rename *ctx) | ||
20 | { | ||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | /* from /sys/kernel/debug/tracing/events/random/urandom_read/format */ | ||
25 | struct urandom_read { | ||
26 | __u64 pad; | ||
27 | int got_bits; | ||
28 | int pool_left; | ||
29 | int input_left; | ||
30 | }; | ||
31 | SEC("tracepoint/random/urandom_read") | ||
32 | int prog2(struct urandom_read *ctx) | ||
33 | { | ||
34 | return 0; | ||
35 | } | ||
36 | char _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 | |||
27 | static __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 | |||
35 | static 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 | |||
54 | static 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 | |||
73 | static 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 | |||
87 | static 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 | |||
110 | static 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 | |||
118 | int 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 | ||
1185 | static int probe_filter_length(struct bpf_insn *fp) | 1453 | static 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 | ||
72 | struct bpf_map_def SEC("maps") my_hist_map = { | 72 | struct 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 = { | |||
22 | SEC("kprobe/seccomp_phase1") | 22 | SEC("kprobe/seccomp_phase1") |
23 | int bpf_prog1(struct pt_regs *ctx) | 23 | int 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 */ |
41 | PROG(__NR_write)(struct pt_regs *ctx) | 41 | PROG(__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 | ||
54 | PROG(__NR_read)(struct pt_regs *ctx) | 54 | PROG(__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) { |