xref: /openbsd-src/sys/net/bpf_filter.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: bpf_filter.c,v 1.24 2011/02/13 22:41:10 canacar 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/types.h>
42 #include <sys/time.h>
43 #ifndef _KERNEL
44 #include <stdlib.h>
45 #include <string.h>
46 #include "pcap.h"
47 #else
48 #include <sys/systm.h>
49 #endif
50 
51 #include <sys/endian.h>
52 #ifdef __STRICT_ALIGNMENT
53 #define BPF_ALIGN
54 #endif
55 
56 #ifndef BPF_ALIGN
57 #define EXTRACT_SHORT(p)	((u_int16_t)ntohs(*(u_int16_t *)p))
58 #define EXTRACT_LONG(p)		(ntohl(*(u_int32_t *)p))
59 #else
60 #define EXTRACT_SHORT(p)\
61 	((u_int16_t)\
62 		((u_int16_t)*((u_char *)p+0)<<8|\
63 		 (u_int16_t)*((u_char *)p+1)<<0))
64 #define EXTRACT_LONG(p)\
65 		((u_int32_t)*((u_char *)p+0)<<24|\
66 		 (u_int32_t)*((u_char *)p+1)<<16|\
67 		 (u_int32_t)*((u_char *)p+2)<<8|\
68 		 (u_int32_t)*((u_char *)p+3)<<0)
69 #endif
70 
71 #ifdef _KERNEL
72 #include <sys/mbuf.h>
73 #define MINDEX(len, m, k) \
74 { \
75 	len = m->m_len; \
76 	while (k >= len) { \
77 		k -= len; \
78 		m = m->m_next; \
79 		if (m == 0) \
80 			return 0; \
81 		len = m->m_len; \
82 	} \
83 }
84 
85 extern int bpf_maxbufsize;
86 
87 int	bpf_m_xword(struct mbuf *, u_int32_t, int *);
88 int	bpf_m_xhalf(struct mbuf *, u_int32_t, int *);
89 
90 int
91 bpf_m_xword(m, k, err)
92 	struct mbuf *m;
93 	u_int32_t k;
94 	int *err;
95 {
96 	int len;
97 	u_char *cp, *np;
98 	struct mbuf *m0;
99 
100 	*err = 1;
101 	MINDEX(len, m, k);
102 	cp = mtod(m, u_char *) + k;
103 	if (len >= k + 4) {
104 		*err = 0;
105 		return EXTRACT_LONG(cp);
106 	}
107 	m0 = m->m_next;
108 	if (m0 == 0 || m0->m_len + len - k < 4)
109 		return 0;
110 	*err = 0;
111 	np = mtod(m0, u_char *);
112 	switch (len - k) {
113 
114 	case 1:
115 		return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
116 
117 	case 2:
118 		return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
119 
120 	default:
121 		return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
122 	}
123 }
124 
125 int
126 bpf_m_xhalf(m, k, err)
127 	struct mbuf *m;
128 	u_int32_t k;
129 	int *err;
130 {
131 	int len;
132 	u_char *cp;
133 	struct mbuf *m0;
134 
135 	*err = 1;
136 	MINDEX(len, m, k);
137 	cp = mtod(m, u_char *) + k;
138 	if (len >= k + 2) {
139 		*err = 0;
140 		return EXTRACT_SHORT(cp);
141 	}
142 	m0 = m->m_next;
143 	if (m0 == 0)
144 		return 0;
145 	*err = 0;
146 	return (cp[0] << 8) | mtod(m0, u_char *)[0];
147 }
148 #endif
149 
150 #include <net/bpf.h>
151 
152 /*
153  * Execute the filter program starting at pc on the packet p
154  * wirelen is the length of the original packet
155  * buflen is the amount of data present
156  */
157 u_int
158 bpf_filter(pc, p, wirelen, buflen)
159 	struct bpf_insn *pc;
160 	u_char *p;
161 	u_int wirelen;
162 	u_int buflen;
163 {
164 	u_int32_t A = 0, X = 0;
165 	u_int32_t k;
166 	int32_t mem[BPF_MEMWORDS];
167 
168 	bzero(mem, sizeof(mem));
169 
170 	if (pc == 0)
171 		/*
172 		 * No filter means accept all.
173 		 */
174 		return (u_int)-1;
175 	--pc;
176 	while (1) {
177 		++pc;
178 		switch (pc->code) {
179 
180 		default:
181 #ifdef _KERNEL
182 			return 0;
183 #else
184 			abort();
185 #endif
186 		case BPF_RET|BPF_K:
187 			return (u_int)pc->k;
188 
189 		case BPF_RET|BPF_A:
190 			return (u_int)A;
191 
192 		case BPF_LD|BPF_W|BPF_ABS:
193 			k = pc->k;
194 			if (k + sizeof(int32_t) > buflen) {
195 #ifdef _KERNEL
196 				int merr;
197 
198 				if (buflen != 0)
199 					return 0;
200 				A = bpf_m_xword((struct mbuf *)p, k, &merr);
201 				if (merr != 0)
202 					return 0;
203 				continue;
204 #else
205 				return 0;
206 #endif
207 			}
208 			A = EXTRACT_LONG(&p[k]);
209 			continue;
210 
211 		case BPF_LD|BPF_H|BPF_ABS:
212 			k = pc->k;
213 			if (k + sizeof(int16_t) > buflen) {
214 #ifdef _KERNEL
215 				int merr;
216 
217 				if (buflen != 0)
218 					return 0;
219 				A = bpf_m_xhalf((struct mbuf *)p, k, &merr);
220 				if (merr != 0)
221 					return 0;
222 				continue;
223 #else
224 				return 0;
225 #endif
226 			}
227 			A = EXTRACT_SHORT(&p[k]);
228 			continue;
229 
230 		case BPF_LD|BPF_B|BPF_ABS:
231 			k = pc->k;
232 			if (k >= buflen) {
233 #ifdef _KERNEL
234 				struct mbuf *m;
235 				int len;
236 
237 				if (buflen != 0)
238 					return 0;
239 				m = (struct mbuf *)p;
240 				MINDEX(len, m, k);
241 				A = mtod(m, u_char *)[k];
242 				continue;
243 #else
244 				return 0;
245 #endif
246 			}
247 			A = p[k];
248 			continue;
249 
250 		case BPF_LD|BPF_W|BPF_LEN:
251 			A = wirelen;
252 			continue;
253 
254 		case BPF_LDX|BPF_W|BPF_LEN:
255 			X = wirelen;
256 			continue;
257 
258 		case BPF_LD|BPF_W|BPF_IND:
259 			k = X + pc->k;
260 			if (k + sizeof(int32_t) > buflen) {
261 #ifdef _KERNEL
262 				int merr;
263 
264 				if (buflen != 0)
265 					return 0;
266 				A = bpf_m_xword((struct mbuf *)p, k, &merr);
267 				if (merr != 0)
268 					return 0;
269 				continue;
270 #else
271 				return 0;
272 #endif
273 			}
274 			A = EXTRACT_LONG(&p[k]);
275 			continue;
276 
277 		case BPF_LD|BPF_H|BPF_IND:
278 			k = X + pc->k;
279 			if (k + sizeof(int16_t) > buflen) {
280 #ifdef _KERNEL
281 				int merr;
282 
283 				if (buflen != 0)
284 					return 0;
285 				A = bpf_m_xhalf((struct mbuf *)p, k, &merr);
286 				if (merr != 0)
287 					return 0;
288 				continue;
289 #else
290 				return 0;
291 #endif
292 			}
293 			A = EXTRACT_SHORT(&p[k]);
294 			continue;
295 
296 		case BPF_LD|BPF_B|BPF_IND:
297 			k = X + pc->k;
298 			if (k >= buflen) {
299 #ifdef _KERNEL
300 				struct mbuf *m;
301 				int len;
302 
303 				if (buflen != 0)
304 					return 0;
305 				m = (struct mbuf *)p;
306 				MINDEX(len, m, k);
307 				A = mtod(m, u_char *)[k];
308 				continue;
309 #else
310 				return 0;
311 #endif
312 			}
313 			A = p[k];
314 			continue;
315 
316 		case BPF_LDX|BPF_MSH|BPF_B:
317 			k = pc->k;
318 			if (k >= buflen) {
319 #ifdef _KERNEL
320 				struct mbuf *m;
321 				int len;
322 
323 				if (buflen != 0)
324 					return 0;
325 				m = (struct mbuf *)p;
326 				MINDEX(len, m, k);
327 				X = (mtod(m, u_char *)[k] & 0xf) << 2;
328 				continue;
329 #else
330 				return 0;
331 #endif
332 			}
333 			X = (p[pc->k] & 0xf) << 2;
334 			continue;
335 
336 		case BPF_LD|BPF_IMM:
337 			A = pc->k;
338 			continue;
339 
340 		case BPF_LDX|BPF_IMM:
341 			X = pc->k;
342 			continue;
343 
344 		case BPF_LD|BPF_MEM:
345 			A = mem[pc->k];
346 			continue;
347 
348 		case BPF_LDX|BPF_MEM:
349 			X = mem[pc->k];
350 			continue;
351 
352 		case BPF_ST:
353 			mem[pc->k] = A;
354 			continue;
355 
356 		case BPF_STX:
357 			mem[pc->k] = X;
358 			continue;
359 
360 		case BPF_JMP|BPF_JA:
361 			pc += pc->k;
362 			continue;
363 
364 		case BPF_JMP|BPF_JGT|BPF_K:
365 			pc += (A > pc->k) ? pc->jt : pc->jf;
366 			continue;
367 
368 		case BPF_JMP|BPF_JGE|BPF_K:
369 			pc += (A >= pc->k) ? pc->jt : pc->jf;
370 			continue;
371 
372 		case BPF_JMP|BPF_JEQ|BPF_K:
373 			pc += (A == pc->k) ? pc->jt : pc->jf;
374 			continue;
375 
376 		case BPF_JMP|BPF_JSET|BPF_K:
377 			pc += (A & pc->k) ? pc->jt : pc->jf;
378 			continue;
379 
380 		case BPF_JMP|BPF_JGT|BPF_X:
381 			pc += (A > X) ? pc->jt : pc->jf;
382 			continue;
383 
384 		case BPF_JMP|BPF_JGE|BPF_X:
385 			pc += (A >= X) ? pc->jt : pc->jf;
386 			continue;
387 
388 		case BPF_JMP|BPF_JEQ|BPF_X:
389 			pc += (A == X) ? pc->jt : pc->jf;
390 			continue;
391 
392 		case BPF_JMP|BPF_JSET|BPF_X:
393 			pc += (A & X) ? pc->jt : pc->jf;
394 			continue;
395 
396 		case BPF_ALU|BPF_ADD|BPF_X:
397 			A += X;
398 			continue;
399 
400 		case BPF_ALU|BPF_SUB|BPF_X:
401 			A -= X;
402 			continue;
403 
404 		case BPF_ALU|BPF_MUL|BPF_X:
405 			A *= X;
406 			continue;
407 
408 		case BPF_ALU|BPF_DIV|BPF_X:
409 			if (X == 0)
410 				return 0;
411 			A /= X;
412 			continue;
413 
414 		case BPF_ALU|BPF_AND|BPF_X:
415 			A &= X;
416 			continue;
417 
418 		case BPF_ALU|BPF_OR|BPF_X:
419 			A |= X;
420 			continue;
421 
422 		case BPF_ALU|BPF_LSH|BPF_X:
423 			A <<= X;
424 			continue;
425 
426 		case BPF_ALU|BPF_RSH|BPF_X:
427 			A >>= X;
428 			continue;
429 
430 		case BPF_ALU|BPF_ADD|BPF_K:
431 			A += pc->k;
432 			continue;
433 
434 		case BPF_ALU|BPF_SUB|BPF_K:
435 			A -= pc->k;
436 			continue;
437 
438 		case BPF_ALU|BPF_MUL|BPF_K:
439 			A *= pc->k;
440 			continue;
441 
442 		case BPF_ALU|BPF_DIV|BPF_K:
443 			A /= pc->k;
444 			continue;
445 
446 		case BPF_ALU|BPF_AND|BPF_K:
447 			A &= pc->k;
448 			continue;
449 
450 		case BPF_ALU|BPF_OR|BPF_K:
451 			A |= pc->k;
452 			continue;
453 
454 		case BPF_ALU|BPF_LSH|BPF_K:
455 			A <<= pc->k;
456 			continue;
457 
458 		case BPF_ALU|BPF_RSH|BPF_K:
459 			A >>= pc->k;
460 			continue;
461 
462 		case BPF_ALU|BPF_NEG:
463 			A = -A;
464 			continue;
465 
466 		case BPF_MISC|BPF_TAX:
467 			X = A;
468 			continue;
469 
470 		case BPF_MISC|BPF_TXA:
471 			A = X;
472 			continue;
473 		}
474 	}
475 }
476 
477 #ifdef _KERNEL
478 /*
479  * Return true if the 'fcode' is a valid filter program.
480  * The constraints are that each jump be forward and to a valid
481  * code and memory operations use valid addresses.  The code
482  * must terminate with either an accept or reject.
483  *
484  * The kernel needs to be able to verify an application's filter code.
485  * Otherwise, a bogus program could easily crash the system.
486  */
487 int
488 bpf_validate(f, len)
489 	struct bpf_insn *f;
490 	int len;
491 {
492 	u_int i, from;
493 	struct bpf_insn *p;
494 
495 	if (len < 1 || len > BPF_MAXINSNS)
496 		return 0;
497 
498 	for (i = 0; i < len; ++i) {
499 		p = &f[i];
500 		switch (BPF_CLASS(p->code)) {
501 		/*
502 		 * Check that memory operations use valid addresses.
503 		 */
504 		case BPF_LD:
505 		case BPF_LDX:
506 			switch (BPF_MODE(p->code)) {
507 			case BPF_IMM:
508 				break;
509 			case BPF_ABS:
510 			case BPF_IND:
511 			case BPF_MSH:
512 				/*
513 				 * More strict check with actual packet length
514 				 * is done runtime.
515 				 */
516 				if (p->k >= bpf_maxbufsize)
517 					return 0;
518 				break;
519 			case BPF_MEM:
520 				if (p->k >= BPF_MEMWORDS)
521 					return 0;
522 				break;
523 			case BPF_LEN:
524 				break;
525 			default:
526 				return 0;
527 			}
528 			break;
529 		case BPF_ST:
530 		case BPF_STX:
531 			if (p->k >= BPF_MEMWORDS)
532 				return 0;
533 			break;
534 		case BPF_ALU:
535 			switch (BPF_OP(p->code)) {
536 			case BPF_ADD:
537 			case BPF_SUB:
538 			case BPF_MUL:
539 			case BPF_OR:
540 			case BPF_AND:
541 			case BPF_LSH:
542 			case BPF_RSH:
543 			case BPF_NEG:
544 				break;
545 			case BPF_DIV:
546 				/*
547 				 * Check for constant division by 0.
548 				 */
549 				if (BPF_SRC(p->code) == BPF_K && p->k == 0)
550 					return 0;
551 				break;
552 			default:
553 				return 0;
554 			}
555 			break;
556 		case BPF_JMP:
557 			/*
558 			 * Check that jumps are forward, and within
559 			 * the code block.
560 			 */
561 			from = i + 1;
562 			switch (BPF_OP(p->code)) {
563 			case BPF_JA:
564 				if (from + p->k < from || from + p->k >= len)
565 					return 0;
566 				break;
567 			case BPF_JEQ:
568 			case BPF_JGT:
569 			case BPF_JGE:
570 			case BPF_JSET:
571 				if (from + p->jt >= len || from + p->jf >= len)
572 					return 0;
573 				break;
574 			default:
575 				return 0;
576 			}
577 			break;
578 		case BPF_RET:
579 			break;
580 		case BPF_MISC:
581 			break;
582 		default:
583 			return 0;
584 		}
585 
586 	}
587 	return BPF_CLASS(f[len - 1].code) == BPF_RET;
588 }
589 #endif
590