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