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