bpf_filter.c revision 172154
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 * 3650477Speter * $FreeBSD: head/sys/net/bpf_filter.c 172154 2007-09-13 09:00:32Z dwmalone $ 371541Srgrimes */ 381541Srgrimes 391541Srgrimes#include <sys/param.h> 401541Srgrimes 411541Srgrimes#ifdef sun 421541Srgrimes#include <netinet/in.h> 431541Srgrimes#endif 441541Srgrimes 4599419Speter#ifndef __i386__ 461541Srgrimes#define BPF_ALIGN 471541Srgrimes#endif 481541Srgrimes 491541Srgrimes#ifndef BPF_ALIGN 5040779Sdfr#define EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p)) 5140779Sdfr#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p)) 521541Srgrimes#else 531541Srgrimes#define EXTRACT_SHORT(p)\ 5440779Sdfr ((u_int16_t)\ 5540779Sdfr ((u_int16_t)*((u_char *)p+0)<<8|\ 5640779Sdfr (u_int16_t)*((u_char *)p+1)<<0)) 571541Srgrimes#define EXTRACT_LONG(p)\ 5840779Sdfr ((u_int32_t)*((u_char *)p+0)<<24|\ 5940779Sdfr (u_int32_t)*((u_char *)p+1)<<16|\ 6040779Sdfr (u_int32_t)*((u_char *)p+2)<<8|\ 6140779Sdfr (u_int32_t)*((u_char *)p+3)<<0) 621541Srgrimes#endif 631541Srgrimes 6455205Speter#ifdef _KERNEL 651541Srgrimes#include <sys/mbuf.h> 6641588Seivind#endif 6741588Seivind#include <net/bpf.h> 6855205Speter#ifdef _KERNEL 691541Srgrimes#define MINDEX(m, k) \ 701541Srgrimes{ \ 711541Srgrimes register int len = m->m_len; \ 721541Srgrimes \ 731541Srgrimes while (k >= len) { \ 741541Srgrimes k -= len; \ 751541Srgrimes m = m->m_next; \ 761541Srgrimes if (m == 0) \ 771541Srgrimes return 0; \ 781541Srgrimes len = m->m_len; \ 791541Srgrimes } \ 801541Srgrimes} 811541Srgrimes 8292725Salfredstatic u_int16_t m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err); 8392725Salfredstatic u_int32_t m_xword(struct mbuf *m, bpf_u_int32 k, int *err); 8412579Sbde 8541588Seivindstatic u_int32_t 861541Srgrimesm_xword(m, k, err) 871541Srgrimes register struct mbuf *m; 8841588Seivind register bpf_u_int32 k; 8941588Seivind register int *err; 901541Srgrimes{ 9141588Seivind register size_t len; 921541Srgrimes register u_char *cp, *np; 931541Srgrimes register struct mbuf *m0; 941541Srgrimes 951541Srgrimes len = m->m_len; 961541Srgrimes while (k >= len) { 971541Srgrimes k -= len; 981541Srgrimes m = m->m_next; 991541Srgrimes if (m == 0) 1001541Srgrimes goto bad; 1011541Srgrimes len = m->m_len; 1021541Srgrimes } 1031541Srgrimes cp = mtod(m, u_char *) + k; 1041541Srgrimes if (len - k >= 4) { 1051541Srgrimes *err = 0; 1061541Srgrimes return EXTRACT_LONG(cp); 1071541Srgrimes } 1081541Srgrimes m0 = m->m_next; 1091541Srgrimes if (m0 == 0 || m0->m_len + len - k < 4) 1101541Srgrimes goto bad; 1111541Srgrimes *err = 0; 1121541Srgrimes np = mtod(m0, u_char *); 1131541Srgrimes switch (len - k) { 1141541Srgrimes 1151541Srgrimes case 1: 11641588Seivind return 11741588Seivind ((u_int32_t)cp[0] << 24) | 11841588Seivind ((u_int32_t)np[0] << 16) | 11941588Seivind ((u_int32_t)np[1] << 8) | 12041588Seivind (u_int32_t)np[2]; 1211541Srgrimes 1221541Srgrimes case 2: 12341588Seivind return 12441588Seivind ((u_int32_t)cp[0] << 24) | 12541588Seivind ((u_int32_t)cp[1] << 16) | 12641588Seivind ((u_int32_t)np[0] << 8) | 12741588Seivind (u_int32_t)np[1]; 1281541Srgrimes 1291541Srgrimes default: 13041588Seivind return 13141588Seivind ((u_int32_t)cp[0] << 24) | 13241588Seivind ((u_int32_t)cp[1] << 16) | 13341588Seivind ((u_int32_t)cp[2] << 8) | 13441588Seivind (u_int32_t)np[0]; 1351541Srgrimes } 1361541Srgrimes bad: 1371541Srgrimes *err = 1; 1381541Srgrimes return 0; 1391541Srgrimes} 1401541Srgrimes 14141588Seivindstatic u_int16_t 1421541Srgrimesm_xhalf(m, k, err) 1431541Srgrimes register struct mbuf *m; 14441588Seivind register bpf_u_int32 k; 14541588Seivind register int *err; 1461541Srgrimes{ 14741588Seivind register size_t len; 1481541Srgrimes register u_char *cp; 1491541Srgrimes register struct mbuf *m0; 1501541Srgrimes 1511541Srgrimes len = m->m_len; 1521541Srgrimes while (k >= len) { 1531541Srgrimes k -= len; 1541541Srgrimes m = m->m_next; 1551541Srgrimes if (m == 0) 1561541Srgrimes goto bad; 1571541Srgrimes len = m->m_len; 1581541Srgrimes } 1591541Srgrimes cp = mtod(m, u_char *) + k; 1601541Srgrimes if (len - k >= 2) { 1611541Srgrimes *err = 0; 1621541Srgrimes return EXTRACT_SHORT(cp); 1631541Srgrimes } 1641541Srgrimes m0 = m->m_next; 1651541Srgrimes if (m0 == 0) 1661541Srgrimes goto bad; 1671541Srgrimes *err = 0; 1687543Sdg return (cp[0] << 8) | mtod(m0, u_char *)[0]; 1691541Srgrimes bad: 1701541Srgrimes *err = 1; 1711541Srgrimes return 0; 1721541Srgrimes} 1731541Srgrimes#endif 1741541Srgrimes 1751541Srgrimes/* 1761541Srgrimes * Execute the filter program starting at pc on the packet p 1771541Srgrimes * wirelen is the length of the original packet 1781541Srgrimes * buflen is the amount of data present 1791541Srgrimes */ 1801541Srgrimesu_int 1811541Srgrimesbpf_filter(pc, p, wirelen, buflen) 18254038Sarchie register const struct bpf_insn *pc; 1831541Srgrimes register u_char *p; 1841541Srgrimes u_int wirelen; 1851541Srgrimes register u_int buflen; 1861541Srgrimes{ 18740779Sdfr register u_int32_t A = 0, X = 0; 18841588Seivind register bpf_u_int32 k; 189172154Sdwmalone u_int32_t mem[BPF_MEMWORDS]; 1901541Srgrimes 1911541Srgrimes if (pc == 0) 1921541Srgrimes /* 1931541Srgrimes * No filter means accept all. 1941541Srgrimes */ 1951541Srgrimes return (u_int)-1; 1961549Srgrimes 1971541Srgrimes --pc; 1981541Srgrimes while (1) { 1991541Srgrimes ++pc; 2001541Srgrimes switch (pc->code) { 2011541Srgrimes 2021541Srgrimes default: 20355205Speter#ifdef _KERNEL 2041541Srgrimes return 0; 2051541Srgrimes#else 2061541Srgrimes abort(); 2078876Srgrimes#endif 2081541Srgrimes case BPF_RET|BPF_K: 2091541Srgrimes return (u_int)pc->k; 2101541Srgrimes 2111541Srgrimes case BPF_RET|BPF_A: 2121541Srgrimes return (u_int)A; 2131541Srgrimes 2141541Srgrimes case BPF_LD|BPF_W|BPF_ABS: 2151541Srgrimes k = pc->k; 21641588Seivind if (k > buflen || sizeof(int32_t) > buflen - k) { 21755205Speter#ifdef _KERNEL 2181541Srgrimes int merr; 2191541Srgrimes 2201541Srgrimes if (buflen != 0) 2211541Srgrimes return 0; 2221541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2231541Srgrimes if (merr != 0) 2241541Srgrimes return 0; 2251541Srgrimes continue; 2261541Srgrimes#else 2271541Srgrimes return 0; 2281541Srgrimes#endif 2291541Srgrimes } 2301541Srgrimes#ifdef BPF_ALIGN 23140779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2321541Srgrimes A = EXTRACT_LONG(&p[k]); 2331541Srgrimes else 2341541Srgrimes#endif 23540779Sdfr A = ntohl(*(int32_t *)(p + k)); 2361541Srgrimes continue; 2371541Srgrimes 2381541Srgrimes case BPF_LD|BPF_H|BPF_ABS: 2391541Srgrimes k = pc->k; 24041588Seivind if (k > buflen || sizeof(int16_t) > buflen - k) { 24155205Speter#ifdef _KERNEL 2421541Srgrimes int merr; 2431541Srgrimes 2441541Srgrimes if (buflen != 0) 2451541Srgrimes return 0; 2461541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 2471541Srgrimes continue; 2481541Srgrimes#else 2491541Srgrimes return 0; 2501541Srgrimes#endif 2511541Srgrimes } 2521541Srgrimes A = EXTRACT_SHORT(&p[k]); 2531541Srgrimes continue; 2541541Srgrimes 2551541Srgrimes case BPF_LD|BPF_B|BPF_ABS: 2561541Srgrimes k = pc->k; 2571541Srgrimes if (k >= buflen) { 25855205Speter#ifdef _KERNEL 2591541Srgrimes register struct mbuf *m; 2601541Srgrimes 2611541Srgrimes if (buflen != 0) 2621541Srgrimes return 0; 2631541Srgrimes m = (struct mbuf *)p; 2641541Srgrimes MINDEX(m, k); 2651541Srgrimes A = mtod(m, u_char *)[k]; 2661541Srgrimes continue; 2671541Srgrimes#else 2681541Srgrimes return 0; 2691541Srgrimes#endif 2701541Srgrimes } 2711541Srgrimes A = p[k]; 2721541Srgrimes continue; 2731541Srgrimes 2741541Srgrimes case BPF_LD|BPF_W|BPF_LEN: 2751541Srgrimes A = wirelen; 2761541Srgrimes continue; 2771541Srgrimes 2781541Srgrimes case BPF_LDX|BPF_W|BPF_LEN: 2791541Srgrimes X = wirelen; 2801541Srgrimes continue; 2811541Srgrimes 2821541Srgrimes case BPF_LD|BPF_W|BPF_IND: 2831541Srgrimes k = X + pc->k; 28445574Seivind if (pc->k > buflen || X > buflen - pc->k || 28545574Seivind sizeof(int32_t) > buflen - k) { 28655205Speter#ifdef _KERNEL 2871541Srgrimes int merr; 2881541Srgrimes 2891541Srgrimes if (buflen != 0) 2901541Srgrimes return 0; 2911541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2921541Srgrimes if (merr != 0) 2931541Srgrimes return 0; 2941541Srgrimes continue; 2951541Srgrimes#else 2961541Srgrimes return 0; 2971541Srgrimes#endif 2981541Srgrimes } 2991541Srgrimes#ifdef BPF_ALIGN 30040779Sdfr if (((intptr_t)(p + k) & 3) != 0) 3011541Srgrimes A = EXTRACT_LONG(&p[k]); 3021541Srgrimes else 3031541Srgrimes#endif 30440779Sdfr A = ntohl(*(int32_t *)(p + k)); 3051541Srgrimes continue; 3061541Srgrimes 3071541Srgrimes case BPF_LD|BPF_H|BPF_IND: 3081541Srgrimes k = X + pc->k; 30945574Seivind if (X > buflen || pc->k > buflen - X || 31045574Seivind sizeof(int16_t) > buflen - k) { 31155205Speter#ifdef _KERNEL 3121541Srgrimes int merr; 3131541Srgrimes 3141541Srgrimes if (buflen != 0) 3151541Srgrimes return 0; 3161541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 3171541Srgrimes if (merr != 0) 3181541Srgrimes return 0; 3191541Srgrimes continue; 3201541Srgrimes#else 3211541Srgrimes return 0; 3221541Srgrimes#endif 3231541Srgrimes } 3241541Srgrimes A = EXTRACT_SHORT(&p[k]); 3251541Srgrimes continue; 3261541Srgrimes 3271541Srgrimes case BPF_LD|BPF_B|BPF_IND: 3281541Srgrimes k = X + pc->k; 32948548Sbde if (pc->k >= buflen || X >= buflen - pc->k) { 33055205Speter#ifdef _KERNEL 3311541Srgrimes register struct mbuf *m; 3321541Srgrimes 3331541Srgrimes if (buflen != 0) 3341541Srgrimes return 0; 3351541Srgrimes m = (struct mbuf *)p; 3361541Srgrimes MINDEX(m, k); 337159018Sdwmalone A = mtod(m, u_char *)[k]; 3381541Srgrimes continue; 3391541Srgrimes#else 3401541Srgrimes return 0; 3411541Srgrimes#endif 3421541Srgrimes } 3431541Srgrimes A = p[k]; 3441541Srgrimes continue; 3451541Srgrimes 3461541Srgrimes case BPF_LDX|BPF_MSH|BPF_B: 3471541Srgrimes k = pc->k; 3481541Srgrimes if (k >= buflen) { 34955205Speter#ifdef _KERNEL 3501541Srgrimes register struct mbuf *m; 3511541Srgrimes 3521541Srgrimes if (buflen != 0) 3531541Srgrimes return 0; 3541541Srgrimes m = (struct mbuf *)p; 3551541Srgrimes MINDEX(m, k); 356159018Sdwmalone X = (mtod(m, u_char *)[k] & 0xf) << 2; 3571541Srgrimes continue; 3581541Srgrimes#else 3591541Srgrimes return 0; 3601541Srgrimes#endif 3611541Srgrimes } 3621541Srgrimes X = (p[pc->k] & 0xf) << 2; 3631541Srgrimes continue; 3641541Srgrimes 3651541Srgrimes case BPF_LD|BPF_IMM: 3661541Srgrimes A = pc->k; 3671541Srgrimes continue; 3681541Srgrimes 3691541Srgrimes case BPF_LDX|BPF_IMM: 3701541Srgrimes X = pc->k; 3711541Srgrimes continue; 3721541Srgrimes 3731541Srgrimes case BPF_LD|BPF_MEM: 3741541Srgrimes A = mem[pc->k]; 3751541Srgrimes continue; 3768876Srgrimes 3771541Srgrimes case BPF_LDX|BPF_MEM: 3781541Srgrimes X = mem[pc->k]; 3791541Srgrimes continue; 3801541Srgrimes 3811541Srgrimes case BPF_ST: 3821541Srgrimes mem[pc->k] = A; 3831541Srgrimes continue; 3841541Srgrimes 3851541Srgrimes case BPF_STX: 3861541Srgrimes mem[pc->k] = X; 3871541Srgrimes continue; 3881541Srgrimes 3891541Srgrimes case BPF_JMP|BPF_JA: 3901541Srgrimes pc += pc->k; 3911541Srgrimes continue; 3921541Srgrimes 3931541Srgrimes case BPF_JMP|BPF_JGT|BPF_K: 3941541Srgrimes pc += (A > pc->k) ? pc->jt : pc->jf; 3951541Srgrimes continue; 3961541Srgrimes 3971541Srgrimes case BPF_JMP|BPF_JGE|BPF_K: 3981541Srgrimes pc += (A >= pc->k) ? pc->jt : pc->jf; 3991541Srgrimes continue; 4001541Srgrimes 4011541Srgrimes case BPF_JMP|BPF_JEQ|BPF_K: 4021541Srgrimes pc += (A == pc->k) ? pc->jt : pc->jf; 4031541Srgrimes continue; 4041541Srgrimes 4051541Srgrimes case BPF_JMP|BPF_JSET|BPF_K: 4061541Srgrimes pc += (A & pc->k) ? pc->jt : pc->jf; 4071541Srgrimes continue; 4081541Srgrimes 4091541Srgrimes case BPF_JMP|BPF_JGT|BPF_X: 4101541Srgrimes pc += (A > X) ? pc->jt : pc->jf; 4111541Srgrimes continue; 4121541Srgrimes 4131541Srgrimes case BPF_JMP|BPF_JGE|BPF_X: 4141541Srgrimes pc += (A >= X) ? pc->jt : pc->jf; 4151541Srgrimes continue; 4161541Srgrimes 4171541Srgrimes case BPF_JMP|BPF_JEQ|BPF_X: 4181541Srgrimes pc += (A == X) ? pc->jt : pc->jf; 4191541Srgrimes continue; 4201541Srgrimes 4211541Srgrimes case BPF_JMP|BPF_JSET|BPF_X: 4221541Srgrimes pc += (A & X) ? pc->jt : pc->jf; 4231541Srgrimes continue; 4241541Srgrimes 4251541Srgrimes case BPF_ALU|BPF_ADD|BPF_X: 4261541Srgrimes A += X; 4271541Srgrimes continue; 4288876Srgrimes 4291541Srgrimes case BPF_ALU|BPF_SUB|BPF_X: 4301541Srgrimes A -= X; 4311541Srgrimes continue; 4328876Srgrimes 4331541Srgrimes case BPF_ALU|BPF_MUL|BPF_X: 4341541Srgrimes A *= X; 4351541Srgrimes continue; 4368876Srgrimes 4371541Srgrimes case BPF_ALU|BPF_DIV|BPF_X: 4381541Srgrimes if (X == 0) 4391541Srgrimes return 0; 4401541Srgrimes A /= X; 4411541Srgrimes continue; 4428876Srgrimes 4431541Srgrimes case BPF_ALU|BPF_AND|BPF_X: 4441541Srgrimes A &= X; 4451541Srgrimes continue; 4468876Srgrimes 4471541Srgrimes case BPF_ALU|BPF_OR|BPF_X: 4481541Srgrimes A |= X; 4491541Srgrimes continue; 4501541Srgrimes 4511541Srgrimes case BPF_ALU|BPF_LSH|BPF_X: 4521541Srgrimes A <<= X; 4531541Srgrimes continue; 4541541Srgrimes 4551541Srgrimes case BPF_ALU|BPF_RSH|BPF_X: 4561541Srgrimes A >>= X; 4571541Srgrimes continue; 4581541Srgrimes 4591541Srgrimes case BPF_ALU|BPF_ADD|BPF_K: 4601541Srgrimes A += pc->k; 4611541Srgrimes continue; 4628876Srgrimes 4631541Srgrimes case BPF_ALU|BPF_SUB|BPF_K: 4641541Srgrimes A -= pc->k; 4651541Srgrimes continue; 4668876Srgrimes 4671541Srgrimes case BPF_ALU|BPF_MUL|BPF_K: 4681541Srgrimes A *= pc->k; 4691541Srgrimes continue; 4708876Srgrimes 4711541Srgrimes case BPF_ALU|BPF_DIV|BPF_K: 4721541Srgrimes A /= pc->k; 4731541Srgrimes continue; 4748876Srgrimes 4751541Srgrimes case BPF_ALU|BPF_AND|BPF_K: 4761541Srgrimes A &= pc->k; 4771541Srgrimes continue; 4788876Srgrimes 4791541Srgrimes case BPF_ALU|BPF_OR|BPF_K: 4801541Srgrimes A |= pc->k; 4811541Srgrimes continue; 4821541Srgrimes 4831541Srgrimes case BPF_ALU|BPF_LSH|BPF_K: 4841541Srgrimes A <<= pc->k; 4851541Srgrimes continue; 4861541Srgrimes 4871541Srgrimes case BPF_ALU|BPF_RSH|BPF_K: 4881541Srgrimes A >>= pc->k; 4891541Srgrimes continue; 4901541Srgrimes 4911541Srgrimes case BPF_ALU|BPF_NEG: 4921541Srgrimes A = -A; 4931541Srgrimes continue; 4941541Srgrimes 4951541Srgrimes case BPF_MISC|BPF_TAX: 4961541Srgrimes X = A; 4971541Srgrimes continue; 4981541Srgrimes 4991541Srgrimes case BPF_MISC|BPF_TXA: 5001541Srgrimes A = X; 5011541Srgrimes continue; 5021541Srgrimes } 5031541Srgrimes } 5041541Srgrimes} 5051541Srgrimes 50655205Speter#ifdef _KERNEL 5071541Srgrimes/* 5081541Srgrimes * Return true if the 'fcode' is a valid filter program. 5091541Srgrimes * The constraints are that each jump be forward and to a valid 5108876Srgrimes * code. The code must terminate with either an accept or reject. 5111541Srgrimes * 5121541Srgrimes * The kernel needs to be able to verify an application's filter code. 5131541Srgrimes * Otherwise, a bogus program could easily crash the system. 5141541Srgrimes */ 5151541Srgrimesint 5161541Srgrimesbpf_validate(f, len) 51754038Sarchie const struct bpf_insn *f; 5181541Srgrimes int len; 5191541Srgrimes{ 5201541Srgrimes register int i; 52154038Sarchie register const struct bpf_insn *p; 5221541Srgrimes 523153996Sjkim /* Do not accept negative length filter. */ 524153996Sjkim if (len < 0) 525153996Sjkim return 0; 526153996Sjkim 527153996Sjkim /* An empty filter means accept all. */ 528153996Sjkim if (len == 0) 529153995Sjkim return 1; 530153221Sjkim 5311541Srgrimes for (i = 0; i < len; ++i) { 5321541Srgrimes /* 5338876Srgrimes * Check that that jumps are forward, and within 5341541Srgrimes * the code block. 5351541Srgrimes */ 5361541Srgrimes p = &f[i]; 5371541Srgrimes if (BPF_CLASS(p->code) == BPF_JMP) { 5381541Srgrimes register int from = i + 1; 5391541Srgrimes 5401541Srgrimes if (BPF_OP(p->code) == BPF_JA) { 54141588Seivind if (from >= len || p->k >= len - from) 5421541Srgrimes return 0; 5431541Srgrimes } 54445574Seivind else if (from >= len || p->jt >= len - from || 54545574Seivind p->jf >= len - from) 5461541Srgrimes return 0; 5471541Srgrimes } 5481541Srgrimes /* 5491541Srgrimes * Check that memory operations use valid addresses. 5501541Srgrimes */ 5511541Srgrimes if ((BPF_CLASS(p->code) == BPF_ST || 5528876Srgrimes (BPF_CLASS(p->code) == BPF_LD && 5531541Srgrimes (p->code & 0xe0) == BPF_MEM)) && 55441588Seivind p->k >= BPF_MEMWORDS) 5551541Srgrimes return 0; 5561541Srgrimes /* 5571541Srgrimes * Check for constant division by 0. 5581541Srgrimes */ 5591541Srgrimes if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) 5601541Srgrimes return 0; 5611541Srgrimes } 5621541Srgrimes return BPF_CLASS(f[len - 1].code) == BPF_RET; 5631541Srgrimes} 5641541Srgrimes#endif 565