bpf_filter.c revision 17683
1/*-
2 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from the Stanford/CMU enet packet filter,
6 * (net/enet.c) distributed as part of 4.3BSD, and code contributed
7 * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
8 * Berkeley Laboratory.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	@(#)bpf.c	7.5 (Berkeley) 7/15/91
39 *
40 * static char rcsid[] =
41 * "$Header: bpf_filter.c,v 1.29 96/06/23 13:44:02 leres Exp $";
42 */
43#if !(defined(lint) || defined(KERNEL))
44static char rcsid[] =
45    "@(#) $Header: bpf_filter.c,v 1.29 96/06/23 13:44:02 leres Exp $ (LBL)";
46#endif
47
48#include <sys/param.h>
49#include <sys/types.h>
50#include <sys/time.h>
51#include <net/bpf.h>
52
53#ifndef KERNEL
54#include <stdlib.h>
55#endif
56
57#define int32 bpf_int32
58#define u_int32 bpf_u_int32
59
60#ifndef LBL_ALIGN
61#if defined(sparc) || defined(mips) || defined(ibm032) || \
62    defined(__alpha) || defined(__hpux)
63#define LBL_ALIGN
64#endif
65#endif
66
67#ifndef LBL_ALIGN
68#include <netinet/in.h>
69
70#define EXTRACT_SHORT(p)	((u_short)ntohs(*(u_short *)p))
71#define EXTRACT_LONG(p)		(ntohl(*(u_int32 *)p))
72#else
73#define EXTRACT_SHORT(p)\
74	((u_short)\
75		((u_short)*((u_char *)p+0)<<8|\
76		 (u_short)*((u_char *)p+1)<<0))
77#define EXTRACT_LONG(p)\
78		((u_int32)*((u_char *)p+0)<<24|\
79		 (u_int32)*((u_char *)p+1)<<16|\
80		 (u_int32)*((u_char *)p+2)<<8|\
81		 (u_int32)*((u_char *)p+3)<<0)
82#endif
83
84#ifdef KERNEL
85#include <sys/mbuf.h>
86#define MINDEX(len, m, k) \
87{ \
88	len = m->m_len; \
89	while (k >= len) { \
90		k -= len; \
91		m = m->m_next; \
92		if (m == 0) \
93			return 0; \
94		len = m->m_len; \
95	} \
96}
97
98static int
99m_xword(m, k, err)
100	register struct mbuf *m;
101	register int k, *err;
102{
103	register int len;
104	register u_char *cp, *np;
105	register struct mbuf *m0;
106
107	MINDEX(len, m, k);
108	cp = mtod(m, u_char *) + k;
109	if (len - k >= 4) {
110		*err = 0;
111		return EXTRACT_LONG(cp);
112	}
113	m0 = m->m_next;
114	if (m0 == 0 || m0->m_len + len - k < 4)
115		goto bad;
116	*err = 0;
117	np = mtod(m0, u_char *);
118	switch (len - k) {
119
120	case 1:
121		return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
122
123	case 2:
124		return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
125
126	default:
127		return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
128	}
129    bad:
130	*err = 1;
131	return 0;
132}
133
134static int
135m_xhalf(m, k, err)
136	register struct mbuf *m;
137	register int k, *err;
138{
139	register int len;
140	register u_char *cp;
141	register struct mbuf *m0;
142
143	MINDEX(len, m, k);
144	cp = mtod(m, u_char *) + k;
145	if (len - k >= 2) {
146		*err = 0;
147		return EXTRACT_SHORT(cp);
148	}
149	m0 = m->m_next;
150	if (m0 == 0)
151		goto bad;
152	*err = 0;
153	return (cp[0] << 8) | mtod(m0, u_char *)[0];
154 bad:
155	*err = 1;
156	return 0;
157}
158#endif
159
160/*
161 * Execute the filter program starting at pc on the packet p
162 * wirelen is the length of the original packet
163 * buflen is the amount of data present
164 */
165u_int
166bpf_filter(pc, p, wirelen, buflen)
167	register struct bpf_insn *pc;
168	register u_char *p;
169	u_int wirelen;
170	register u_int buflen;
171{
172	register u_int32 A, X;
173	register int k;
174	int32 mem[BPF_MEMWORDS];
175
176	if (pc == 0)
177		/*
178		 * No filter means accept all.
179		 */
180		return (u_int)-1;
181	A = 0;
182	X = 0;
183	--pc;
184	while (1) {
185		++pc;
186		switch (pc->code) {
187
188		default:
189#ifdef KERNEL
190			return 0;
191#else
192			abort();
193#endif
194		case BPF_RET|BPF_K:
195			return (u_int)pc->k;
196
197		case BPF_RET|BPF_A:
198			return (u_int)A;
199
200		case BPF_LD|BPF_W|BPF_ABS:
201			k = pc->k;
202			if (k + sizeof(int32) > buflen) {
203#ifdef KERNEL
204				int merr;
205
206				if (buflen != 0)
207					return 0;
208				A = m_xword((struct mbuf *)p, k, &merr);
209				if (merr != 0)
210					return 0;
211				continue;
212#else
213				return 0;
214#endif
215			}
216			A = EXTRACT_LONG(&p[k]);
217			continue;
218
219		case BPF_LD|BPF_H|BPF_ABS:
220			k = pc->k;
221			if (k + sizeof(short) > buflen) {
222#ifdef KERNEL
223				int merr;
224
225				if (buflen != 0)
226					return 0;
227				A = m_xhalf((struct mbuf *)p, k, &merr);
228				continue;
229#else
230				return 0;
231#endif
232			}
233			A = EXTRACT_SHORT(&p[k]);
234			continue;
235
236		case BPF_LD|BPF_B|BPF_ABS:
237			k = pc->k;
238			if (k >= buflen) {
239#ifdef KERNEL
240				register struct mbuf *m;
241				register int len;
242
243				if (buflen != 0)
244					return 0;
245				m = (struct mbuf *)p;
246				MINDEX(len, m, k);
247				A = mtod(m, u_char *)[k];
248				continue;
249#else
250				return 0;
251#endif
252			}
253			A = p[k];
254			continue;
255
256		case BPF_LD|BPF_W|BPF_LEN:
257			A = wirelen;
258			continue;
259
260		case BPF_LDX|BPF_W|BPF_LEN:
261			X = wirelen;
262			continue;
263
264		case BPF_LD|BPF_W|BPF_IND:
265			k = X + pc->k;
266			if (k + sizeof(int32) > buflen) {
267#ifdef KERNEL
268				int merr;
269
270				if (buflen != 0)
271					return 0;
272				A = m_xword((struct mbuf *)p, k, &merr);
273				if (merr != 0)
274					return 0;
275				continue;
276#else
277				return 0;
278#endif
279			}
280			A = EXTRACT_LONG(&p[k]);
281			continue;
282
283		case BPF_LD|BPF_H|BPF_IND:
284			k = X + pc->k;
285			if (k + sizeof(short) > buflen) {
286#ifdef KERNEL
287				int merr;
288
289				if (buflen != 0)
290					return 0;
291				A = m_xhalf((struct mbuf *)p, k, &merr);
292				if (merr != 0)
293					return 0;
294				continue;
295#else
296				return 0;
297#endif
298			}
299			A = EXTRACT_SHORT(&p[k]);
300			continue;
301
302		case BPF_LD|BPF_B|BPF_IND:
303			k = X + pc->k;
304			if (k >= buflen) {
305#ifdef KERNEL
306				register struct mbuf *m;
307				register int len;
308
309				if (buflen != 0)
310					return 0;
311				m = (struct mbuf *)p;
312				MINDEX(len, m, k);
313				A = mtod(m, u_char *)[k];
314				continue;
315#else
316				return 0;
317#endif
318			}
319			A = p[k];
320			continue;
321
322		case BPF_LDX|BPF_MSH|BPF_B:
323			k = pc->k;
324			if (k >= buflen) {
325#ifdef KERNEL
326				register struct mbuf *m;
327				register int len;
328
329				if (buflen != 0)
330					return 0;
331				m = (struct mbuf *)p;
332				MINDEX(len, m, k);
333				X = (mtod(m, char *)[k] & 0xf) << 2;
334				continue;
335#else
336				return 0;
337#endif
338			}
339			X = (p[pc->k] & 0xf) << 2;
340			continue;
341
342		case BPF_LD|BPF_IMM:
343			A = pc->k;
344			continue;
345
346		case BPF_LDX|BPF_IMM:
347			X = pc->k;
348			continue;
349
350		case BPF_LD|BPF_MEM:
351			A = mem[pc->k];
352			continue;
353
354		case BPF_LDX|BPF_MEM:
355			X = mem[pc->k];
356			continue;
357
358		case BPF_ST:
359			mem[pc->k] = A;
360			continue;
361
362		case BPF_STX:
363			mem[pc->k] = X;
364			continue;
365
366		case BPF_JMP|BPF_JA:
367			pc += pc->k;
368			continue;
369
370		case BPF_JMP|BPF_JGT|BPF_K:
371			pc += (A > pc->k) ? pc->jt : pc->jf;
372			continue;
373
374		case BPF_JMP|BPF_JGE|BPF_K:
375			pc += (A >= pc->k) ? pc->jt : pc->jf;
376			continue;
377
378		case BPF_JMP|BPF_JEQ|BPF_K:
379			pc += (A == pc->k) ? pc->jt : pc->jf;
380			continue;
381
382		case BPF_JMP|BPF_JSET|BPF_K:
383			pc += (A & pc->k) ? pc->jt : pc->jf;
384			continue;
385
386		case BPF_JMP|BPF_JGT|BPF_X:
387			pc += (A > X) ? pc->jt : pc->jf;
388			continue;
389
390		case BPF_JMP|BPF_JGE|BPF_X:
391			pc += (A >= X) ? pc->jt : pc->jf;
392			continue;
393
394		case BPF_JMP|BPF_JEQ|BPF_X:
395			pc += (A == X) ? pc->jt : pc->jf;
396			continue;
397
398		case BPF_JMP|BPF_JSET|BPF_X:
399			pc += (A & X) ? pc->jt : pc->jf;
400			continue;
401
402		case BPF_ALU|BPF_ADD|BPF_X:
403			A += X;
404			continue;
405
406		case BPF_ALU|BPF_SUB|BPF_X:
407			A -= X;
408			continue;
409
410		case BPF_ALU|BPF_MUL|BPF_X:
411			A *= X;
412			continue;
413
414		case BPF_ALU|BPF_DIV|BPF_X:
415			if (X == 0)
416				return 0;
417			A /= X;
418			continue;
419
420		case BPF_ALU|BPF_AND|BPF_X:
421			A &= X;
422			continue;
423
424		case BPF_ALU|BPF_OR|BPF_X:
425			A |= X;
426			continue;
427
428		case BPF_ALU|BPF_LSH|BPF_X:
429			A <<= X;
430			continue;
431
432		case BPF_ALU|BPF_RSH|BPF_X:
433			A >>= X;
434			continue;
435
436		case BPF_ALU|BPF_ADD|BPF_K:
437			A += pc->k;
438			continue;
439
440		case BPF_ALU|BPF_SUB|BPF_K:
441			A -= pc->k;
442			continue;
443
444		case BPF_ALU|BPF_MUL|BPF_K:
445			A *= pc->k;
446			continue;
447
448		case BPF_ALU|BPF_DIV|BPF_K:
449			A /= pc->k;
450			continue;
451
452		case BPF_ALU|BPF_AND|BPF_K:
453			A &= pc->k;
454			continue;
455
456		case BPF_ALU|BPF_OR|BPF_K:
457			A |= pc->k;
458			continue;
459
460		case BPF_ALU|BPF_LSH|BPF_K:
461			A <<= pc->k;
462			continue;
463
464		case BPF_ALU|BPF_RSH|BPF_K:
465			A >>= pc->k;
466			continue;
467
468		case BPF_ALU|BPF_NEG:
469			A = -A;
470			continue;
471
472		case BPF_MISC|BPF_TAX:
473			X = A;
474			continue;
475
476		case BPF_MISC|BPF_TXA:
477			A = X;
478			continue;
479		}
480	}
481}
482
483#ifdef KERNEL
484/*
485 * Return true if the 'fcode' is a valid filter program.
486 * The constraints are that each jump be forward and to a valid
487 * code.  The code must terminate with either an accept or reject.
488 * 'valid' is an array for use by the routine (it must be at least
489 * 'len' bytes long).
490 *
491 * The kernel needs to be able to verify an application's filter code.
492 * Otherwise, a bogus program could easily crash the system.
493 */
494int
495bpf_validate(f, len)
496	struct bpf_insn *f;
497	int len;
498{
499	register int i;
500	register struct bpf_insn *p;
501
502	for (i = 0; i < len; ++i) {
503		/*
504		 * Check that that jumps are forward, and within
505		 * the code block.
506		 */
507		p = &f[i];
508		if (BPF_CLASS(p->code) == BPF_JMP) {
509			register int from = i + 1;
510
511			if (BPF_OP(p->code) == BPF_JA) {
512				if (from + p->k >= len)
513					return 0;
514			}
515			else if (from + p->jt >= len || from + p->jf >= len)
516				return 0;
517		}
518		/*
519		 * Check that memory operations use valid addresses.
520		 */
521		if ((BPF_CLASS(p->code) == BPF_ST ||
522		     (BPF_CLASS(p->code) == BPF_LD &&
523		      (p->code & 0xe0) == BPF_MEM)) &&
524		    (p->k >= BPF_MEMWORDS || p->k < 0))
525			return 0;
526		/*
527		 * Check for constant division by 0.
528		 */
529		if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
530			return 0;
531	}
532	return BPF_CLASS(f[len - 1].code) == BPF_RET;
533}
534#endif
535