Commit | Line | Data |
---|---|---|
2541517c AS |
1 | /* Copyright (c) 2011-2015 PLUMgrid, http://plumgrid.com |
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/kernel.h> | |
8 | #include <linux/types.h> | |
9 | #include <linux/slab.h> | |
10 | #include <linux/bpf.h> | |
11 | #include <linux/filter.h> | |
12 | #include <linux/uaccess.h> | |
9c959c86 | 13 | #include <linux/ctype.h> |
2541517c AS |
14 | #include "trace.h" |
15 | ||
16 | static DEFINE_PER_CPU(int, bpf_prog_active); | |
17 | ||
18 | /** | |
19 | * trace_call_bpf - invoke BPF program | |
20 | * @prog: BPF program | |
21 | * @ctx: opaque context pointer | |
22 | * | |
23 | * kprobe handlers execute BPF programs via this helper. | |
24 | * Can be used from static tracepoints in the future. | |
25 | * | |
26 | * Return: BPF programs always return an integer which is interpreted by | |
27 | * kprobe handler as: | |
28 | * 0 - return from kprobe (event is filtered out) | |
29 | * 1 - store kprobe event into ring buffer | |
30 | * Other values are reserved and currently alias to 1 | |
31 | */ | |
32 | unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx) | |
33 | { | |
34 | unsigned int ret; | |
35 | ||
36 | if (in_nmi()) /* not supported yet */ | |
37 | return 1; | |
38 | ||
39 | preempt_disable(); | |
40 | ||
41 | if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) { | |
42 | /* | |
43 | * since some bpf program is already running on this cpu, | |
44 | * don't call into another bpf program (same or different) | |
45 | * and don't send kprobe event into ring-buffer, | |
46 | * so return zero here | |
47 | */ | |
48 | ret = 0; | |
49 | goto out; | |
50 | } | |
51 | ||
52 | rcu_read_lock(); | |
53 | ret = BPF_PROG_RUN(prog, ctx); | |
54 | rcu_read_unlock(); | |
55 | ||
56 | out: | |
57 | __this_cpu_dec(bpf_prog_active); | |
58 | preempt_enable(); | |
59 | ||
60 | return ret; | |
61 | } | |
62 | EXPORT_SYMBOL_GPL(trace_call_bpf); | |
63 | ||
64 | static u64 bpf_probe_read(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) | |
65 | { | |
66 | void *dst = (void *) (long) r1; | |
67 | int size = (int) r2; | |
68 | void *unsafe_ptr = (void *) (long) r3; | |
69 | ||
70 | return probe_kernel_read(dst, unsafe_ptr, size); | |
71 | } | |
72 | ||
73 | static const struct bpf_func_proto bpf_probe_read_proto = { | |
74 | .func = bpf_probe_read, | |
75 | .gpl_only = true, | |
76 | .ret_type = RET_INTEGER, | |
77 | .arg1_type = ARG_PTR_TO_STACK, | |
78 | .arg2_type = ARG_CONST_STACK_SIZE, | |
79 | .arg3_type = ARG_ANYTHING, | |
80 | }; | |
81 | ||
9c959c86 AS |
82 | /* |
83 | * limited trace_printk() | |
84 | * only %d %u %x %ld %lu %lx %lld %llu %llx %p conversion specifiers allowed | |
85 | */ | |
86 | static u64 bpf_trace_printk(u64 r1, u64 fmt_size, u64 r3, u64 r4, u64 r5) | |
87 | { | |
88 | char *fmt = (char *) (long) r1; | |
89 | int mod[3] = {}; | |
90 | int fmt_cnt = 0; | |
91 | int i; | |
92 | ||
93 | /* | |
94 | * bpf_check()->check_func_arg()->check_stack_boundary() | |
95 | * guarantees that fmt points to bpf program stack, | |
96 | * fmt_size bytes of it were initialized and fmt_size > 0 | |
97 | */ | |
98 | if (fmt[--fmt_size] != 0) | |
99 | return -EINVAL; | |
100 | ||
101 | /* check format string for allowed specifiers */ | |
102 | for (i = 0; i < fmt_size; i++) { | |
103 | if ((!isprint(fmt[i]) && !isspace(fmt[i])) || !isascii(fmt[i])) | |
104 | return -EINVAL; | |
105 | ||
106 | if (fmt[i] != '%') | |
107 | continue; | |
108 | ||
109 | if (fmt_cnt >= 3) | |
110 | return -EINVAL; | |
111 | ||
112 | /* fmt[i] != 0 && fmt[last] == 0, so we can access fmt[i + 1] */ | |
113 | i++; | |
114 | if (fmt[i] == 'l') { | |
115 | mod[fmt_cnt]++; | |
116 | i++; | |
117 | } else if (fmt[i] == 'p') { | |
118 | mod[fmt_cnt]++; | |
119 | i++; | |
120 | if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0) | |
121 | return -EINVAL; | |
122 | fmt_cnt++; | |
123 | continue; | |
124 | } | |
125 | ||
126 | if (fmt[i] == 'l') { | |
127 | mod[fmt_cnt]++; | |
128 | i++; | |
129 | } | |
130 | ||
131 | if (fmt[i] != 'd' && fmt[i] != 'u' && fmt[i] != 'x') | |
132 | return -EINVAL; | |
133 | fmt_cnt++; | |
134 | } | |
135 | ||
136 | return __trace_printk(1/* fake ip will not be printed */, fmt, | |
137 | mod[0] == 2 ? r3 : mod[0] == 1 ? (long) r3 : (u32) r3, | |
138 | mod[1] == 2 ? r4 : mod[1] == 1 ? (long) r4 : (u32) r4, | |
139 | mod[2] == 2 ? r5 : mod[2] == 1 ? (long) r5 : (u32) r5); | |
140 | } | |
141 | ||
142 | static const struct bpf_func_proto bpf_trace_printk_proto = { | |
143 | .func = bpf_trace_printk, | |
144 | .gpl_only = true, | |
145 | .ret_type = RET_INTEGER, | |
146 | .arg1_type = ARG_PTR_TO_STACK, | |
147 | .arg2_type = ARG_CONST_STACK_SIZE, | |
148 | }; | |
149 | ||
0756ea3e AS |
150 | const struct bpf_func_proto *bpf_get_trace_printk_proto(void) |
151 | { | |
152 | /* | |
153 | * this program might be calling bpf_trace_printk, | |
154 | * so allocate per-cpu printk buffers | |
155 | */ | |
156 | trace_printk_init_buffers(); | |
157 | ||
158 | return &bpf_trace_printk_proto; | |
159 | } | |
160 | ||
2541517c AS |
161 | static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id) |
162 | { | |
163 | switch (func_id) { | |
164 | case BPF_FUNC_map_lookup_elem: | |
165 | return &bpf_map_lookup_elem_proto; | |
166 | case BPF_FUNC_map_update_elem: | |
167 | return &bpf_map_update_elem_proto; | |
168 | case BPF_FUNC_map_delete_elem: | |
169 | return &bpf_map_delete_elem_proto; | |
170 | case BPF_FUNC_probe_read: | |
171 | return &bpf_probe_read_proto; | |
d9847d31 AS |
172 | case BPF_FUNC_ktime_get_ns: |
173 | return &bpf_ktime_get_ns_proto; | |
04fd61ab AS |
174 | case BPF_FUNC_tail_call: |
175 | return &bpf_tail_call_proto; | |
ffeedafb AS |
176 | case BPF_FUNC_get_current_pid_tgid: |
177 | return &bpf_get_current_pid_tgid_proto; | |
178 | case BPF_FUNC_get_current_uid_gid: | |
179 | return &bpf_get_current_uid_gid_proto; | |
180 | case BPF_FUNC_get_current_comm: | |
181 | return &bpf_get_current_comm_proto; | |
9c959c86 | 182 | case BPF_FUNC_trace_printk: |
0756ea3e | 183 | return bpf_get_trace_printk_proto(); |
ab1973d3 AS |
184 | case BPF_FUNC_get_smp_processor_id: |
185 | return &bpf_get_smp_processor_id_proto; | |
2541517c AS |
186 | default: |
187 | return NULL; | |
188 | } | |
189 | } | |
190 | ||
191 | /* bpf+kprobe programs can access fields of 'struct pt_regs' */ | |
192 | static bool kprobe_prog_is_valid_access(int off, int size, enum bpf_access_type type) | |
193 | { | |
194 | /* check bounds */ | |
195 | if (off < 0 || off >= sizeof(struct pt_regs)) | |
196 | return false; | |
197 | ||
198 | /* only read is allowed */ | |
199 | if (type != BPF_READ) | |
200 | return false; | |
201 | ||
202 | /* disallow misaligned access */ | |
203 | if (off % size != 0) | |
204 | return false; | |
205 | ||
206 | return true; | |
207 | } | |
208 | ||
209 | static struct bpf_verifier_ops kprobe_prog_ops = { | |
210 | .get_func_proto = kprobe_prog_func_proto, | |
211 | .is_valid_access = kprobe_prog_is_valid_access, | |
212 | }; | |
213 | ||
214 | static struct bpf_prog_type_list kprobe_tl = { | |
215 | .ops = &kprobe_prog_ops, | |
216 | .type = BPF_PROG_TYPE_KPROBE, | |
217 | }; | |
218 | ||
219 | static int __init register_kprobe_prog_ops(void) | |
220 | { | |
221 | bpf_register_prog_type(&kprobe_tl); | |
222 | return 0; | |
223 | } | |
224 | late_initcall(register_kprobe_prog_ops); |