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