xref: /minix3/sys/net/bpf_filter.c (revision d56f51ea7d8b9045e5c8e2028422523d3f9a5840)
1*d56f51eaSDavid van Moolenbroek /*	$NetBSD: bpf_filter.c,v 1.70 2015/02/11 12:53:15 alnsn Exp $	*/
2*d56f51eaSDavid van Moolenbroek 
3*d56f51eaSDavid van Moolenbroek /*-
4*d56f51eaSDavid van Moolenbroek  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
5*d56f51eaSDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
6*d56f51eaSDavid van Moolenbroek  *
7*d56f51eaSDavid van Moolenbroek  * This code is derived from the Stanford/CMU enet packet filter,
8*d56f51eaSDavid van Moolenbroek  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
9*d56f51eaSDavid van Moolenbroek  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
10*d56f51eaSDavid van Moolenbroek  * Berkeley Laboratory.
11*d56f51eaSDavid van Moolenbroek  *
12*d56f51eaSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
13*d56f51eaSDavid van Moolenbroek  * modification, are permitted provided that the following conditions
14*d56f51eaSDavid van Moolenbroek  * are met:
15*d56f51eaSDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
16*d56f51eaSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
17*d56f51eaSDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
18*d56f51eaSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
19*d56f51eaSDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
20*d56f51eaSDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
21*d56f51eaSDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
22*d56f51eaSDavid van Moolenbroek  *    without specific prior written permission.
23*d56f51eaSDavid van Moolenbroek  *
24*d56f51eaSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25*d56f51eaSDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*d56f51eaSDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27*d56f51eaSDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28*d56f51eaSDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29*d56f51eaSDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30*d56f51eaSDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31*d56f51eaSDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32*d56f51eaSDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33*d56f51eaSDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34*d56f51eaSDavid van Moolenbroek  * SUCH DAMAGE.
35*d56f51eaSDavid van Moolenbroek  *
36*d56f51eaSDavid van Moolenbroek  *	@(#)bpf_filter.c	8.1 (Berkeley) 6/10/93
37*d56f51eaSDavid van Moolenbroek  */
38*d56f51eaSDavid van Moolenbroek 
39*d56f51eaSDavid van Moolenbroek #include <sys/cdefs.h>
40*d56f51eaSDavid van Moolenbroek __KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.70 2015/02/11 12:53:15 alnsn Exp $");
41*d56f51eaSDavid van Moolenbroek 
42*d56f51eaSDavid van Moolenbroek #if 0
43*d56f51eaSDavid van Moolenbroek #if !(defined(lint) || defined(KERNEL))
44*d56f51eaSDavid van Moolenbroek static const char rcsid[] =
45*d56f51eaSDavid van Moolenbroek     "@(#) Header: bpf_filter.c,v 1.33 97/04/26 13:37:18 leres Exp  (LBL)";
46*d56f51eaSDavid van Moolenbroek #endif
47*d56f51eaSDavid van Moolenbroek #endif
48*d56f51eaSDavid van Moolenbroek 
49*d56f51eaSDavid van Moolenbroek #include <sys/param.h>
50*d56f51eaSDavid van Moolenbroek #include <sys/time.h>
51*d56f51eaSDavid van Moolenbroek #include <sys/kmem.h>
52*d56f51eaSDavid van Moolenbroek #include <sys/endian.h>
53*d56f51eaSDavid van Moolenbroek 
54*d56f51eaSDavid van Moolenbroek #define	__BPF_PRIVATE
55*d56f51eaSDavid van Moolenbroek #include <net/bpf.h>
56*d56f51eaSDavid van Moolenbroek 
57*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
58*d56f51eaSDavid van Moolenbroek 
59*d56f51eaSDavid van Moolenbroek bpf_ctx_t *
bpf_create(void)60*d56f51eaSDavid van Moolenbroek bpf_create(void)
61*d56f51eaSDavid van Moolenbroek {
62*d56f51eaSDavid van Moolenbroek 	return kmem_zalloc(sizeof(bpf_ctx_t), KM_SLEEP);
63*d56f51eaSDavid van Moolenbroek }
64*d56f51eaSDavid van Moolenbroek 
65*d56f51eaSDavid van Moolenbroek void
bpf_destroy(bpf_ctx_t * bc)66*d56f51eaSDavid van Moolenbroek bpf_destroy(bpf_ctx_t *bc)
67*d56f51eaSDavid van Moolenbroek {
68*d56f51eaSDavid van Moolenbroek 	kmem_free(bc, sizeof(bpf_ctx_t));
69*d56f51eaSDavid van Moolenbroek }
70*d56f51eaSDavid van Moolenbroek 
71*d56f51eaSDavid van Moolenbroek int
bpf_set_cop(bpf_ctx_t * bc,const bpf_copfunc_t * funcs,size_t n)72*d56f51eaSDavid van Moolenbroek bpf_set_cop(bpf_ctx_t *bc, const bpf_copfunc_t *funcs, size_t n)
73*d56f51eaSDavid van Moolenbroek {
74*d56f51eaSDavid van Moolenbroek 	bc->copfuncs = funcs;
75*d56f51eaSDavid van Moolenbroek 	bc->nfuncs = n;
76*d56f51eaSDavid van Moolenbroek 	return 0;
77*d56f51eaSDavid van Moolenbroek }
78*d56f51eaSDavid van Moolenbroek 
79*d56f51eaSDavid van Moolenbroek int
bpf_set_extmem(bpf_ctx_t * bc,size_t nwords,bpf_memword_init_t preinited)80*d56f51eaSDavid van Moolenbroek bpf_set_extmem(bpf_ctx_t *bc, size_t nwords, bpf_memword_init_t preinited)
81*d56f51eaSDavid van Moolenbroek {
82*d56f51eaSDavid van Moolenbroek 	if (nwords > BPF_MAX_MEMWORDS || (preinited >> nwords) != 0) {
83*d56f51eaSDavid van Moolenbroek 		return EINVAL;
84*d56f51eaSDavid van Moolenbroek 	}
85*d56f51eaSDavid van Moolenbroek 	bc->extwords = nwords;
86*d56f51eaSDavid van Moolenbroek 	bc->preinited = preinited;
87*d56f51eaSDavid van Moolenbroek 	return 0;
88*d56f51eaSDavid van Moolenbroek }
89*d56f51eaSDavid van Moolenbroek 
90*d56f51eaSDavid van Moolenbroek #endif
91*d56f51eaSDavid van Moolenbroek 
92*d56f51eaSDavid van Moolenbroek #define EXTRACT_SHORT(p)	be16dec(p)
93*d56f51eaSDavid van Moolenbroek #define EXTRACT_LONG(p)		be32dec(p)
94*d56f51eaSDavid van Moolenbroek 
95*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
96*d56f51eaSDavid van Moolenbroek #include <sys/mbuf.h>
97*d56f51eaSDavid van Moolenbroek #define MINDEX(len, m, k) 		\
98*d56f51eaSDavid van Moolenbroek {					\
99*d56f51eaSDavid van Moolenbroek 	len = m->m_len; 		\
100*d56f51eaSDavid van Moolenbroek 	while (k >= len) { 		\
101*d56f51eaSDavid van Moolenbroek 		k -= len; 		\
102*d56f51eaSDavid van Moolenbroek 		m = m->m_next; 		\
103*d56f51eaSDavid van Moolenbroek 		if (m == 0) 		\
104*d56f51eaSDavid van Moolenbroek 			return 0; 	\
105*d56f51eaSDavid van Moolenbroek 		len = m->m_len; 	\
106*d56f51eaSDavid van Moolenbroek 	}				\
107*d56f51eaSDavid van Moolenbroek }
108*d56f51eaSDavid van Moolenbroek 
109*d56f51eaSDavid van Moolenbroek uint32_t m_xword(const struct mbuf *, uint32_t, int *);
110*d56f51eaSDavid van Moolenbroek uint32_t m_xhalf(const struct mbuf *, uint32_t, int *);
111*d56f51eaSDavid van Moolenbroek uint32_t m_xbyte(const struct mbuf *, uint32_t, int *);
112*d56f51eaSDavid van Moolenbroek 
113*d56f51eaSDavid van Moolenbroek #define xword(p, k, err) m_xword((const struct mbuf *)(p), (k), (err))
114*d56f51eaSDavid van Moolenbroek #define xhalf(p, k, err) m_xhalf((const struct mbuf *)(p), (k), (err))
115*d56f51eaSDavid van Moolenbroek #define xbyte(p, k, err) m_xbyte((const struct mbuf *)(p), (k), (err))
116*d56f51eaSDavid van Moolenbroek 
117*d56f51eaSDavid van Moolenbroek uint32_t
m_xword(const struct mbuf * m,uint32_t k,int * err)118*d56f51eaSDavid van Moolenbroek m_xword(const struct mbuf *m, uint32_t k, int *err)
119*d56f51eaSDavid van Moolenbroek {
120*d56f51eaSDavid van Moolenbroek 	int len;
121*d56f51eaSDavid van Moolenbroek 	u_char *cp, *np;
122*d56f51eaSDavid van Moolenbroek 	struct mbuf *m0;
123*d56f51eaSDavid van Moolenbroek 
124*d56f51eaSDavid van Moolenbroek 	*err = 1;
125*d56f51eaSDavid van Moolenbroek 	MINDEX(len, m, k);
126*d56f51eaSDavid van Moolenbroek 	cp = mtod(m, u_char *) + k;
127*d56f51eaSDavid van Moolenbroek 	if (len - k >= 4) {
128*d56f51eaSDavid van Moolenbroek 		*err = 0;
129*d56f51eaSDavid van Moolenbroek 		return EXTRACT_LONG(cp);
130*d56f51eaSDavid van Moolenbroek 	}
131*d56f51eaSDavid van Moolenbroek 	m0 = m->m_next;
132*d56f51eaSDavid van Moolenbroek 	if (m0 == 0 || (len - k) + m0->m_len < 4)
133*d56f51eaSDavid van Moolenbroek 		return 0;
134*d56f51eaSDavid van Moolenbroek 	*err = 0;
135*d56f51eaSDavid van Moolenbroek 	np = mtod(m0, u_char *);
136*d56f51eaSDavid van Moolenbroek 
137*d56f51eaSDavid van Moolenbroek 	switch (len - k) {
138*d56f51eaSDavid van Moolenbroek 	case 1:
139*d56f51eaSDavid van Moolenbroek 		return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
140*d56f51eaSDavid van Moolenbroek 	case 2:
141*d56f51eaSDavid van Moolenbroek 		return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
142*d56f51eaSDavid van Moolenbroek 	default:
143*d56f51eaSDavid van Moolenbroek 		return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
144*d56f51eaSDavid van Moolenbroek 	}
145*d56f51eaSDavid van Moolenbroek }
146*d56f51eaSDavid van Moolenbroek 
147*d56f51eaSDavid van Moolenbroek uint32_t
m_xhalf(const struct mbuf * m,uint32_t k,int * err)148*d56f51eaSDavid van Moolenbroek m_xhalf(const struct mbuf *m, uint32_t k, int *err)
149*d56f51eaSDavid van Moolenbroek {
150*d56f51eaSDavid van Moolenbroek 	int len;
151*d56f51eaSDavid van Moolenbroek 	u_char *cp;
152*d56f51eaSDavid van Moolenbroek 	struct mbuf *m0;
153*d56f51eaSDavid van Moolenbroek 
154*d56f51eaSDavid van Moolenbroek 	*err = 1;
155*d56f51eaSDavid van Moolenbroek 	MINDEX(len, m, k);
156*d56f51eaSDavid van Moolenbroek 	cp = mtod(m, u_char *) + k;
157*d56f51eaSDavid van Moolenbroek 	if (len - k >= 2) {
158*d56f51eaSDavid van Moolenbroek 		*err = 0;
159*d56f51eaSDavid van Moolenbroek 		return EXTRACT_SHORT(cp);
160*d56f51eaSDavid van Moolenbroek 	}
161*d56f51eaSDavid van Moolenbroek 	m0 = m->m_next;
162*d56f51eaSDavid van Moolenbroek 	if (m0 == 0)
163*d56f51eaSDavid van Moolenbroek 		return 0;
164*d56f51eaSDavid van Moolenbroek 	*err = 0;
165*d56f51eaSDavid van Moolenbroek 	return (cp[0] << 8) | mtod(m0, u_char *)[0];
166*d56f51eaSDavid van Moolenbroek }
167*d56f51eaSDavid van Moolenbroek 
168*d56f51eaSDavid van Moolenbroek uint32_t
m_xbyte(const struct mbuf * m,uint32_t k,int * err)169*d56f51eaSDavid van Moolenbroek m_xbyte(const struct mbuf *m, uint32_t k, int *err)
170*d56f51eaSDavid van Moolenbroek {
171*d56f51eaSDavid van Moolenbroek 	int len;
172*d56f51eaSDavid van Moolenbroek 
173*d56f51eaSDavid van Moolenbroek 	*err = 1;
174*d56f51eaSDavid van Moolenbroek 	MINDEX(len, m, k);
175*d56f51eaSDavid van Moolenbroek 	*err = 0;
176*d56f51eaSDavid van Moolenbroek 	return mtod(m, u_char *)[k];
177*d56f51eaSDavid van Moolenbroek }
178*d56f51eaSDavid van Moolenbroek #else /* _KERNEL */
179*d56f51eaSDavid van Moolenbroek #include <stdlib.h>
180*d56f51eaSDavid van Moolenbroek #endif /* !_KERNEL */
181*d56f51eaSDavid van Moolenbroek 
182*d56f51eaSDavid van Moolenbroek #include <net/bpf.h>
183*d56f51eaSDavid van Moolenbroek 
184*d56f51eaSDavid van Moolenbroek /*
185*d56f51eaSDavid van Moolenbroek  * Execute the filter program starting at pc on the packet p
186*d56f51eaSDavid van Moolenbroek  * wirelen is the length of the original packet
187*d56f51eaSDavid van Moolenbroek  * buflen is the amount of data present
188*d56f51eaSDavid van Moolenbroek  */
189*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
190*d56f51eaSDavid van Moolenbroek 
191*d56f51eaSDavid van Moolenbroek u_int
bpf_filter(const struct bpf_insn * pc,const u_char * p,u_int wirelen,u_int buflen)192*d56f51eaSDavid van Moolenbroek bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
193*d56f51eaSDavid van Moolenbroek     u_int buflen)
194*d56f51eaSDavid van Moolenbroek {
195*d56f51eaSDavid van Moolenbroek 	uint32_t mem[BPF_MEMWORDS];
196*d56f51eaSDavid van Moolenbroek 	bpf_args_t args = {
197*d56f51eaSDavid van Moolenbroek 		.pkt = p,
198*d56f51eaSDavid van Moolenbroek 		.wirelen = wirelen,
199*d56f51eaSDavid van Moolenbroek 		.buflen = buflen,
200*d56f51eaSDavid van Moolenbroek 		.mem = mem,
201*d56f51eaSDavid van Moolenbroek 		.arg = NULL
202*d56f51eaSDavid van Moolenbroek 	};
203*d56f51eaSDavid van Moolenbroek 
204*d56f51eaSDavid van Moolenbroek 	return bpf_filter_ext(NULL, pc, &args);
205*d56f51eaSDavid van Moolenbroek }
206*d56f51eaSDavid van Moolenbroek 
207*d56f51eaSDavid van Moolenbroek u_int
bpf_filter_ext(const bpf_ctx_t * bc,const struct bpf_insn * pc,bpf_args_t * args)208*d56f51eaSDavid van Moolenbroek bpf_filter_ext(const bpf_ctx_t *bc, const struct bpf_insn *pc, bpf_args_t *args)
209*d56f51eaSDavid van Moolenbroek #else
210*d56f51eaSDavid van Moolenbroek u_int
211*d56f51eaSDavid van Moolenbroek bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
212*d56f51eaSDavid van Moolenbroek     u_int buflen)
213*d56f51eaSDavid van Moolenbroek #endif
214*d56f51eaSDavid van Moolenbroek {
215*d56f51eaSDavid van Moolenbroek 	uint32_t A, X, k;
216*d56f51eaSDavid van Moolenbroek #ifndef _KERNEL
217*d56f51eaSDavid van Moolenbroek 	uint32_t mem[BPF_MEMWORDS];
218*d56f51eaSDavid van Moolenbroek 	bpf_args_t args_store = {
219*d56f51eaSDavid van Moolenbroek 		.pkt = p,
220*d56f51eaSDavid van Moolenbroek 		.wirelen = wirelen,
221*d56f51eaSDavid van Moolenbroek 		.buflen = buflen,
222*d56f51eaSDavid van Moolenbroek 		.mem = mem,
223*d56f51eaSDavid van Moolenbroek 		.arg = NULL
224*d56f51eaSDavid van Moolenbroek 	};
225*d56f51eaSDavid van Moolenbroek 	bpf_args_t * const args = &args_store;
226*d56f51eaSDavid van Moolenbroek #else
227*d56f51eaSDavid van Moolenbroek 	const uint8_t * const p = args->pkt;
228*d56f51eaSDavid van Moolenbroek #endif
229*d56f51eaSDavid van Moolenbroek 	if (pc == 0) {
230*d56f51eaSDavid van Moolenbroek 		/*
231*d56f51eaSDavid van Moolenbroek 		 * No filter means accept all.
232*d56f51eaSDavid van Moolenbroek 		 */
233*d56f51eaSDavid van Moolenbroek 		return (u_int)-1;
234*d56f51eaSDavid van Moolenbroek 	}
235*d56f51eaSDavid van Moolenbroek 
236*d56f51eaSDavid van Moolenbroek 	/*
237*d56f51eaSDavid van Moolenbroek 	 * Note: safe to leave memwords uninitialised, as the validation
238*d56f51eaSDavid van Moolenbroek 	 * step ensures that it will not be read, if it was not written.
239*d56f51eaSDavid van Moolenbroek 	 */
240*d56f51eaSDavid van Moolenbroek 	A = 0;
241*d56f51eaSDavid van Moolenbroek 	X = 0;
242*d56f51eaSDavid van Moolenbroek 	--pc;
243*d56f51eaSDavid van Moolenbroek 
244*d56f51eaSDavid van Moolenbroek 	for (;;) {
245*d56f51eaSDavid van Moolenbroek 		++pc;
246*d56f51eaSDavid van Moolenbroek 		switch (pc->code) {
247*d56f51eaSDavid van Moolenbroek 
248*d56f51eaSDavid van Moolenbroek 		default:
249*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
250*d56f51eaSDavid van Moolenbroek 			return 0;
251*d56f51eaSDavid van Moolenbroek #else
252*d56f51eaSDavid van Moolenbroek 			abort();
253*d56f51eaSDavid van Moolenbroek 			/*NOTREACHED*/
254*d56f51eaSDavid van Moolenbroek #endif
255*d56f51eaSDavid van Moolenbroek 		case BPF_RET|BPF_K:
256*d56f51eaSDavid van Moolenbroek 			return (u_int)pc->k;
257*d56f51eaSDavid van Moolenbroek 
258*d56f51eaSDavid van Moolenbroek 		case BPF_RET|BPF_A:
259*d56f51eaSDavid van Moolenbroek 			return (u_int)A;
260*d56f51eaSDavid van Moolenbroek 
261*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_W|BPF_ABS:
262*d56f51eaSDavid van Moolenbroek 			k = pc->k;
263*d56f51eaSDavid van Moolenbroek 			if (k > args->buflen ||
264*d56f51eaSDavid van Moolenbroek 			    sizeof(int32_t) > args->buflen - k) {
265*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
266*d56f51eaSDavid van Moolenbroek 				int merr;
267*d56f51eaSDavid van Moolenbroek 
268*d56f51eaSDavid van Moolenbroek 				if (args->buflen != 0)
269*d56f51eaSDavid van Moolenbroek 					return 0;
270*d56f51eaSDavid van Moolenbroek 				A = xword(args->pkt, k, &merr);
271*d56f51eaSDavid van Moolenbroek 				if (merr != 0)
272*d56f51eaSDavid van Moolenbroek 					return 0;
273*d56f51eaSDavid van Moolenbroek 				continue;
274*d56f51eaSDavid van Moolenbroek #else
275*d56f51eaSDavid van Moolenbroek 				return 0;
276*d56f51eaSDavid van Moolenbroek #endif
277*d56f51eaSDavid van Moolenbroek 			}
278*d56f51eaSDavid van Moolenbroek 			A = EXTRACT_LONG(&p[k]);
279*d56f51eaSDavid van Moolenbroek 			continue;
280*d56f51eaSDavid van Moolenbroek 
281*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_H|BPF_ABS:
282*d56f51eaSDavid van Moolenbroek 			k = pc->k;
283*d56f51eaSDavid van Moolenbroek 			if (k > args->buflen ||
284*d56f51eaSDavid van Moolenbroek 			    sizeof(int16_t) > args->buflen - k) {
285*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
286*d56f51eaSDavid van Moolenbroek 				int merr;
287*d56f51eaSDavid van Moolenbroek 
288*d56f51eaSDavid van Moolenbroek 				if (args->buflen != 0)
289*d56f51eaSDavid van Moolenbroek 					return 0;
290*d56f51eaSDavid van Moolenbroek 				A = xhalf(args->pkt, k, &merr);
291*d56f51eaSDavid van Moolenbroek 				if (merr != 0)
292*d56f51eaSDavid van Moolenbroek 					return 0;
293*d56f51eaSDavid van Moolenbroek 				continue;
294*d56f51eaSDavid van Moolenbroek #else
295*d56f51eaSDavid van Moolenbroek 				return 0;
296*d56f51eaSDavid van Moolenbroek #endif
297*d56f51eaSDavid van Moolenbroek 			}
298*d56f51eaSDavid van Moolenbroek 			A = EXTRACT_SHORT(&p[k]);
299*d56f51eaSDavid van Moolenbroek 			continue;
300*d56f51eaSDavid van Moolenbroek 
301*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_B|BPF_ABS:
302*d56f51eaSDavid van Moolenbroek 			k = pc->k;
303*d56f51eaSDavid van Moolenbroek 			if (k >= args->buflen) {
304*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
305*d56f51eaSDavid van Moolenbroek 				int merr;
306*d56f51eaSDavid van Moolenbroek 
307*d56f51eaSDavid van Moolenbroek 				if (args->buflen != 0)
308*d56f51eaSDavid van Moolenbroek 					return 0;
309*d56f51eaSDavid van Moolenbroek 				A = xbyte(args->pkt, k, &merr);
310*d56f51eaSDavid van Moolenbroek 				if (merr != 0)
311*d56f51eaSDavid van Moolenbroek 					return 0;
312*d56f51eaSDavid van Moolenbroek 				continue;
313*d56f51eaSDavid van Moolenbroek #else
314*d56f51eaSDavid van Moolenbroek 				return 0;
315*d56f51eaSDavid van Moolenbroek #endif
316*d56f51eaSDavid van Moolenbroek 			}
317*d56f51eaSDavid van Moolenbroek 			A = p[k];
318*d56f51eaSDavid van Moolenbroek 			continue;
319*d56f51eaSDavid van Moolenbroek 
320*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_W|BPF_LEN:
321*d56f51eaSDavid van Moolenbroek 			A = args->wirelen;
322*d56f51eaSDavid van Moolenbroek 			continue;
323*d56f51eaSDavid van Moolenbroek 
324*d56f51eaSDavid van Moolenbroek 		case BPF_LDX|BPF_W|BPF_LEN:
325*d56f51eaSDavid van Moolenbroek 			X = args->wirelen;
326*d56f51eaSDavid van Moolenbroek 			continue;
327*d56f51eaSDavid van Moolenbroek 
328*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_W|BPF_IND:
329*d56f51eaSDavid van Moolenbroek 			k = X + pc->k;
330*d56f51eaSDavid van Moolenbroek 			if (k < X || k >= args->buflen ||
331*d56f51eaSDavid van Moolenbroek 			    sizeof(int32_t) > args->buflen - k) {
332*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
333*d56f51eaSDavid van Moolenbroek 				int merr;
334*d56f51eaSDavid van Moolenbroek 
335*d56f51eaSDavid van Moolenbroek 				if (k < X || args->buflen != 0)
336*d56f51eaSDavid van Moolenbroek 					return 0;
337*d56f51eaSDavid van Moolenbroek 				A = xword(args->pkt, k, &merr);
338*d56f51eaSDavid van Moolenbroek 				if (merr != 0)
339*d56f51eaSDavid van Moolenbroek 					return 0;
340*d56f51eaSDavid van Moolenbroek 				continue;
341*d56f51eaSDavid van Moolenbroek #else
342*d56f51eaSDavid van Moolenbroek 				return 0;
343*d56f51eaSDavid van Moolenbroek #endif
344*d56f51eaSDavid van Moolenbroek 			}
345*d56f51eaSDavid van Moolenbroek 			A = EXTRACT_LONG(&p[k]);
346*d56f51eaSDavid van Moolenbroek 			continue;
347*d56f51eaSDavid van Moolenbroek 
348*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_H|BPF_IND:
349*d56f51eaSDavid van Moolenbroek 			k = X + pc->k;
350*d56f51eaSDavid van Moolenbroek 			if (k < X || k >= args->buflen ||
351*d56f51eaSDavid van Moolenbroek 			    sizeof(int16_t) > args->buflen - k) {
352*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
353*d56f51eaSDavid van Moolenbroek 				int merr;
354*d56f51eaSDavid van Moolenbroek 
355*d56f51eaSDavid van Moolenbroek 				if (k < X || args->buflen != 0)
356*d56f51eaSDavid van Moolenbroek 					return 0;
357*d56f51eaSDavid van Moolenbroek 				A = xhalf(args->pkt, k, &merr);
358*d56f51eaSDavid van Moolenbroek 				if (merr != 0)
359*d56f51eaSDavid van Moolenbroek 					return 0;
360*d56f51eaSDavid van Moolenbroek 				continue;
361*d56f51eaSDavid van Moolenbroek #else
362*d56f51eaSDavid van Moolenbroek 				return 0;
363*d56f51eaSDavid van Moolenbroek #endif
364*d56f51eaSDavid van Moolenbroek 			}
365*d56f51eaSDavid van Moolenbroek 			A = EXTRACT_SHORT(&p[k]);
366*d56f51eaSDavid van Moolenbroek 			continue;
367*d56f51eaSDavid van Moolenbroek 
368*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_B|BPF_IND:
369*d56f51eaSDavid van Moolenbroek 			k = X + pc->k;
370*d56f51eaSDavid van Moolenbroek 			if (k < X || k >= args->buflen) {
371*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
372*d56f51eaSDavid van Moolenbroek 				int merr;
373*d56f51eaSDavid van Moolenbroek 
374*d56f51eaSDavid van Moolenbroek 				if (k < X || args->buflen != 0)
375*d56f51eaSDavid van Moolenbroek 					return 0;
376*d56f51eaSDavid van Moolenbroek 				A = xbyte(args->pkt, k, &merr);
377*d56f51eaSDavid van Moolenbroek 				if (merr != 0)
378*d56f51eaSDavid van Moolenbroek 					return 0;
379*d56f51eaSDavid van Moolenbroek 				continue;
380*d56f51eaSDavid van Moolenbroek #else
381*d56f51eaSDavid van Moolenbroek 				return 0;
382*d56f51eaSDavid van Moolenbroek #endif
383*d56f51eaSDavid van Moolenbroek 			}
384*d56f51eaSDavid van Moolenbroek 			A = p[k];
385*d56f51eaSDavid van Moolenbroek 			continue;
386*d56f51eaSDavid van Moolenbroek 
387*d56f51eaSDavid van Moolenbroek 		case BPF_LDX|BPF_MSH|BPF_B:
388*d56f51eaSDavid van Moolenbroek 			k = pc->k;
389*d56f51eaSDavid van Moolenbroek 			if (k >= args->buflen) {
390*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
391*d56f51eaSDavid van Moolenbroek 				int merr;
392*d56f51eaSDavid van Moolenbroek 
393*d56f51eaSDavid van Moolenbroek 				if (args->buflen != 0)
394*d56f51eaSDavid van Moolenbroek 					return 0;
395*d56f51eaSDavid van Moolenbroek 				X = (xbyte(args->pkt, k, &merr) & 0xf) << 2;
396*d56f51eaSDavid van Moolenbroek 				if (merr != 0)
397*d56f51eaSDavid van Moolenbroek 					return 0;
398*d56f51eaSDavid van Moolenbroek 				continue;
399*d56f51eaSDavid van Moolenbroek #else
400*d56f51eaSDavid van Moolenbroek 				return 0;
401*d56f51eaSDavid van Moolenbroek #endif
402*d56f51eaSDavid van Moolenbroek 			}
403*d56f51eaSDavid van Moolenbroek 			X = (p[pc->k] & 0xf) << 2;
404*d56f51eaSDavid van Moolenbroek 			continue;
405*d56f51eaSDavid van Moolenbroek 
406*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_IMM:
407*d56f51eaSDavid van Moolenbroek 			A = pc->k;
408*d56f51eaSDavid van Moolenbroek 			continue;
409*d56f51eaSDavid van Moolenbroek 
410*d56f51eaSDavid van Moolenbroek 		case BPF_LDX|BPF_IMM:
411*d56f51eaSDavid van Moolenbroek 			X = pc->k;
412*d56f51eaSDavid van Moolenbroek 			continue;
413*d56f51eaSDavid van Moolenbroek 
414*d56f51eaSDavid van Moolenbroek 		case BPF_LD|BPF_MEM:
415*d56f51eaSDavid van Moolenbroek 			A = args->mem[pc->k];
416*d56f51eaSDavid van Moolenbroek 			continue;
417*d56f51eaSDavid van Moolenbroek 
418*d56f51eaSDavid van Moolenbroek 		case BPF_LDX|BPF_MEM:
419*d56f51eaSDavid van Moolenbroek 			X = args->mem[pc->k];
420*d56f51eaSDavid van Moolenbroek 			continue;
421*d56f51eaSDavid van Moolenbroek 
422*d56f51eaSDavid van Moolenbroek 		case BPF_ST:
423*d56f51eaSDavid van Moolenbroek 			args->mem[pc->k] = A;
424*d56f51eaSDavid van Moolenbroek 			continue;
425*d56f51eaSDavid van Moolenbroek 
426*d56f51eaSDavid van Moolenbroek 		case BPF_STX:
427*d56f51eaSDavid van Moolenbroek 			args->mem[pc->k] = X;
428*d56f51eaSDavid van Moolenbroek 			continue;
429*d56f51eaSDavid van Moolenbroek 
430*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JA:
431*d56f51eaSDavid van Moolenbroek 			pc += pc->k;
432*d56f51eaSDavid van Moolenbroek 			continue;
433*d56f51eaSDavid van Moolenbroek 
434*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JGT|BPF_K:
435*d56f51eaSDavid van Moolenbroek 			pc += (A > pc->k) ? pc->jt : pc->jf;
436*d56f51eaSDavid van Moolenbroek 			continue;
437*d56f51eaSDavid van Moolenbroek 
438*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JGE|BPF_K:
439*d56f51eaSDavid van Moolenbroek 			pc += (A >= pc->k) ? pc->jt : pc->jf;
440*d56f51eaSDavid van Moolenbroek 			continue;
441*d56f51eaSDavid van Moolenbroek 
442*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JEQ|BPF_K:
443*d56f51eaSDavid van Moolenbroek 			pc += (A == pc->k) ? pc->jt : pc->jf;
444*d56f51eaSDavid van Moolenbroek 			continue;
445*d56f51eaSDavid van Moolenbroek 
446*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JSET|BPF_K:
447*d56f51eaSDavid van Moolenbroek 			pc += (A & pc->k) ? pc->jt : pc->jf;
448*d56f51eaSDavid van Moolenbroek 			continue;
449*d56f51eaSDavid van Moolenbroek 
450*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JGT|BPF_X:
451*d56f51eaSDavid van Moolenbroek 			pc += (A > X) ? pc->jt : pc->jf;
452*d56f51eaSDavid van Moolenbroek 			continue;
453*d56f51eaSDavid van Moolenbroek 
454*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JGE|BPF_X:
455*d56f51eaSDavid van Moolenbroek 			pc += (A >= X) ? pc->jt : pc->jf;
456*d56f51eaSDavid van Moolenbroek 			continue;
457*d56f51eaSDavid van Moolenbroek 
458*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JEQ|BPF_X:
459*d56f51eaSDavid van Moolenbroek 			pc += (A == X) ? pc->jt : pc->jf;
460*d56f51eaSDavid van Moolenbroek 			continue;
461*d56f51eaSDavid van Moolenbroek 
462*d56f51eaSDavid van Moolenbroek 		case BPF_JMP|BPF_JSET|BPF_X:
463*d56f51eaSDavid van Moolenbroek 			pc += (A & X) ? pc->jt : pc->jf;
464*d56f51eaSDavid van Moolenbroek 			continue;
465*d56f51eaSDavid van Moolenbroek 
466*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_ADD|BPF_X:
467*d56f51eaSDavid van Moolenbroek 			A += X;
468*d56f51eaSDavid van Moolenbroek 			continue;
469*d56f51eaSDavid van Moolenbroek 
470*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_SUB|BPF_X:
471*d56f51eaSDavid van Moolenbroek 			A -= X;
472*d56f51eaSDavid van Moolenbroek 			continue;
473*d56f51eaSDavid van Moolenbroek 
474*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_MUL|BPF_X:
475*d56f51eaSDavid van Moolenbroek 			A *= X;
476*d56f51eaSDavid van Moolenbroek 			continue;
477*d56f51eaSDavid van Moolenbroek 
478*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_DIV|BPF_X:
479*d56f51eaSDavid van Moolenbroek 			if (X == 0)
480*d56f51eaSDavid van Moolenbroek 				return 0;
481*d56f51eaSDavid van Moolenbroek 			A /= X;
482*d56f51eaSDavid van Moolenbroek 			continue;
483*d56f51eaSDavid van Moolenbroek 
484*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_MOD|BPF_X:
485*d56f51eaSDavid van Moolenbroek 			if (X == 0)
486*d56f51eaSDavid van Moolenbroek 				return 0;
487*d56f51eaSDavid van Moolenbroek 			A %= X;
488*d56f51eaSDavid van Moolenbroek 			continue;
489*d56f51eaSDavid van Moolenbroek 
490*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_AND|BPF_X:
491*d56f51eaSDavid van Moolenbroek 			A &= X;
492*d56f51eaSDavid van Moolenbroek 			continue;
493*d56f51eaSDavid van Moolenbroek 
494*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_OR|BPF_X:
495*d56f51eaSDavid van Moolenbroek 			A |= X;
496*d56f51eaSDavid van Moolenbroek 			continue;
497*d56f51eaSDavid van Moolenbroek 
498*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_XOR|BPF_X:
499*d56f51eaSDavid van Moolenbroek 			A ^= X;
500*d56f51eaSDavid van Moolenbroek 			continue;
501*d56f51eaSDavid van Moolenbroek 
502*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_LSH|BPF_X:
503*d56f51eaSDavid van Moolenbroek 			A <<= X;
504*d56f51eaSDavid van Moolenbroek 			continue;
505*d56f51eaSDavid van Moolenbroek 
506*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_RSH|BPF_X:
507*d56f51eaSDavid van Moolenbroek 			A >>= X;
508*d56f51eaSDavid van Moolenbroek 			continue;
509*d56f51eaSDavid van Moolenbroek 
510*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_ADD|BPF_K:
511*d56f51eaSDavid van Moolenbroek 			A += pc->k;
512*d56f51eaSDavid van Moolenbroek 			continue;
513*d56f51eaSDavid van Moolenbroek 
514*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_SUB|BPF_K:
515*d56f51eaSDavid van Moolenbroek 			A -= pc->k;
516*d56f51eaSDavid van Moolenbroek 			continue;
517*d56f51eaSDavid van Moolenbroek 
518*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_MUL|BPF_K:
519*d56f51eaSDavid van Moolenbroek 			A *= pc->k;
520*d56f51eaSDavid van Moolenbroek 			continue;
521*d56f51eaSDavid van Moolenbroek 
522*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_DIV|BPF_K:
523*d56f51eaSDavid van Moolenbroek 			A /= pc->k;
524*d56f51eaSDavid van Moolenbroek 			continue;
525*d56f51eaSDavid van Moolenbroek 
526*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_MOD|BPF_K:
527*d56f51eaSDavid van Moolenbroek 			A %= pc->k;
528*d56f51eaSDavid van Moolenbroek 			continue;
529*d56f51eaSDavid van Moolenbroek 
530*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_AND|BPF_K:
531*d56f51eaSDavid van Moolenbroek 			A &= pc->k;
532*d56f51eaSDavid van Moolenbroek 			continue;
533*d56f51eaSDavid van Moolenbroek 
534*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_OR|BPF_K:
535*d56f51eaSDavid van Moolenbroek 			A |= pc->k;
536*d56f51eaSDavid van Moolenbroek 			continue;
537*d56f51eaSDavid van Moolenbroek 
538*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_XOR|BPF_K:
539*d56f51eaSDavid van Moolenbroek 			A ^= pc->k;
540*d56f51eaSDavid van Moolenbroek 			continue;
541*d56f51eaSDavid van Moolenbroek 
542*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_LSH|BPF_K:
543*d56f51eaSDavid van Moolenbroek 			A <<= pc->k;
544*d56f51eaSDavid van Moolenbroek 			continue;
545*d56f51eaSDavid van Moolenbroek 
546*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_RSH|BPF_K:
547*d56f51eaSDavid van Moolenbroek 			A >>= pc->k;
548*d56f51eaSDavid van Moolenbroek 			continue;
549*d56f51eaSDavid van Moolenbroek 
550*d56f51eaSDavid van Moolenbroek 		case BPF_ALU|BPF_NEG:
551*d56f51eaSDavid van Moolenbroek 			A = -A;
552*d56f51eaSDavid van Moolenbroek 			continue;
553*d56f51eaSDavid van Moolenbroek 
554*d56f51eaSDavid van Moolenbroek 		case BPF_MISC|BPF_TAX:
555*d56f51eaSDavid van Moolenbroek 			X = A;
556*d56f51eaSDavid van Moolenbroek 			continue;
557*d56f51eaSDavid van Moolenbroek 
558*d56f51eaSDavid van Moolenbroek 		case BPF_MISC|BPF_TXA:
559*d56f51eaSDavid van Moolenbroek 			A = X;
560*d56f51eaSDavid van Moolenbroek 			continue;
561*d56f51eaSDavid van Moolenbroek 
562*d56f51eaSDavid van Moolenbroek 		case BPF_MISC|BPF_COP:
563*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
564*d56f51eaSDavid van Moolenbroek 			if (pc->k < bc->nfuncs) {
565*d56f51eaSDavid van Moolenbroek 				const bpf_copfunc_t fn = bc->copfuncs[pc->k];
566*d56f51eaSDavid van Moolenbroek 				A = fn(bc, args, A);
567*d56f51eaSDavid van Moolenbroek 				continue;
568*d56f51eaSDavid van Moolenbroek 			}
569*d56f51eaSDavid van Moolenbroek #endif
570*d56f51eaSDavid van Moolenbroek 			return 0;
571*d56f51eaSDavid van Moolenbroek 
572*d56f51eaSDavid van Moolenbroek 		case BPF_MISC|BPF_COPX:
573*d56f51eaSDavid van Moolenbroek #ifdef _KERNEL
574*d56f51eaSDavid van Moolenbroek 			if (X < bc->nfuncs) {
575*d56f51eaSDavid van Moolenbroek 				const bpf_copfunc_t fn = bc->copfuncs[X];
576*d56f51eaSDavid van Moolenbroek 				A = fn(bc, args, A);
577*d56f51eaSDavid van Moolenbroek 				continue;
578*d56f51eaSDavid van Moolenbroek 			}
579*d56f51eaSDavid van Moolenbroek #endif
580*d56f51eaSDavid van Moolenbroek 			return 0;
581*d56f51eaSDavid van Moolenbroek 		}
582*d56f51eaSDavid van Moolenbroek 	}
583*d56f51eaSDavid van Moolenbroek }
584*d56f51eaSDavid van Moolenbroek 
585*d56f51eaSDavid van Moolenbroek /*
586*d56f51eaSDavid van Moolenbroek  * Return true if the 'fcode' is a valid filter program.
587*d56f51eaSDavid van Moolenbroek  * The constraints are that each jump be forward and to a valid
588*d56f51eaSDavid van Moolenbroek  * code, that memory accesses are within valid ranges (to the
589*d56f51eaSDavid van Moolenbroek  * extent that this can be checked statically; loads of packet
590*d56f51eaSDavid van Moolenbroek  * data have to be, and are, also checked at run time), and that
591*d56f51eaSDavid van Moolenbroek  * the code terminates with either an accept or reject.
592*d56f51eaSDavid van Moolenbroek  *
593*d56f51eaSDavid van Moolenbroek  * The kernel needs to be able to verify an application's filter code.
594*d56f51eaSDavid van Moolenbroek  * Otherwise, a bogus program could easily crash the system.
595*d56f51eaSDavid van Moolenbroek  */
596*d56f51eaSDavid van Moolenbroek 
597*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
598*d56f51eaSDavid van Moolenbroek 
599*d56f51eaSDavid van Moolenbroek int
bpf_validate(const struct bpf_insn * f,int signed_len)600*d56f51eaSDavid van Moolenbroek bpf_validate(const struct bpf_insn *f, int signed_len)
601*d56f51eaSDavid van Moolenbroek {
602*d56f51eaSDavid van Moolenbroek 	return bpf_validate_ext(NULL, f, signed_len);
603*d56f51eaSDavid van Moolenbroek }
604*d56f51eaSDavid van Moolenbroek 
605*d56f51eaSDavid van Moolenbroek int
bpf_validate_ext(const bpf_ctx_t * bc,const struct bpf_insn * f,int signed_len)606*d56f51eaSDavid van Moolenbroek bpf_validate_ext(const bpf_ctx_t *bc, const struct bpf_insn *f, int signed_len)
607*d56f51eaSDavid van Moolenbroek #else
608*d56f51eaSDavid van Moolenbroek int
609*d56f51eaSDavid van Moolenbroek bpf_validate(const struct bpf_insn *f, int signed_len)
610*d56f51eaSDavid van Moolenbroek #endif
611*d56f51eaSDavid van Moolenbroek {
612*d56f51eaSDavid van Moolenbroek 	u_int i, from, len, ok = 0;
613*d56f51eaSDavid van Moolenbroek 	const struct bpf_insn *p;
614*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
615*d56f51eaSDavid van Moolenbroek 	bpf_memword_init_t *mem, invalid;
616*d56f51eaSDavid van Moolenbroek 	size_t size;
617*d56f51eaSDavid van Moolenbroek 	const size_t extwords = bc ? bc->extwords : 0;
618*d56f51eaSDavid van Moolenbroek 	const size_t memwords = extwords ? extwords : BPF_MEMWORDS;
619*d56f51eaSDavid van Moolenbroek 	const bpf_memword_init_t preinited = extwords ? bc->preinited : 0;
620*d56f51eaSDavid van Moolenbroek #else
621*d56f51eaSDavid van Moolenbroek 	const size_t memwords = BPF_MEMWORDS;
622*d56f51eaSDavid van Moolenbroek #endif
623*d56f51eaSDavid van Moolenbroek 
624*d56f51eaSDavid van Moolenbroek 	len = (u_int)signed_len;
625*d56f51eaSDavid van Moolenbroek 	if (len < 1)
626*d56f51eaSDavid van Moolenbroek 		return 0;
627*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
628*d56f51eaSDavid van Moolenbroek 	if (len > BPF_MAXINSNS)
629*d56f51eaSDavid van Moolenbroek 		return 0;
630*d56f51eaSDavid van Moolenbroek #endif
631*d56f51eaSDavid van Moolenbroek 	if (f[len - 1].code != (BPF_RET|BPF_K) &&
632*d56f51eaSDavid van Moolenbroek 	    f[len - 1].code != (BPF_RET|BPF_A)) {
633*d56f51eaSDavid van Moolenbroek 		return 0;
634*d56f51eaSDavid van Moolenbroek 	}
635*d56f51eaSDavid van Moolenbroek 
636*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
637*d56f51eaSDavid van Moolenbroek 	/* Note: only the pre-initialised is valid on startup */
638*d56f51eaSDavid van Moolenbroek 	mem = kmem_zalloc(size = sizeof(*mem) * len, KM_SLEEP);
639*d56f51eaSDavid van Moolenbroek 	invalid = ~preinited;
640*d56f51eaSDavid van Moolenbroek #endif
641*d56f51eaSDavid van Moolenbroek 
642*d56f51eaSDavid van Moolenbroek 	for (i = 0; i < len; ++i) {
643*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
644*d56f51eaSDavid van Moolenbroek 		/* blend in any invalid bits for current pc */
645*d56f51eaSDavid van Moolenbroek 		invalid |= mem[i];
646*d56f51eaSDavid van Moolenbroek #endif
647*d56f51eaSDavid van Moolenbroek 		p = &f[i];
648*d56f51eaSDavid van Moolenbroek 		switch (BPF_CLASS(p->code)) {
649*d56f51eaSDavid van Moolenbroek 		/*
650*d56f51eaSDavid van Moolenbroek 		 * Check that memory operations use valid addresses.
651*d56f51eaSDavid van Moolenbroek 		 */
652*d56f51eaSDavid van Moolenbroek 		case BPF_LD:
653*d56f51eaSDavid van Moolenbroek 		case BPF_LDX:
654*d56f51eaSDavid van Moolenbroek 			switch (BPF_MODE(p->code)) {
655*d56f51eaSDavid van Moolenbroek 			case BPF_MEM:
656*d56f51eaSDavid van Moolenbroek 				/*
657*d56f51eaSDavid van Moolenbroek 				 * There's no maximum packet data size
658*d56f51eaSDavid van Moolenbroek 				 * in userland.  The runtime packet length
659*d56f51eaSDavid van Moolenbroek 				 * check suffices.
660*d56f51eaSDavid van Moolenbroek 				 */
661*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
662*d56f51eaSDavid van Moolenbroek 				/*
663*d56f51eaSDavid van Moolenbroek 				 * More strict check with actual packet length
664*d56f51eaSDavid van Moolenbroek 				 * is done runtime.
665*d56f51eaSDavid van Moolenbroek 				 */
666*d56f51eaSDavid van Moolenbroek 				if (p->k >= memwords)
667*d56f51eaSDavid van Moolenbroek 					goto out;
668*d56f51eaSDavid van Moolenbroek 				/* check for current memory invalid */
669*d56f51eaSDavid van Moolenbroek 				if (invalid & BPF_MEMWORD_INIT(p->k))
670*d56f51eaSDavid van Moolenbroek 					goto out;
671*d56f51eaSDavid van Moolenbroek #endif
672*d56f51eaSDavid van Moolenbroek 				break;
673*d56f51eaSDavid van Moolenbroek 			case BPF_ABS:
674*d56f51eaSDavid van Moolenbroek 			case BPF_IND:
675*d56f51eaSDavid van Moolenbroek 			case BPF_MSH:
676*d56f51eaSDavid van Moolenbroek 			case BPF_IMM:
677*d56f51eaSDavid van Moolenbroek 			case BPF_LEN:
678*d56f51eaSDavid van Moolenbroek 				break;
679*d56f51eaSDavid van Moolenbroek 			default:
680*d56f51eaSDavid van Moolenbroek 				goto out;
681*d56f51eaSDavid van Moolenbroek 			}
682*d56f51eaSDavid van Moolenbroek 			break;
683*d56f51eaSDavid van Moolenbroek 		case BPF_ST:
684*d56f51eaSDavid van Moolenbroek 		case BPF_STX:
685*d56f51eaSDavid van Moolenbroek 			if (p->k >= memwords)
686*d56f51eaSDavid van Moolenbroek 				goto out;
687*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
688*d56f51eaSDavid van Moolenbroek 			/* validate the memory word */
689*d56f51eaSDavid van Moolenbroek 			invalid &= ~BPF_MEMWORD_INIT(p->k);
690*d56f51eaSDavid van Moolenbroek #endif
691*d56f51eaSDavid van Moolenbroek 			break;
692*d56f51eaSDavid van Moolenbroek 		case BPF_ALU:
693*d56f51eaSDavid van Moolenbroek 			switch (BPF_OP(p->code)) {
694*d56f51eaSDavid van Moolenbroek 			case BPF_ADD:
695*d56f51eaSDavid van Moolenbroek 			case BPF_SUB:
696*d56f51eaSDavid van Moolenbroek 			case BPF_MUL:
697*d56f51eaSDavid van Moolenbroek 			case BPF_OR:
698*d56f51eaSDavid van Moolenbroek 			case BPF_XOR:
699*d56f51eaSDavid van Moolenbroek 			case BPF_AND:
700*d56f51eaSDavid van Moolenbroek 			case BPF_LSH:
701*d56f51eaSDavid van Moolenbroek 			case BPF_RSH:
702*d56f51eaSDavid van Moolenbroek 			case BPF_NEG:
703*d56f51eaSDavid van Moolenbroek 				break;
704*d56f51eaSDavid van Moolenbroek 			case BPF_DIV:
705*d56f51eaSDavid van Moolenbroek 			case BPF_MOD:
706*d56f51eaSDavid van Moolenbroek 				/*
707*d56f51eaSDavid van Moolenbroek 				 * Check for constant division by 0.
708*d56f51eaSDavid van Moolenbroek 				 */
709*d56f51eaSDavid van Moolenbroek 				if (BPF_SRC(p->code) == BPF_K && p->k == 0)
710*d56f51eaSDavid van Moolenbroek 					goto out;
711*d56f51eaSDavid van Moolenbroek 				break;
712*d56f51eaSDavid van Moolenbroek 			default:
713*d56f51eaSDavid van Moolenbroek 				goto out;
714*d56f51eaSDavid van Moolenbroek 			}
715*d56f51eaSDavid van Moolenbroek 			break;
716*d56f51eaSDavid van Moolenbroek 		case BPF_JMP:
717*d56f51eaSDavid van Moolenbroek 			/*
718*d56f51eaSDavid van Moolenbroek 			 * Check that jumps are within the code block,
719*d56f51eaSDavid van Moolenbroek 			 * and that unconditional branches don't go
720*d56f51eaSDavid van Moolenbroek 			 * backwards as a result of an overflow.
721*d56f51eaSDavid van Moolenbroek 			 * Unconditional branches have a 32-bit offset,
722*d56f51eaSDavid van Moolenbroek 			 * so they could overflow; we check to make
723*d56f51eaSDavid van Moolenbroek 			 * sure they don't.  Conditional branches have
724*d56f51eaSDavid van Moolenbroek 			 * an 8-bit offset, and the from address is <=
725*d56f51eaSDavid van Moolenbroek 			 * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
726*d56f51eaSDavid van Moolenbroek 			 * is sufficiently small that adding 255 to it
727*d56f51eaSDavid van Moolenbroek 			 * won't overflow.
728*d56f51eaSDavid van Moolenbroek 			 *
729*d56f51eaSDavid van Moolenbroek 			 * We know that len is <= BPF_MAXINSNS, and we
730*d56f51eaSDavid van Moolenbroek 			 * assume that BPF_MAXINSNS is < the maximum size
731*d56f51eaSDavid van Moolenbroek 			 * of a u_int, so that i + 1 doesn't overflow.
732*d56f51eaSDavid van Moolenbroek 			 *
733*d56f51eaSDavid van Moolenbroek 			 * For userland, we don't know that the from
734*d56f51eaSDavid van Moolenbroek 			 * or len are <= BPF_MAXINSNS, but we know that
735*d56f51eaSDavid van Moolenbroek 			 * from <= len, and, except on a 64-bit system,
736*d56f51eaSDavid van Moolenbroek 			 * it's unlikely that len, if it truly reflects
737*d56f51eaSDavid van Moolenbroek 			 * the size of the program we've been handed,
738*d56f51eaSDavid van Moolenbroek 			 * will be anywhere near the maximum size of
739*d56f51eaSDavid van Moolenbroek 			 * a u_int.  We also don't check for backward
740*d56f51eaSDavid van Moolenbroek 			 * branches, as we currently support them in
741*d56f51eaSDavid van Moolenbroek 			 * userland for the protochain operation.
742*d56f51eaSDavid van Moolenbroek 			 */
743*d56f51eaSDavid van Moolenbroek 			from = i + 1;
744*d56f51eaSDavid van Moolenbroek 			switch (BPF_OP(p->code)) {
745*d56f51eaSDavid van Moolenbroek 			case BPF_JA:
746*d56f51eaSDavid van Moolenbroek 				if (from + p->k >= len)
747*d56f51eaSDavid van Moolenbroek 					goto out;
748*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
749*d56f51eaSDavid van Moolenbroek 				if (from + p->k < from)
750*d56f51eaSDavid van Moolenbroek 					goto out;
751*d56f51eaSDavid van Moolenbroek 				/*
752*d56f51eaSDavid van Moolenbroek 				 * mark the currently invalid bits for the
753*d56f51eaSDavid van Moolenbroek 				 * destination
754*d56f51eaSDavid van Moolenbroek 				 */
755*d56f51eaSDavid van Moolenbroek 				mem[from + p->k] |= invalid;
756*d56f51eaSDavid van Moolenbroek 				invalid = 0;
757*d56f51eaSDavid van Moolenbroek #endif
758*d56f51eaSDavid van Moolenbroek 				break;
759*d56f51eaSDavid van Moolenbroek 			case BPF_JEQ:
760*d56f51eaSDavid van Moolenbroek 			case BPF_JGT:
761*d56f51eaSDavid van Moolenbroek 			case BPF_JGE:
762*d56f51eaSDavid van Moolenbroek 			case BPF_JSET:
763*d56f51eaSDavid van Moolenbroek 				if (from + p->jt >= len || from + p->jf >= len)
764*d56f51eaSDavid van Moolenbroek 					goto out;
765*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
766*d56f51eaSDavid van Moolenbroek 				/*
767*d56f51eaSDavid van Moolenbroek 				 * mark the currently invalid bits for both
768*d56f51eaSDavid van Moolenbroek 				 * possible jump destinations
769*d56f51eaSDavid van Moolenbroek 				 */
770*d56f51eaSDavid van Moolenbroek 				mem[from + p->jt] |= invalid;
771*d56f51eaSDavid van Moolenbroek 				mem[from + p->jf] |= invalid;
772*d56f51eaSDavid van Moolenbroek 				invalid = 0;
773*d56f51eaSDavid van Moolenbroek #endif
774*d56f51eaSDavid van Moolenbroek 				break;
775*d56f51eaSDavid van Moolenbroek 			default:
776*d56f51eaSDavid van Moolenbroek 				goto out;
777*d56f51eaSDavid van Moolenbroek 			}
778*d56f51eaSDavid van Moolenbroek 			break;
779*d56f51eaSDavid van Moolenbroek 		case BPF_RET:
780*d56f51eaSDavid van Moolenbroek 			break;
781*d56f51eaSDavid van Moolenbroek 		case BPF_MISC:
782*d56f51eaSDavid van Moolenbroek 			switch (BPF_MISCOP(p->code)) {
783*d56f51eaSDavid van Moolenbroek 			case BPF_COP:
784*d56f51eaSDavid van Moolenbroek 			case BPF_COPX:
785*d56f51eaSDavid van Moolenbroek 				/* In-kernel COP use only. */
786*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
787*d56f51eaSDavid van Moolenbroek 				if (bc == NULL || bc->copfuncs == NULL)
788*d56f51eaSDavid van Moolenbroek 					goto out;
789*d56f51eaSDavid van Moolenbroek 				if (BPF_MISCOP(p->code) == BPF_COP &&
790*d56f51eaSDavid van Moolenbroek 				    p->k >= bc->nfuncs) {
791*d56f51eaSDavid van Moolenbroek 					goto out;
792*d56f51eaSDavid van Moolenbroek 				}
793*d56f51eaSDavid van Moolenbroek 				break;
794*d56f51eaSDavid van Moolenbroek #else
795*d56f51eaSDavid van Moolenbroek 				goto out;
796*d56f51eaSDavid van Moolenbroek #endif
797*d56f51eaSDavid van Moolenbroek 			default:
798*d56f51eaSDavid van Moolenbroek 				break;
799*d56f51eaSDavid van Moolenbroek 			}
800*d56f51eaSDavid van Moolenbroek 			break;
801*d56f51eaSDavid van Moolenbroek 		default:
802*d56f51eaSDavid van Moolenbroek 			goto out;
803*d56f51eaSDavid van Moolenbroek 		}
804*d56f51eaSDavid van Moolenbroek 	}
805*d56f51eaSDavid van Moolenbroek 	ok = 1;
806*d56f51eaSDavid van Moolenbroek out:
807*d56f51eaSDavid van Moolenbroek #if defined(KERNEL) || defined(_KERNEL)
808*d56f51eaSDavid van Moolenbroek 	kmem_free(mem, size);
809*d56f51eaSDavid van Moolenbroek #endif
810*d56f51eaSDavid van Moolenbroek 	return ok;
811*d56f51eaSDavid van Moolenbroek }
812