1 /* $OpenBSD: bpf_filter.c,v 1.34 2020/08/03 03:21:24 dlg Exp $ */
2 /* $NetBSD: bpf_filter.c,v 1.12 1996/02/13 22:00:00 christos Exp $ */
3
4 /*
5 * Copyright (c) 1990, 1991, 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from the Stanford/CMU enet packet filter,
9 * (net/enet.c) distributed as part of 4.3BSD, and code contributed
10 * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
11 * Berkeley Laboratory.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93
38 */
39
40 #include <sys/param.h>
41 #include <sys/time.h>
42 #ifndef _KERNEL
43 #include <stdlib.h>
44 #include <string.h>
45 #include "pcap.h"
46 #else
47 #include <sys/systm.h>
48 #endif
49
50 #include <sys/endian.h>
51
52 #ifdef _KERNEL
53 extern int bpf_maxbufsize;
54 #define Static
55 #else /* _KERNEL */
56 #define Static static
57 #endif /* _KERNEL */
58
59 #include <net/bpf.h>
60
61 struct bpf_mem {
62 const u_char *pkt;
63 u_int len;
64 };
65
66 Static u_int32_t bpf_mem_ldw(const void *, u_int32_t, int *);
67 Static u_int32_t bpf_mem_ldh(const void *, u_int32_t, int *);
68 Static u_int32_t bpf_mem_ldb(const void *, u_int32_t, int *);
69
70 static const struct bpf_ops bpf_mem_ops = {
71 bpf_mem_ldw,
72 bpf_mem_ldh,
73 bpf_mem_ldb,
74 };
75
76 Static u_int32_t
bpf_mem_ldw(const void * mem,u_int32_t k,int * err)77 bpf_mem_ldw(const void *mem, u_int32_t k, int *err)
78 {
79 const struct bpf_mem *bm = mem;
80 u_int32_t v;
81
82 *err = 1;
83
84 if (k + sizeof(v) > bm->len)
85 return (0);
86
87 memcpy(&v, bm->pkt + k, sizeof(v));
88
89 *err = 0;
90 return ntohl(v);
91 }
92
93 Static u_int32_t
bpf_mem_ldh(const void * mem,u_int32_t k,int * err)94 bpf_mem_ldh(const void *mem, u_int32_t k, int *err)
95 {
96 const struct bpf_mem *bm = mem;
97 u_int16_t v;
98
99 *err = 1;
100
101 if (k + sizeof(v) > bm->len)
102 return (0);
103
104 memcpy(&v, bm->pkt + k, sizeof(v));
105
106 *err = 0;
107 return ntohs(v);
108 }
109
110 Static u_int32_t
bpf_mem_ldb(const void * mem,u_int32_t k,int * err)111 bpf_mem_ldb(const void *mem, u_int32_t k, int *err)
112 {
113 const struct bpf_mem *bm = mem;
114
115 *err = 1;
116
117 if (k >= bm->len)
118 return (0);
119
120 *err = 0;
121 return bm->pkt[k];
122 }
123
124 /*
125 * Execute the filter program starting at pc on the packet p
126 * wirelen is the length of the original packet
127 * buflen is the amount of data present
128 */
129 u_int
bpf_filter(const struct bpf_insn * pc,const u_char * pkt,u_int wirelen,u_int buflen)130 bpf_filter(const struct bpf_insn *pc, const u_char *pkt,
131 u_int wirelen, u_int buflen)
132 {
133 struct bpf_mem bm;
134
135 bm.pkt = pkt;
136 bm.len = buflen;
137
138 return _bpf_filter(pc, &bpf_mem_ops, &bm, wirelen);
139 }
140
141 u_int
_bpf_filter(const struct bpf_insn * pc,const struct bpf_ops * ops,const void * pkt,u_int wirelen)142 _bpf_filter(const struct bpf_insn *pc, const struct bpf_ops *ops,
143 const void *pkt, u_int wirelen)
144 {
145 u_int32_t A = 0, X = 0;
146 u_int32_t k;
147 int32_t mem[BPF_MEMWORDS];
148 int err;
149
150 if (pc == NULL) {
151 /*
152 * No filter means accept all.
153 */
154 return (u_int)-1;
155 }
156
157 memset(mem, 0, sizeof(mem));
158
159 --pc;
160 while (1) {
161 ++pc;
162 switch (pc->code) {
163
164 default:
165 #ifdef _KERNEL
166 return 0;
167 #else
168 abort();
169 #endif
170 case BPF_RET|BPF_K:
171 return (u_int)pc->k;
172
173 case BPF_RET|BPF_A:
174 return (u_int)A;
175
176 case BPF_LD|BPF_W|BPF_ABS:
177 A = ops->ldw(pkt, pc->k, &err);
178 if (err != 0)
179 return 0;
180 continue;
181
182 case BPF_LD|BPF_H|BPF_ABS:
183 A = ops->ldh(pkt, pc->k, &err);
184 if (err != 0)
185 return 0;
186 continue;
187
188 case BPF_LD|BPF_B|BPF_ABS:
189 A = ops->ldb(pkt, pc->k, &err);
190 if (err != 0)
191 return 0;
192 continue;
193
194 case BPF_LD|BPF_W|BPF_LEN:
195 A = wirelen;
196 continue;
197
198 case BPF_LDX|BPF_W|BPF_LEN:
199 X = wirelen;
200 continue;
201
202 case BPF_LD|BPF_W|BPF_RND:
203 A = arc4random();
204 continue;
205
206 case BPF_LD|BPF_W|BPF_IND:
207 k = X + pc->k;
208 A = ops->ldw(pkt, k, &err);
209 if (err != 0)
210 return 0;
211 continue;
212
213 case BPF_LD|BPF_H|BPF_IND:
214 k = X + pc->k;
215 A = ops->ldh(pkt, k, &err);
216 if (err != 0)
217 return 0;
218 continue;
219
220 case BPF_LD|BPF_B|BPF_IND:
221 k = X + pc->k;
222 A = ops->ldb(pkt, k, &err);
223 if (err != 0)
224 return 0;
225 continue;
226
227 case BPF_LDX|BPF_MSH|BPF_B:
228 X = ops->ldb(pkt, pc->k, &err);
229 if (err != 0)
230 return 0;
231 X &= 0xf;
232 X <<= 2;
233 continue;
234
235 case BPF_LD|BPF_IMM:
236 A = pc->k;
237 continue;
238
239 case BPF_LDX|BPF_IMM:
240 X = pc->k;
241 continue;
242
243 case BPF_LD|BPF_MEM:
244 A = mem[pc->k];
245 continue;
246
247 case BPF_LDX|BPF_MEM:
248 X = mem[pc->k];
249 continue;
250
251 case BPF_ST:
252 mem[pc->k] = A;
253 continue;
254
255 case BPF_STX:
256 mem[pc->k] = X;
257 continue;
258
259 case BPF_JMP|BPF_JA:
260 pc += pc->k;
261 continue;
262
263 case BPF_JMP|BPF_JGT|BPF_K:
264 pc += (A > pc->k) ? pc->jt : pc->jf;
265 continue;
266
267 case BPF_JMP|BPF_JGE|BPF_K:
268 pc += (A >= pc->k) ? pc->jt : pc->jf;
269 continue;
270
271 case BPF_JMP|BPF_JEQ|BPF_K:
272 pc += (A == pc->k) ? pc->jt : pc->jf;
273 continue;
274
275 case BPF_JMP|BPF_JSET|BPF_K:
276 pc += (A & pc->k) ? pc->jt : pc->jf;
277 continue;
278
279 case BPF_JMP|BPF_JGT|BPF_X:
280 pc += (A > X) ? pc->jt : pc->jf;
281 continue;
282
283 case BPF_JMP|BPF_JGE|BPF_X:
284 pc += (A >= X) ? pc->jt : pc->jf;
285 continue;
286
287 case BPF_JMP|BPF_JEQ|BPF_X:
288 pc += (A == X) ? pc->jt : pc->jf;
289 continue;
290
291 case BPF_JMP|BPF_JSET|BPF_X:
292 pc += (A & X) ? pc->jt : pc->jf;
293 continue;
294
295 case BPF_ALU|BPF_ADD|BPF_X:
296 A += X;
297 continue;
298
299 case BPF_ALU|BPF_SUB|BPF_X:
300 A -= X;
301 continue;
302
303 case BPF_ALU|BPF_MUL|BPF_X:
304 A *= X;
305 continue;
306
307 case BPF_ALU|BPF_DIV|BPF_X:
308 if (X == 0)
309 return 0;
310 A /= X;
311 continue;
312
313 case BPF_ALU|BPF_AND|BPF_X:
314 A &= X;
315 continue;
316
317 case BPF_ALU|BPF_OR|BPF_X:
318 A |= X;
319 continue;
320
321 case BPF_ALU|BPF_LSH|BPF_X:
322 A <<= X;
323 continue;
324
325 case BPF_ALU|BPF_RSH|BPF_X:
326 A >>= X;
327 continue;
328
329 case BPF_ALU|BPF_ADD|BPF_K:
330 A += pc->k;
331 continue;
332
333 case BPF_ALU|BPF_SUB|BPF_K:
334 A -= pc->k;
335 continue;
336
337 case BPF_ALU|BPF_MUL|BPF_K:
338 A *= pc->k;
339 continue;
340
341 case BPF_ALU|BPF_DIV|BPF_K:
342 A /= pc->k;
343 continue;
344
345 case BPF_ALU|BPF_AND|BPF_K:
346 A &= pc->k;
347 continue;
348
349 case BPF_ALU|BPF_OR|BPF_K:
350 A |= pc->k;
351 continue;
352
353 case BPF_ALU|BPF_LSH|BPF_K:
354 A <<= pc->k;
355 continue;
356
357 case BPF_ALU|BPF_RSH|BPF_K:
358 A >>= pc->k;
359 continue;
360
361 case BPF_ALU|BPF_NEG:
362 A = -A;
363 continue;
364
365 case BPF_MISC|BPF_TAX:
366 X = A;
367 continue;
368
369 case BPF_MISC|BPF_TXA:
370 A = X;
371 continue;
372 }
373 }
374 }
375
376 #ifdef _KERNEL
377 /*
378 * Return true if the 'fcode' is a valid filter program.
379 * The constraints are that each jump be forward and to a valid
380 * code and memory operations use valid addresses. The code
381 * must terminate with either an accept or reject.
382 *
383 * The kernel needs to be able to verify an application's filter code.
384 * Otherwise, a bogus program could easily crash the system.
385 */
386 int
bpf_validate(struct bpf_insn * f,int len)387 bpf_validate(struct bpf_insn *f, int len)
388 {
389 u_int i, from;
390 struct bpf_insn *p;
391
392 if (len < 1 || len > BPF_MAXINSNS)
393 return 0;
394
395 for (i = 0; i < len; ++i) {
396 p = &f[i];
397 switch (BPF_CLASS(p->code)) {
398 /*
399 * Check that memory operations use valid addresses.
400 */
401 case BPF_LD:
402 case BPF_LDX:
403 switch (BPF_MODE(p->code)) {
404 case BPF_IMM:
405 break;
406 case BPF_ABS:
407 case BPF_IND:
408 case BPF_MSH:
409 /*
410 * More strict check with actual packet length
411 * is done runtime.
412 */
413 if (p->k >= bpf_maxbufsize)
414 return 0;
415 break;
416 case BPF_MEM:
417 if (p->k >= BPF_MEMWORDS)
418 return 0;
419 break;
420 case BPF_LEN:
421 case BPF_RND:
422 break;
423 default:
424 return 0;
425 }
426 break;
427 case BPF_ST:
428 case BPF_STX:
429 if (p->k >= BPF_MEMWORDS)
430 return 0;
431 break;
432 case BPF_ALU:
433 switch (BPF_OP(p->code)) {
434 case BPF_ADD:
435 case BPF_SUB:
436 case BPF_MUL:
437 case BPF_OR:
438 case BPF_AND:
439 case BPF_LSH:
440 case BPF_RSH:
441 case BPF_NEG:
442 break;
443 case BPF_DIV:
444 /*
445 * Check for constant division by 0.
446 */
447 if (BPF_SRC(p->code) == BPF_K && p->k == 0)
448 return 0;
449 break;
450 default:
451 return 0;
452 }
453 break;
454 case BPF_JMP:
455 /*
456 * Check that jumps are forward, and within
457 * the code block.
458 */
459 from = i + 1;
460 switch (BPF_OP(p->code)) {
461 case BPF_JA:
462 if (from + p->k < from || from + p->k >= len)
463 return 0;
464 break;
465 case BPF_JEQ:
466 case BPF_JGT:
467 case BPF_JGE:
468 case BPF_JSET:
469 if (from + p->jt >= len || from + p->jf >= len)
470 return 0;
471 break;
472 default:
473 return 0;
474 }
475 break;
476 case BPF_RET:
477 break;
478 case BPF_MISC:
479 break;
480 default:
481 return 0;
482 }
483
484 }
485 return BPF_CLASS(f[len - 1].code) == BPF_RET;
486 }
487 #endif
488