Line data Source code
1 : /* $OpenBSD: bpf_filter.c,v 1.33 2017/09/08 05:36:53 deraadt 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
77 0 : bpf_mem_ldw(const void *mem, u_int32_t k, int *err)
78 : {
79 0 : const struct bpf_mem *bm = mem;
80 : u_int32_t v;
81 :
82 0 : *err = 1;
83 :
84 0 : if (k + sizeof(v) > bm->len)
85 0 : return (0);
86 :
87 0 : memcpy(&v, bm->pkt + k, sizeof(v));
88 :
89 0 : *err = 0;
90 0 : return ntohl(v);
91 0 : }
92 :
93 : Static u_int32_t
94 0 : bpf_mem_ldh(const void *mem, u_int32_t k, int *err)
95 : {
96 0 : const struct bpf_mem *bm = mem;
97 : u_int16_t v;
98 :
99 0 : *err = 1;
100 :
101 0 : if (k + sizeof(v) > bm->len)
102 0 : return (0);
103 :
104 0 : memcpy(&v, bm->pkt + k, sizeof(v));
105 :
106 0 : *err = 0;
107 0 : return ntohs(v);
108 0 : }
109 :
110 : Static u_int32_t
111 0 : bpf_mem_ldb(const void *mem, u_int32_t k, int *err)
112 : {
113 0 : const struct bpf_mem *bm = mem;
114 :
115 0 : *err = 1;
116 :
117 0 : if (k >= bm->len)
118 0 : return (0);
119 :
120 0 : *err = 0;
121 0 : return bm->pkt[k];
122 0 : }
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
130 0 : bpf_filter(const struct bpf_insn *pc, const u_char *pkt,
131 : u_int wirelen, u_int buflen)
132 : {
133 0 : struct bpf_mem bm;
134 :
135 0 : bm.pkt = pkt;
136 0 : bm.len = buflen;
137 :
138 0 : return _bpf_filter(pc, &bpf_mem_ops, &bm, wirelen);
139 0 : }
140 :
141 : u_int
142 0 : _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 0 : int32_t mem[BPF_MEMWORDS];
148 0 : int err;
149 :
150 0 : if (pc == NULL) {
151 : /*
152 : * No filter means accept all.
153 : */
154 0 : return (u_int)-1;
155 : }
156 :
157 0 : memset(mem, 0, sizeof(mem));
158 :
159 0 : --pc;
160 0 : while (1) {
161 0 : ++pc;
162 0 : switch (pc->code) {
163 :
164 : default:
165 : #ifdef _KERNEL
166 0 : return 0;
167 : #else
168 : abort();
169 : #endif
170 : case BPF_RET|BPF_K:
171 0 : return (u_int)pc->k;
172 :
173 : case BPF_RET|BPF_A:
174 0 : return (u_int)A;
175 :
176 : case BPF_LD|BPF_W|BPF_ABS:
177 0 : A = ops->ldw(pkt, pc->k, &err);
178 0 : if (err != 0)
179 0 : return 0;
180 0 : continue;
181 :
182 : case BPF_LD|BPF_H|BPF_ABS:
183 0 : A = ops->ldh(pkt, pc->k, &err);
184 0 : if (err != 0)
185 0 : return 0;
186 0 : continue;
187 :
188 : case BPF_LD|BPF_B|BPF_ABS:
189 0 : A = ops->ldb(pkt, pc->k, &err);
190 0 : if (err != 0)
191 0 : return 0;
192 0 : continue;
193 :
194 : case BPF_LD|BPF_W|BPF_LEN:
195 : A = wirelen;
196 0 : continue;
197 :
198 : case BPF_LDX|BPF_W|BPF_LEN:
199 : X = wirelen;
200 0 : continue;
201 :
202 : case BPF_LD|BPF_W|BPF_IND:
203 0 : k = X + pc->k;
204 0 : A = ops->ldw(pkt, k, &err);
205 0 : if (err != 0)
206 0 : return 0;
207 0 : continue;
208 :
209 : case BPF_LD|BPF_H|BPF_IND:
210 0 : k = X + pc->k;
211 0 : A = ops->ldh(pkt, k, &err);
212 0 : if (err != 0)
213 0 : return 0;
214 0 : continue;
215 :
216 : case BPF_LD|BPF_B|BPF_IND:
217 0 : k = X + pc->k;
218 0 : A = ops->ldb(pkt, k, &err);
219 0 : if (err != 0)
220 0 : return 0;
221 0 : continue;
222 :
223 : case BPF_LDX|BPF_MSH|BPF_B:
224 0 : X = ops->ldb(pkt, pc->k, &err);
225 0 : if (err != 0)
226 0 : return 0;
227 0 : X &= 0xf;
228 0 : X <<= 2;
229 0 : continue;
230 :
231 : case BPF_LD|BPF_IMM:
232 0 : A = pc->k;
233 0 : continue;
234 :
235 : case BPF_LDX|BPF_IMM:
236 0 : X = pc->k;
237 0 : continue;
238 :
239 : case BPF_LD|BPF_MEM:
240 0 : A = mem[pc->k];
241 0 : continue;
242 :
243 : case BPF_LDX|BPF_MEM:
244 0 : X = mem[pc->k];
245 0 : continue;
246 :
247 : case BPF_ST:
248 0 : mem[pc->k] = A;
249 0 : continue;
250 :
251 : case BPF_STX:
252 0 : mem[pc->k] = X;
253 0 : continue;
254 :
255 : case BPF_JMP|BPF_JA:
256 0 : pc += pc->k;
257 0 : continue;
258 :
259 : case BPF_JMP|BPF_JGT|BPF_K:
260 0 : pc += (A > pc->k) ? pc->jt : pc->jf;
261 0 : continue;
262 :
263 : case BPF_JMP|BPF_JGE|BPF_K:
264 0 : pc += (A >= pc->k) ? pc->jt : pc->jf;
265 0 : continue;
266 :
267 : case BPF_JMP|BPF_JEQ|BPF_K:
268 0 : pc += (A == pc->k) ? pc->jt : pc->jf;
269 0 : continue;
270 :
271 : case BPF_JMP|BPF_JSET|BPF_K:
272 0 : pc += (A & pc->k) ? pc->jt : pc->jf;
273 0 : continue;
274 :
275 : case BPF_JMP|BPF_JGT|BPF_X:
276 0 : pc += (A > X) ? pc->jt : pc->jf;
277 0 : continue;
278 :
279 : case BPF_JMP|BPF_JGE|BPF_X:
280 0 : pc += (A >= X) ? pc->jt : pc->jf;
281 0 : continue;
282 :
283 : case BPF_JMP|BPF_JEQ|BPF_X:
284 0 : pc += (A == X) ? pc->jt : pc->jf;
285 0 : continue;
286 :
287 : case BPF_JMP|BPF_JSET|BPF_X:
288 0 : pc += (A & X) ? pc->jt : pc->jf;
289 0 : continue;
290 :
291 : case BPF_ALU|BPF_ADD|BPF_X:
292 0 : A += X;
293 0 : continue;
294 :
295 : case BPF_ALU|BPF_SUB|BPF_X:
296 0 : A -= X;
297 0 : continue;
298 :
299 : case BPF_ALU|BPF_MUL|BPF_X:
300 0 : A *= X;
301 0 : continue;
302 :
303 : case BPF_ALU|BPF_DIV|BPF_X:
304 0 : if (X == 0)
305 0 : return 0;
306 0 : A /= X;
307 0 : continue;
308 :
309 : case BPF_ALU|BPF_AND|BPF_X:
310 0 : A &= X;
311 0 : continue;
312 :
313 : case BPF_ALU|BPF_OR|BPF_X:
314 0 : A |= X;
315 0 : continue;
316 :
317 : case BPF_ALU|BPF_LSH|BPF_X:
318 0 : A <<= X;
319 0 : continue;
320 :
321 : case BPF_ALU|BPF_RSH|BPF_X:
322 0 : A >>= X;
323 0 : continue;
324 :
325 : case BPF_ALU|BPF_ADD|BPF_K:
326 0 : A += pc->k;
327 0 : continue;
328 :
329 : case BPF_ALU|BPF_SUB|BPF_K:
330 0 : A -= pc->k;
331 0 : continue;
332 :
333 : case BPF_ALU|BPF_MUL|BPF_K:
334 0 : A *= pc->k;
335 0 : continue;
336 :
337 : case BPF_ALU|BPF_DIV|BPF_K:
338 0 : A /= pc->k;
339 0 : continue;
340 :
341 : case BPF_ALU|BPF_AND|BPF_K:
342 0 : A &= pc->k;
343 0 : continue;
344 :
345 : case BPF_ALU|BPF_OR|BPF_K:
346 0 : A |= pc->k;
347 0 : continue;
348 :
349 : case BPF_ALU|BPF_LSH|BPF_K:
350 0 : A <<= pc->k;
351 0 : continue;
352 :
353 : case BPF_ALU|BPF_RSH|BPF_K:
354 0 : A >>= pc->k;
355 0 : continue;
356 :
357 : case BPF_ALU|BPF_NEG:
358 0 : A = -A;
359 0 : continue;
360 :
361 : case BPF_MISC|BPF_TAX:
362 : X = A;
363 0 : continue;
364 :
365 : case BPF_MISC|BPF_TXA:
366 : A = X;
367 0 : continue;
368 : }
369 : }
370 0 : }
371 :
372 : #ifdef _KERNEL
373 : /*
374 : * Return true if the 'fcode' is a valid filter program.
375 : * The constraints are that each jump be forward and to a valid
376 : * code and memory operations use valid addresses. The code
377 : * must terminate with either an accept or reject.
378 : *
379 : * The kernel needs to be able to verify an application's filter code.
380 : * Otherwise, a bogus program could easily crash the system.
381 : */
382 : int
383 0 : bpf_validate(struct bpf_insn *f, int len)
384 : {
385 : u_int i, from;
386 : struct bpf_insn *p;
387 :
388 0 : if (len < 1 || len > BPF_MAXINSNS)
389 0 : return 0;
390 :
391 0 : for (i = 0; i < len; ++i) {
392 0 : p = &f[i];
393 0 : switch (BPF_CLASS(p->code)) {
394 : /*
395 : * Check that memory operations use valid addresses.
396 : */
397 : case BPF_LD:
398 : case BPF_LDX:
399 0 : switch (BPF_MODE(p->code)) {
400 : case BPF_IMM:
401 : break;
402 : case BPF_ABS:
403 : case BPF_IND:
404 : case BPF_MSH:
405 : /*
406 : * More strict check with actual packet length
407 : * is done runtime.
408 : */
409 0 : if (p->k >= bpf_maxbufsize)
410 0 : return 0;
411 : break;
412 : case BPF_MEM:
413 0 : if (p->k >= BPF_MEMWORDS)
414 0 : return 0;
415 : break;
416 : case BPF_LEN:
417 : break;
418 : default:
419 0 : return 0;
420 : }
421 : break;
422 : case BPF_ST:
423 : case BPF_STX:
424 0 : if (p->k >= BPF_MEMWORDS)
425 0 : return 0;
426 : break;
427 : case BPF_ALU:
428 0 : switch (BPF_OP(p->code)) {
429 : case BPF_ADD:
430 : case BPF_SUB:
431 : case BPF_MUL:
432 : case BPF_OR:
433 : case BPF_AND:
434 : case BPF_LSH:
435 : case BPF_RSH:
436 : case BPF_NEG:
437 : break;
438 : case BPF_DIV:
439 : /*
440 : * Check for constant division by 0.
441 : */
442 0 : if (BPF_SRC(p->code) == BPF_K && p->k == 0)
443 0 : return 0;
444 : break;
445 : default:
446 0 : return 0;
447 : }
448 : break;
449 : case BPF_JMP:
450 : /*
451 : * Check that jumps are forward, and within
452 : * the code block.
453 : */
454 0 : from = i + 1;
455 0 : switch (BPF_OP(p->code)) {
456 : case BPF_JA:
457 0 : if (from + p->k < from || from + p->k >= len)
458 0 : return 0;
459 : break;
460 : case BPF_JEQ:
461 : case BPF_JGT:
462 : case BPF_JGE:
463 : case BPF_JSET:
464 0 : if (from + p->jt >= len || from + p->jf >= len)
465 0 : return 0;
466 : break;
467 : default:
468 0 : return 0;
469 : }
470 : break;
471 : case BPF_RET:
472 : break;
473 : case BPF_MISC:
474 : break;
475 : default:
476 : return 0;
477 : }
478 :
479 : }
480 0 : return BPF_CLASS(f[len - 1].code) == BPF_RET;
481 0 : }
482 : #endif
|