bpf_filter.c revision 174895
1139823Simp/*- 21541Srgrimes * Copyright (c) 1990, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from the Stanford/CMU enet packet filter, 61541Srgrimes * (net/enet.c) distributed as part of 4.3BSD, and code contributed 71541Srgrimes * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 81541Srgrimes * Berkeley Laboratory. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 4. Neither the name of the University nor the names of its contributors 191541Srgrimes * may be used to endorse or promote products derived from this software 201541Srgrimes * without specific prior written permission. 211541Srgrimes * 221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321541Srgrimes * SUCH DAMAGE. 331541Srgrimes * 341541Srgrimes * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93 351541Srgrimes */ 361541Srgrimes 37174895Srwatson#include <sys/cdefs.h> 38174895Srwatson__FBSDID("$FreeBSD: head/sys/net/bpf_filter.c 174895 2007-12-25 13:24:02Z rwatson $"); 39174895Srwatson 401541Srgrimes#include <sys/param.h> 411541Srgrimes 421541Srgrimes#ifdef sun 431541Srgrimes#include <netinet/in.h> 441541Srgrimes#endif 451541Srgrimes 4699419Speter#ifndef __i386__ 471541Srgrimes#define BPF_ALIGN 481541Srgrimes#endif 491541Srgrimes 501541Srgrimes#ifndef BPF_ALIGN 5140779Sdfr#define EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p)) 5240779Sdfr#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p)) 531541Srgrimes#else 541541Srgrimes#define EXTRACT_SHORT(p)\ 5540779Sdfr ((u_int16_t)\ 5640779Sdfr ((u_int16_t)*((u_char *)p+0)<<8|\ 5740779Sdfr (u_int16_t)*((u_char *)p+1)<<0)) 581541Srgrimes#define EXTRACT_LONG(p)\ 5940779Sdfr ((u_int32_t)*((u_char *)p+0)<<24|\ 6040779Sdfr (u_int32_t)*((u_char *)p+1)<<16|\ 6140779Sdfr (u_int32_t)*((u_char *)p+2)<<8|\ 6240779Sdfr (u_int32_t)*((u_char *)p+3)<<0) 631541Srgrimes#endif 641541Srgrimes 6555205Speter#ifdef _KERNEL 661541Srgrimes#include <sys/mbuf.h> 6741588Seivind#endif 6841588Seivind#include <net/bpf.h> 6955205Speter#ifdef _KERNEL 701541Srgrimes#define MINDEX(m, k) \ 711541Srgrimes{ \ 721541Srgrimes register int len = m->m_len; \ 731541Srgrimes \ 741541Srgrimes while (k >= len) { \ 751541Srgrimes k -= len; \ 761541Srgrimes m = m->m_next; \ 771541Srgrimes if (m == 0) \ 781541Srgrimes return 0; \ 791541Srgrimes len = m->m_len; \ 801541Srgrimes } \ 811541Srgrimes} 821541Srgrimes 8392725Salfredstatic u_int16_t m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err); 8492725Salfredstatic u_int32_t m_xword(struct mbuf *m, bpf_u_int32 k, int *err); 8512579Sbde 8641588Seivindstatic u_int32_t 871541Srgrimesm_xword(m, k, err) 881541Srgrimes register struct mbuf *m; 8941588Seivind register bpf_u_int32 k; 9041588Seivind register int *err; 911541Srgrimes{ 9241588Seivind register size_t len; 931541Srgrimes register u_char *cp, *np; 941541Srgrimes register struct mbuf *m0; 951541Srgrimes 961541Srgrimes len = m->m_len; 971541Srgrimes while (k >= len) { 981541Srgrimes k -= len; 991541Srgrimes m = m->m_next; 1001541Srgrimes if (m == 0) 1011541Srgrimes goto bad; 1021541Srgrimes len = m->m_len; 1031541Srgrimes } 1041541Srgrimes cp = mtod(m, u_char *) + k; 1051541Srgrimes if (len - k >= 4) { 1061541Srgrimes *err = 0; 1071541Srgrimes return EXTRACT_LONG(cp); 1081541Srgrimes } 1091541Srgrimes m0 = m->m_next; 1101541Srgrimes if (m0 == 0 || m0->m_len + len - k < 4) 1111541Srgrimes goto bad; 1121541Srgrimes *err = 0; 1131541Srgrimes np = mtod(m0, u_char *); 1141541Srgrimes switch (len - k) { 1151541Srgrimes 1161541Srgrimes case 1: 11741588Seivind return 11841588Seivind ((u_int32_t)cp[0] << 24) | 11941588Seivind ((u_int32_t)np[0] << 16) | 12041588Seivind ((u_int32_t)np[1] << 8) | 12141588Seivind (u_int32_t)np[2]; 1221541Srgrimes 1231541Srgrimes case 2: 12441588Seivind return 12541588Seivind ((u_int32_t)cp[0] << 24) | 12641588Seivind ((u_int32_t)cp[1] << 16) | 12741588Seivind ((u_int32_t)np[0] << 8) | 12841588Seivind (u_int32_t)np[1]; 1291541Srgrimes 1301541Srgrimes default: 13141588Seivind return 13241588Seivind ((u_int32_t)cp[0] << 24) | 13341588Seivind ((u_int32_t)cp[1] << 16) | 13441588Seivind ((u_int32_t)cp[2] << 8) | 13541588Seivind (u_int32_t)np[0]; 1361541Srgrimes } 1371541Srgrimes bad: 1381541Srgrimes *err = 1; 1391541Srgrimes return 0; 1401541Srgrimes} 1411541Srgrimes 14241588Seivindstatic u_int16_t 1431541Srgrimesm_xhalf(m, k, err) 1441541Srgrimes register struct mbuf *m; 14541588Seivind register bpf_u_int32 k; 14641588Seivind register int *err; 1471541Srgrimes{ 14841588Seivind register size_t len; 1491541Srgrimes register u_char *cp; 1501541Srgrimes register struct mbuf *m0; 1511541Srgrimes 1521541Srgrimes len = m->m_len; 1531541Srgrimes while (k >= len) { 1541541Srgrimes k -= len; 1551541Srgrimes m = m->m_next; 1561541Srgrimes if (m == 0) 1571541Srgrimes goto bad; 1581541Srgrimes len = m->m_len; 1591541Srgrimes } 1601541Srgrimes cp = mtod(m, u_char *) + k; 1611541Srgrimes if (len - k >= 2) { 1621541Srgrimes *err = 0; 1631541Srgrimes return EXTRACT_SHORT(cp); 1641541Srgrimes } 1651541Srgrimes m0 = m->m_next; 1661541Srgrimes if (m0 == 0) 1671541Srgrimes goto bad; 1681541Srgrimes *err = 0; 1697543Sdg return (cp[0] << 8) | mtod(m0, u_char *)[0]; 1701541Srgrimes bad: 1711541Srgrimes *err = 1; 1721541Srgrimes return 0; 1731541Srgrimes} 1741541Srgrimes#endif 1751541Srgrimes 1761541Srgrimes/* 1771541Srgrimes * Execute the filter program starting at pc on the packet p 1781541Srgrimes * wirelen is the length of the original packet 1791541Srgrimes * buflen is the amount of data present 1801541Srgrimes */ 1811541Srgrimesu_int 1821541Srgrimesbpf_filter(pc, p, wirelen, buflen) 18354038Sarchie register const struct bpf_insn *pc; 1841541Srgrimes register u_char *p; 1851541Srgrimes u_int wirelen; 1861541Srgrimes register u_int buflen; 1871541Srgrimes{ 18840779Sdfr register u_int32_t A = 0, X = 0; 18941588Seivind register bpf_u_int32 k; 190172154Sdwmalone u_int32_t mem[BPF_MEMWORDS]; 1911541Srgrimes 1921541Srgrimes if (pc == 0) 1931541Srgrimes /* 1941541Srgrimes * No filter means accept all. 1951541Srgrimes */ 1961541Srgrimes return (u_int)-1; 1971549Srgrimes 1981541Srgrimes --pc; 1991541Srgrimes while (1) { 2001541Srgrimes ++pc; 2011541Srgrimes switch (pc->code) { 2021541Srgrimes 2031541Srgrimes default: 20455205Speter#ifdef _KERNEL 2051541Srgrimes return 0; 2061541Srgrimes#else 2071541Srgrimes abort(); 2088876Srgrimes#endif 2091541Srgrimes case BPF_RET|BPF_K: 2101541Srgrimes return (u_int)pc->k; 2111541Srgrimes 2121541Srgrimes case BPF_RET|BPF_A: 2131541Srgrimes return (u_int)A; 2141541Srgrimes 2151541Srgrimes case BPF_LD|BPF_W|BPF_ABS: 2161541Srgrimes k = pc->k; 21741588Seivind if (k > buflen || sizeof(int32_t) > buflen - k) { 21855205Speter#ifdef _KERNEL 2191541Srgrimes int merr; 2201541Srgrimes 2211541Srgrimes if (buflen != 0) 2221541Srgrimes return 0; 2231541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2241541Srgrimes if (merr != 0) 2251541Srgrimes return 0; 2261541Srgrimes continue; 2271541Srgrimes#else 2281541Srgrimes return 0; 2291541Srgrimes#endif 2301541Srgrimes } 2311541Srgrimes#ifdef BPF_ALIGN 23240779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2331541Srgrimes A = EXTRACT_LONG(&p[k]); 2341541Srgrimes else 2351541Srgrimes#endif 23640779Sdfr A = ntohl(*(int32_t *)(p + k)); 2371541Srgrimes continue; 2381541Srgrimes 2391541Srgrimes case BPF_LD|BPF_H|BPF_ABS: 2401541Srgrimes k = pc->k; 24141588Seivind if (k > buflen || sizeof(int16_t) > buflen - k) { 24255205Speter#ifdef _KERNEL 2431541Srgrimes int merr; 2441541Srgrimes 2451541Srgrimes if (buflen != 0) 2461541Srgrimes return 0; 2471541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 2481541Srgrimes continue; 2491541Srgrimes#else 2501541Srgrimes return 0; 2511541Srgrimes#endif 2521541Srgrimes } 2531541Srgrimes A = EXTRACT_SHORT(&p[k]); 2541541Srgrimes continue; 2551541Srgrimes 2561541Srgrimes case BPF_LD|BPF_B|BPF_ABS: 2571541Srgrimes k = pc->k; 2581541Srgrimes if (k >= buflen) { 25955205Speter#ifdef _KERNEL 2601541Srgrimes register struct mbuf *m; 2611541Srgrimes 2621541Srgrimes if (buflen != 0) 2631541Srgrimes return 0; 2641541Srgrimes m = (struct mbuf *)p; 2651541Srgrimes MINDEX(m, k); 2661541Srgrimes A = mtod(m, u_char *)[k]; 2671541Srgrimes continue; 2681541Srgrimes#else 2691541Srgrimes return 0; 2701541Srgrimes#endif 2711541Srgrimes } 2721541Srgrimes A = p[k]; 2731541Srgrimes continue; 2741541Srgrimes 2751541Srgrimes case BPF_LD|BPF_W|BPF_LEN: 2761541Srgrimes A = wirelen; 2771541Srgrimes continue; 2781541Srgrimes 2791541Srgrimes case BPF_LDX|BPF_W|BPF_LEN: 2801541Srgrimes X = wirelen; 2811541Srgrimes continue; 2821541Srgrimes 2831541Srgrimes case BPF_LD|BPF_W|BPF_IND: 2841541Srgrimes k = X + pc->k; 28545574Seivind if (pc->k > buflen || X > buflen - pc->k || 28645574Seivind sizeof(int32_t) > buflen - k) { 28755205Speter#ifdef _KERNEL 2881541Srgrimes int merr; 2891541Srgrimes 2901541Srgrimes if (buflen != 0) 2911541Srgrimes return 0; 2921541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2931541Srgrimes if (merr != 0) 2941541Srgrimes return 0; 2951541Srgrimes continue; 2961541Srgrimes#else 2971541Srgrimes return 0; 2981541Srgrimes#endif 2991541Srgrimes } 3001541Srgrimes#ifdef BPF_ALIGN 30140779Sdfr if (((intptr_t)(p + k) & 3) != 0) 3021541Srgrimes A = EXTRACT_LONG(&p[k]); 3031541Srgrimes else 3041541Srgrimes#endif 30540779Sdfr A = ntohl(*(int32_t *)(p + k)); 3061541Srgrimes continue; 3071541Srgrimes 3081541Srgrimes case BPF_LD|BPF_H|BPF_IND: 3091541Srgrimes k = X + pc->k; 31045574Seivind if (X > buflen || pc->k > buflen - X || 31145574Seivind sizeof(int16_t) > buflen - k) { 31255205Speter#ifdef _KERNEL 3131541Srgrimes int merr; 3141541Srgrimes 3151541Srgrimes if (buflen != 0) 3161541Srgrimes return 0; 3171541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 3181541Srgrimes if (merr != 0) 3191541Srgrimes return 0; 3201541Srgrimes continue; 3211541Srgrimes#else 3221541Srgrimes return 0; 3231541Srgrimes#endif 3241541Srgrimes } 3251541Srgrimes A = EXTRACT_SHORT(&p[k]); 3261541Srgrimes continue; 3271541Srgrimes 3281541Srgrimes case BPF_LD|BPF_B|BPF_IND: 3291541Srgrimes k = X + pc->k; 33048548Sbde if (pc->k >= buflen || X >= buflen - pc->k) { 33155205Speter#ifdef _KERNEL 3321541Srgrimes register struct mbuf *m; 3331541Srgrimes 3341541Srgrimes if (buflen != 0) 3351541Srgrimes return 0; 3361541Srgrimes m = (struct mbuf *)p; 3371541Srgrimes MINDEX(m, k); 338159018Sdwmalone A = mtod(m, u_char *)[k]; 3391541Srgrimes continue; 3401541Srgrimes#else 3411541Srgrimes return 0; 3421541Srgrimes#endif 3431541Srgrimes } 3441541Srgrimes A = p[k]; 3451541Srgrimes continue; 3461541Srgrimes 3471541Srgrimes case BPF_LDX|BPF_MSH|BPF_B: 3481541Srgrimes k = pc->k; 3491541Srgrimes if (k >= buflen) { 35055205Speter#ifdef _KERNEL 3511541Srgrimes register struct mbuf *m; 3521541Srgrimes 3531541Srgrimes if (buflen != 0) 3541541Srgrimes return 0; 3551541Srgrimes m = (struct mbuf *)p; 3561541Srgrimes MINDEX(m, k); 357159018Sdwmalone X = (mtod(m, u_char *)[k] & 0xf) << 2; 3581541Srgrimes continue; 3591541Srgrimes#else 3601541Srgrimes return 0; 3611541Srgrimes#endif 3621541Srgrimes } 3631541Srgrimes X = (p[pc->k] & 0xf) << 2; 3641541Srgrimes continue; 3651541Srgrimes 3661541Srgrimes case BPF_LD|BPF_IMM: 3671541Srgrimes A = pc->k; 3681541Srgrimes continue; 3691541Srgrimes 3701541Srgrimes case BPF_LDX|BPF_IMM: 3711541Srgrimes X = pc->k; 3721541Srgrimes continue; 3731541Srgrimes 3741541Srgrimes case BPF_LD|BPF_MEM: 3751541Srgrimes A = mem[pc->k]; 3761541Srgrimes continue; 3778876Srgrimes 3781541Srgrimes case BPF_LDX|BPF_MEM: 3791541Srgrimes X = mem[pc->k]; 3801541Srgrimes continue; 3811541Srgrimes 3821541Srgrimes case BPF_ST: 3831541Srgrimes mem[pc->k] = A; 3841541Srgrimes continue; 3851541Srgrimes 3861541Srgrimes case BPF_STX: 3871541Srgrimes mem[pc->k] = X; 3881541Srgrimes continue; 3891541Srgrimes 3901541Srgrimes case BPF_JMP|BPF_JA: 3911541Srgrimes pc += pc->k; 3921541Srgrimes continue; 3931541Srgrimes 3941541Srgrimes case BPF_JMP|BPF_JGT|BPF_K: 3951541Srgrimes pc += (A > pc->k) ? pc->jt : pc->jf; 3961541Srgrimes continue; 3971541Srgrimes 3981541Srgrimes case BPF_JMP|BPF_JGE|BPF_K: 3991541Srgrimes pc += (A >= pc->k) ? pc->jt : pc->jf; 4001541Srgrimes continue; 4011541Srgrimes 4021541Srgrimes case BPF_JMP|BPF_JEQ|BPF_K: 4031541Srgrimes pc += (A == pc->k) ? pc->jt : pc->jf; 4041541Srgrimes continue; 4051541Srgrimes 4061541Srgrimes case BPF_JMP|BPF_JSET|BPF_K: 4071541Srgrimes pc += (A & pc->k) ? pc->jt : pc->jf; 4081541Srgrimes continue; 4091541Srgrimes 4101541Srgrimes case BPF_JMP|BPF_JGT|BPF_X: 4111541Srgrimes pc += (A > X) ? pc->jt : pc->jf; 4121541Srgrimes continue; 4131541Srgrimes 4141541Srgrimes case BPF_JMP|BPF_JGE|BPF_X: 4151541Srgrimes pc += (A >= X) ? pc->jt : pc->jf; 4161541Srgrimes continue; 4171541Srgrimes 4181541Srgrimes case BPF_JMP|BPF_JEQ|BPF_X: 4191541Srgrimes pc += (A == X) ? pc->jt : pc->jf; 4201541Srgrimes continue; 4211541Srgrimes 4221541Srgrimes case BPF_JMP|BPF_JSET|BPF_X: 4231541Srgrimes pc += (A & X) ? pc->jt : pc->jf; 4241541Srgrimes continue; 4251541Srgrimes 4261541Srgrimes case BPF_ALU|BPF_ADD|BPF_X: 4271541Srgrimes A += X; 4281541Srgrimes continue; 4298876Srgrimes 4301541Srgrimes case BPF_ALU|BPF_SUB|BPF_X: 4311541Srgrimes A -= X; 4321541Srgrimes continue; 4338876Srgrimes 4341541Srgrimes case BPF_ALU|BPF_MUL|BPF_X: 4351541Srgrimes A *= X; 4361541Srgrimes continue; 4378876Srgrimes 4381541Srgrimes case BPF_ALU|BPF_DIV|BPF_X: 4391541Srgrimes if (X == 0) 4401541Srgrimes return 0; 4411541Srgrimes A /= X; 4421541Srgrimes continue; 4438876Srgrimes 4441541Srgrimes case BPF_ALU|BPF_AND|BPF_X: 4451541Srgrimes A &= X; 4461541Srgrimes continue; 4478876Srgrimes 4481541Srgrimes case BPF_ALU|BPF_OR|BPF_X: 4491541Srgrimes A |= X; 4501541Srgrimes continue; 4511541Srgrimes 4521541Srgrimes case BPF_ALU|BPF_LSH|BPF_X: 4531541Srgrimes A <<= X; 4541541Srgrimes continue; 4551541Srgrimes 4561541Srgrimes case BPF_ALU|BPF_RSH|BPF_X: 4571541Srgrimes A >>= X; 4581541Srgrimes continue; 4591541Srgrimes 4601541Srgrimes case BPF_ALU|BPF_ADD|BPF_K: 4611541Srgrimes A += pc->k; 4621541Srgrimes continue; 4638876Srgrimes 4641541Srgrimes case BPF_ALU|BPF_SUB|BPF_K: 4651541Srgrimes A -= pc->k; 4661541Srgrimes continue; 4678876Srgrimes 4681541Srgrimes case BPF_ALU|BPF_MUL|BPF_K: 4691541Srgrimes A *= pc->k; 4701541Srgrimes continue; 4718876Srgrimes 4721541Srgrimes case BPF_ALU|BPF_DIV|BPF_K: 4731541Srgrimes A /= pc->k; 4741541Srgrimes continue; 4758876Srgrimes 4761541Srgrimes case BPF_ALU|BPF_AND|BPF_K: 4771541Srgrimes A &= pc->k; 4781541Srgrimes continue; 4798876Srgrimes 4801541Srgrimes case BPF_ALU|BPF_OR|BPF_K: 4811541Srgrimes A |= pc->k; 4821541Srgrimes continue; 4831541Srgrimes 4841541Srgrimes case BPF_ALU|BPF_LSH|BPF_K: 4851541Srgrimes A <<= pc->k; 4861541Srgrimes continue; 4871541Srgrimes 4881541Srgrimes case BPF_ALU|BPF_RSH|BPF_K: 4891541Srgrimes A >>= pc->k; 4901541Srgrimes continue; 4911541Srgrimes 4921541Srgrimes case BPF_ALU|BPF_NEG: 4931541Srgrimes A = -A; 4941541Srgrimes continue; 4951541Srgrimes 4961541Srgrimes case BPF_MISC|BPF_TAX: 4971541Srgrimes X = A; 4981541Srgrimes continue; 4991541Srgrimes 5001541Srgrimes case BPF_MISC|BPF_TXA: 5011541Srgrimes A = X; 5021541Srgrimes continue; 5031541Srgrimes } 5041541Srgrimes } 5051541Srgrimes} 5061541Srgrimes 50755205Speter#ifdef _KERNEL 5081541Srgrimes/* 5091541Srgrimes * Return true if the 'fcode' is a valid filter program. 5101541Srgrimes * The constraints are that each jump be forward and to a valid 5118876Srgrimes * code. The code must terminate with either an accept or reject. 5121541Srgrimes * 5131541Srgrimes * The kernel needs to be able to verify an application's filter code. 5141541Srgrimes * Otherwise, a bogus program could easily crash the system. 5151541Srgrimes */ 5161541Srgrimesint 5171541Srgrimesbpf_validate(f, len) 51854038Sarchie const struct bpf_insn *f; 5191541Srgrimes int len; 5201541Srgrimes{ 5211541Srgrimes register int i; 52254038Sarchie register const struct bpf_insn *p; 5231541Srgrimes 524153996Sjkim /* Do not accept negative length filter. */ 525153996Sjkim if (len < 0) 526153996Sjkim return 0; 527153996Sjkim 528153996Sjkim /* An empty filter means accept all. */ 529153996Sjkim if (len == 0) 530153995Sjkim return 1; 531153221Sjkim 5321541Srgrimes for (i = 0; i < len; ++i) { 5331541Srgrimes /* 5348876Srgrimes * Check that that jumps are forward, and within 5351541Srgrimes * the code block. 5361541Srgrimes */ 5371541Srgrimes p = &f[i]; 5381541Srgrimes if (BPF_CLASS(p->code) == BPF_JMP) { 5391541Srgrimes register int from = i + 1; 5401541Srgrimes 5411541Srgrimes if (BPF_OP(p->code) == BPF_JA) { 54241588Seivind if (from >= len || p->k >= len - from) 5431541Srgrimes return 0; 5441541Srgrimes } 54545574Seivind else if (from >= len || p->jt >= len - from || 54645574Seivind p->jf >= len - from) 5471541Srgrimes return 0; 5481541Srgrimes } 5491541Srgrimes /* 5501541Srgrimes * Check that memory operations use valid addresses. 5511541Srgrimes */ 5521541Srgrimes if ((BPF_CLASS(p->code) == BPF_ST || 5538876Srgrimes (BPF_CLASS(p->code) == BPF_LD && 5541541Srgrimes (p->code & 0xe0) == BPF_MEM)) && 55541588Seivind p->k >= BPF_MEMWORDS) 5561541Srgrimes return 0; 5571541Srgrimes /* 5581541Srgrimes * Check for constant division by 0. 5591541Srgrimes */ 5601541Srgrimes if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) 5611541Srgrimes return 0; 5621541Srgrimes } 5631541Srgrimes return BPF_CLASS(f[len - 1].code) == BPF_RET; 5641541Srgrimes} 5651541Srgrimes#endif 566