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