bpf_filter.c revision 182454
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 182454 2008-08-29 19:10:51Z jkim $"); 39174895Srwatson 401541Srgrimes#include <sys/param.h> 411541Srgrimes 42182184Sjkim#if !defined(_KERNEL) || defined(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> 67182184Sjkim#else 68182184Sjkim#include <stdlib.h> 6941588Seivind#endif 7041588Seivind#include <net/bpf.h> 7155205Speter#ifdef _KERNEL 721541Srgrimes#define MINDEX(m, k) \ 731541Srgrimes{ \ 741541Srgrimes register int len = m->m_len; \ 751541Srgrimes \ 761541Srgrimes while (k >= len) { \ 771541Srgrimes k -= len; \ 781541Srgrimes m = m->m_next; \ 791541Srgrimes if (m == 0) \ 801541Srgrimes return 0; \ 811541Srgrimes len = m->m_len; \ 821541Srgrimes } \ 831541Srgrimes} 841541Srgrimes 8592725Salfredstatic u_int16_t m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err); 8692725Salfredstatic u_int32_t m_xword(struct mbuf *m, bpf_u_int32 k, int *err); 8712579Sbde 8841588Seivindstatic u_int32_t 89177003Srwatsonm_xword(struct mbuf *m, bpf_u_int32 k, int *err) 901541Srgrimes{ 91177003Srwatson size_t len; 92177003Srwatson u_char *cp, *np; 93177003Srwatson 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 case 1: 11541588Seivind return 11641588Seivind ((u_int32_t)cp[0] << 24) | 11741588Seivind ((u_int32_t)np[0] << 16) | 11841588Seivind ((u_int32_t)np[1] << 8) | 11941588Seivind (u_int32_t)np[2]; 1201541Srgrimes 1211541Srgrimes case 2: 12241588Seivind return 12341588Seivind ((u_int32_t)cp[0] << 24) | 12441588Seivind ((u_int32_t)cp[1] << 16) | 12541588Seivind ((u_int32_t)np[0] << 8) | 12641588Seivind (u_int32_t)np[1]; 1271541Srgrimes 1281541Srgrimes default: 12941588Seivind return 13041588Seivind ((u_int32_t)cp[0] << 24) | 13141588Seivind ((u_int32_t)cp[1] << 16) | 13241588Seivind ((u_int32_t)cp[2] << 8) | 13341588Seivind (u_int32_t)np[0]; 1341541Srgrimes } 1351541Srgrimes bad: 1361541Srgrimes *err = 1; 137177003Srwatson return (0); 1381541Srgrimes} 1391541Srgrimes 14041588Seivindstatic u_int16_t 141177003Srwatsonm_xhalf(struct mbuf *m, bpf_u_int32 k, int *err) 1421541Srgrimes{ 143177003Srwatson size_t len; 144177003Srwatson u_char *cp; 145177003Srwatson struct mbuf *m0; 1461541Srgrimes 1471541Srgrimes len = m->m_len; 1481541Srgrimes while (k >= len) { 1491541Srgrimes k -= len; 1501541Srgrimes m = m->m_next; 1511541Srgrimes if (m == 0) 1521541Srgrimes goto bad; 1531541Srgrimes len = m->m_len; 1541541Srgrimes } 1551541Srgrimes cp = mtod(m, u_char *) + k; 1561541Srgrimes if (len - k >= 2) { 1571541Srgrimes *err = 0; 158177003Srwatson return (EXTRACT_SHORT(cp)); 1591541Srgrimes } 1601541Srgrimes m0 = m->m_next; 1611541Srgrimes if (m0 == 0) 1621541Srgrimes goto bad; 1631541Srgrimes *err = 0; 164177003Srwatson return ((cp[0] << 8) | mtod(m0, u_char *)[0]); 1651541Srgrimes bad: 1661541Srgrimes *err = 1; 167177003Srwatson return (0); 1681541Srgrimes} 1691541Srgrimes#endif 1701541Srgrimes 1711541Srgrimes/* 1721541Srgrimes * Execute the filter program starting at pc on the packet p 1731541Srgrimes * wirelen is the length of the original packet 1741541Srgrimes * buflen is the amount of data present 1751541Srgrimes */ 1761541Srgrimesu_int 177177003Srwatsonbpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) 1781541Srgrimes{ 179177003Srwatson u_int32_t A = 0, X = 0; 180177003Srwatson bpf_u_int32 k; 181172154Sdwmalone u_int32_t mem[BPF_MEMWORDS]; 1821541Srgrimes 183177003Srwatson if (pc == NULL) 1841541Srgrimes /* 1851541Srgrimes * No filter means accept all. 1861541Srgrimes */ 187177003Srwatson return ((u_int)-1); 1881549Srgrimes 1891541Srgrimes --pc; 1901541Srgrimes while (1) { 1911541Srgrimes ++pc; 1921541Srgrimes switch (pc->code) { 1931541Srgrimes default: 19455205Speter#ifdef _KERNEL 1951541Srgrimes return 0; 1961541Srgrimes#else 1971541Srgrimes abort(); 1988876Srgrimes#endif 199177003Srwatson 2001541Srgrimes case BPF_RET|BPF_K: 201177003Srwatson return ((u_int)pc->k); 2021541Srgrimes 2031541Srgrimes case BPF_RET|BPF_A: 204177003Srwatson return ((u_int)A); 2051541Srgrimes 2061541Srgrimes case BPF_LD|BPF_W|BPF_ABS: 2071541Srgrimes k = pc->k; 20841588Seivind if (k > buflen || sizeof(int32_t) > buflen - k) { 20955205Speter#ifdef _KERNEL 2101541Srgrimes int merr; 2111541Srgrimes 2121541Srgrimes if (buflen != 0) 2131541Srgrimes return 0; 2141541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2151541Srgrimes if (merr != 0) 2161541Srgrimes return 0; 2171541Srgrimes continue; 2181541Srgrimes#else 219177003Srwatson return (0); 2201541Srgrimes#endif 2211541Srgrimes } 2221541Srgrimes#ifdef BPF_ALIGN 22340779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2241541Srgrimes A = EXTRACT_LONG(&p[k]); 2251541Srgrimes else 2261541Srgrimes#endif 22740779Sdfr A = ntohl(*(int32_t *)(p + k)); 2281541Srgrimes continue; 2291541Srgrimes 2301541Srgrimes case BPF_LD|BPF_H|BPF_ABS: 2311541Srgrimes k = pc->k; 23241588Seivind if (k > buflen || sizeof(int16_t) > buflen - k) { 23355205Speter#ifdef _KERNEL 2341541Srgrimes int merr; 2351541Srgrimes 2361541Srgrimes if (buflen != 0) 2371541Srgrimes return 0; 2381541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 2391541Srgrimes continue; 2401541Srgrimes#else 2411541Srgrimes return 0; 2421541Srgrimes#endif 2431541Srgrimes } 2441541Srgrimes A = EXTRACT_SHORT(&p[k]); 2451541Srgrimes continue; 2461541Srgrimes 2471541Srgrimes case BPF_LD|BPF_B|BPF_ABS: 2481541Srgrimes k = pc->k; 2491541Srgrimes if (k >= buflen) { 25055205Speter#ifdef _KERNEL 251177003Srwatson struct mbuf *m; 2521541Srgrimes 2531541Srgrimes if (buflen != 0) 2541541Srgrimes return 0; 2551541Srgrimes m = (struct mbuf *)p; 2561541Srgrimes MINDEX(m, k); 2571541Srgrimes A = mtod(m, u_char *)[k]; 2581541Srgrimes continue; 2591541Srgrimes#else 2601541Srgrimes return 0; 2611541Srgrimes#endif 2621541Srgrimes } 2631541Srgrimes A = p[k]; 2641541Srgrimes continue; 2651541Srgrimes 2661541Srgrimes case BPF_LD|BPF_W|BPF_LEN: 2671541Srgrimes A = wirelen; 2681541Srgrimes continue; 2691541Srgrimes 2701541Srgrimes case BPF_LDX|BPF_W|BPF_LEN: 2711541Srgrimes X = wirelen; 2721541Srgrimes continue; 2731541Srgrimes 2741541Srgrimes case BPF_LD|BPF_W|BPF_IND: 2751541Srgrimes k = X + pc->k; 27645574Seivind if (pc->k > buflen || X > buflen - pc->k || 27745574Seivind sizeof(int32_t) > buflen - k) { 27855205Speter#ifdef _KERNEL 2791541Srgrimes int merr; 2801541Srgrimes 2811541Srgrimes if (buflen != 0) 282177003Srwatson return (0); 2831541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2841541Srgrimes if (merr != 0) 285177003Srwatson return (0); 2861541Srgrimes continue; 2871541Srgrimes#else 288177003Srwatson return (0); 2891541Srgrimes#endif 2901541Srgrimes } 2911541Srgrimes#ifdef BPF_ALIGN 29240779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2931541Srgrimes A = EXTRACT_LONG(&p[k]); 2941541Srgrimes else 2951541Srgrimes#endif 29640779Sdfr A = ntohl(*(int32_t *)(p + k)); 2971541Srgrimes continue; 2981541Srgrimes 2991541Srgrimes case BPF_LD|BPF_H|BPF_IND: 3001541Srgrimes k = X + pc->k; 30145574Seivind if (X > buflen || pc->k > buflen - X || 30245574Seivind sizeof(int16_t) > buflen - k) { 30355205Speter#ifdef _KERNEL 3041541Srgrimes int merr; 3051541Srgrimes 3061541Srgrimes if (buflen != 0) 3071541Srgrimes return 0; 3081541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 3091541Srgrimes if (merr != 0) 310177003Srwatson return (0); 3111541Srgrimes continue; 3121541Srgrimes#else 313177003Srwatson return (0); 3141541Srgrimes#endif 3151541Srgrimes } 3161541Srgrimes A = EXTRACT_SHORT(&p[k]); 3171541Srgrimes continue; 3181541Srgrimes 3191541Srgrimes case BPF_LD|BPF_B|BPF_IND: 3201541Srgrimes k = X + pc->k; 32148548Sbde if (pc->k >= buflen || X >= buflen - pc->k) { 32255205Speter#ifdef _KERNEL 323177003Srwatson struct mbuf *m; 3241541Srgrimes 3251541Srgrimes if (buflen != 0) 3261541Srgrimes return 0; 3271541Srgrimes m = (struct mbuf *)p; 3281541Srgrimes MINDEX(m, k); 329159018Sdwmalone A = mtod(m, u_char *)[k]; 3301541Srgrimes continue; 3311541Srgrimes#else 332177003Srwatson return (0); 3331541Srgrimes#endif 3341541Srgrimes } 3351541Srgrimes A = p[k]; 3361541Srgrimes continue; 3371541Srgrimes 3381541Srgrimes case BPF_LDX|BPF_MSH|BPF_B: 3391541Srgrimes k = pc->k; 3401541Srgrimes if (k >= buflen) { 34155205Speter#ifdef _KERNEL 3421541Srgrimes register struct mbuf *m; 3431541Srgrimes 3441541Srgrimes if (buflen != 0) 3451541Srgrimes return 0; 3461541Srgrimes m = (struct mbuf *)p; 3471541Srgrimes MINDEX(m, k); 348159018Sdwmalone X = (mtod(m, u_char *)[k] & 0xf) << 2; 3491541Srgrimes continue; 3501541Srgrimes#else 3511541Srgrimes return 0; 3521541Srgrimes#endif 3531541Srgrimes } 3541541Srgrimes X = (p[pc->k] & 0xf) << 2; 3551541Srgrimes continue; 3561541Srgrimes 3571541Srgrimes case BPF_LD|BPF_IMM: 3581541Srgrimes A = pc->k; 3591541Srgrimes continue; 3601541Srgrimes 3611541Srgrimes case BPF_LDX|BPF_IMM: 3621541Srgrimes X = pc->k; 3631541Srgrimes continue; 3641541Srgrimes 3651541Srgrimes case BPF_LD|BPF_MEM: 3661541Srgrimes A = mem[pc->k]; 3671541Srgrimes continue; 3688876Srgrimes 3691541Srgrimes case BPF_LDX|BPF_MEM: 3701541Srgrimes X = mem[pc->k]; 3711541Srgrimes continue; 3721541Srgrimes 3731541Srgrimes case BPF_ST: 3741541Srgrimes mem[pc->k] = A; 3751541Srgrimes continue; 3761541Srgrimes 3771541Srgrimes case BPF_STX: 3781541Srgrimes mem[pc->k] = X; 3791541Srgrimes continue; 3801541Srgrimes 3811541Srgrimes case BPF_JMP|BPF_JA: 3821541Srgrimes pc += pc->k; 3831541Srgrimes continue; 3841541Srgrimes 3851541Srgrimes case BPF_JMP|BPF_JGT|BPF_K: 3861541Srgrimes pc += (A > pc->k) ? pc->jt : pc->jf; 3871541Srgrimes continue; 3881541Srgrimes 3891541Srgrimes case BPF_JMP|BPF_JGE|BPF_K: 3901541Srgrimes pc += (A >= pc->k) ? pc->jt : pc->jf; 3911541Srgrimes continue; 3921541Srgrimes 3931541Srgrimes case BPF_JMP|BPF_JEQ|BPF_K: 3941541Srgrimes pc += (A == pc->k) ? pc->jt : pc->jf; 3951541Srgrimes continue; 3961541Srgrimes 3971541Srgrimes case BPF_JMP|BPF_JSET|BPF_K: 3981541Srgrimes pc += (A & pc->k) ? pc->jt : pc->jf; 3991541Srgrimes continue; 4001541Srgrimes 4011541Srgrimes case BPF_JMP|BPF_JGT|BPF_X: 4021541Srgrimes pc += (A > X) ? pc->jt : pc->jf; 4031541Srgrimes continue; 4041541Srgrimes 4051541Srgrimes case BPF_JMP|BPF_JGE|BPF_X: 4061541Srgrimes pc += (A >= X) ? pc->jt : pc->jf; 4071541Srgrimes continue; 4081541Srgrimes 4091541Srgrimes case BPF_JMP|BPF_JEQ|BPF_X: 4101541Srgrimes pc += (A == X) ? pc->jt : pc->jf; 4111541Srgrimes continue; 4121541Srgrimes 4131541Srgrimes case BPF_JMP|BPF_JSET|BPF_X: 4141541Srgrimes pc += (A & X) ? pc->jt : pc->jf; 4151541Srgrimes continue; 4161541Srgrimes 4171541Srgrimes case BPF_ALU|BPF_ADD|BPF_X: 4181541Srgrimes A += X; 4191541Srgrimes continue; 4208876Srgrimes 4211541Srgrimes case BPF_ALU|BPF_SUB|BPF_X: 4221541Srgrimes A -= X; 4231541Srgrimes continue; 4248876Srgrimes 4251541Srgrimes case BPF_ALU|BPF_MUL|BPF_X: 4261541Srgrimes A *= X; 4271541Srgrimes continue; 4288876Srgrimes 4291541Srgrimes case BPF_ALU|BPF_DIV|BPF_X: 4301541Srgrimes if (X == 0) 4311541Srgrimes return 0; 4321541Srgrimes A /= X; 4331541Srgrimes continue; 4348876Srgrimes 4351541Srgrimes case BPF_ALU|BPF_AND|BPF_X: 4361541Srgrimes A &= X; 4371541Srgrimes continue; 4388876Srgrimes 4391541Srgrimes case BPF_ALU|BPF_OR|BPF_X: 4401541Srgrimes A |= X; 4411541Srgrimes continue; 4421541Srgrimes 4431541Srgrimes case BPF_ALU|BPF_LSH|BPF_X: 4441541Srgrimes A <<= X; 4451541Srgrimes continue; 4461541Srgrimes 4471541Srgrimes case BPF_ALU|BPF_RSH|BPF_X: 4481541Srgrimes A >>= X; 4491541Srgrimes continue; 4501541Srgrimes 4511541Srgrimes case BPF_ALU|BPF_ADD|BPF_K: 4521541Srgrimes A += pc->k; 4531541Srgrimes continue; 4548876Srgrimes 4551541Srgrimes case BPF_ALU|BPF_SUB|BPF_K: 4561541Srgrimes A -= pc->k; 4571541Srgrimes continue; 4588876Srgrimes 4591541Srgrimes case BPF_ALU|BPF_MUL|BPF_K: 4601541Srgrimes A *= pc->k; 4611541Srgrimes continue; 4628876Srgrimes 4631541Srgrimes case BPF_ALU|BPF_DIV|BPF_K: 4641541Srgrimes A /= pc->k; 4651541Srgrimes continue; 4668876Srgrimes 4671541Srgrimes case BPF_ALU|BPF_AND|BPF_K: 4681541Srgrimes A &= pc->k; 4691541Srgrimes continue; 4708876Srgrimes 4711541Srgrimes case BPF_ALU|BPF_OR|BPF_K: 4721541Srgrimes A |= pc->k; 4731541Srgrimes continue; 4741541Srgrimes 4751541Srgrimes case BPF_ALU|BPF_LSH|BPF_K: 4761541Srgrimes A <<= pc->k; 4771541Srgrimes continue; 4781541Srgrimes 4791541Srgrimes case BPF_ALU|BPF_RSH|BPF_K: 4801541Srgrimes A >>= pc->k; 4811541Srgrimes continue; 4821541Srgrimes 4831541Srgrimes case BPF_ALU|BPF_NEG: 4841541Srgrimes A = -A; 4851541Srgrimes continue; 4861541Srgrimes 4871541Srgrimes case BPF_MISC|BPF_TAX: 4881541Srgrimes X = A; 4891541Srgrimes continue; 4901541Srgrimes 4911541Srgrimes case BPF_MISC|BPF_TXA: 4921541Srgrimes A = X; 4931541Srgrimes continue; 4941541Srgrimes } 4951541Srgrimes } 4961541Srgrimes} 4971541Srgrimes 49855205Speter#ifdef _KERNEL 499182454Sjkimstatic const u_short bpf_code_map[] = { 500182412Sjkim 0x10ff, /* 0x00-0x0f: 1111111100001000 */ 501182412Sjkim 0x3070, /* 0x10-0x1f: 0000111000001100 */ 502182412Sjkim 0x3131, /* 0x20-0x2f: 1000110010001100 */ 503182412Sjkim 0x3031, /* 0x30-0x3f: 1000110000001100 */ 504182412Sjkim 0x3131, /* 0x40-0x4f: 1000110010001100 */ 505182412Sjkim 0x1011, /* 0x50-0x5f: 1000100000001000 */ 506182412Sjkim 0x1013, /* 0x60-0x6f: 1100100000001000 */ 507182412Sjkim 0x1010, /* 0x70-0x7f: 0000100000001000 */ 508182412Sjkim 0x0093, /* 0x80-0x8f: 1100100100000000 */ 509182412Sjkim 0x0000, /* 0x90-0x9f: 0000000000000000 */ 510182412Sjkim 0x0000, /* 0xa0-0xaf: 0000000000000000 */ 511182412Sjkim 0x0002, /* 0xb0-0xbf: 0100000000000000 */ 512182412Sjkim 0x0000, /* 0xc0-0xcf: 0000000000000000 */ 513182412Sjkim 0x0000, /* 0xd0-0xdf: 0000000000000000 */ 514182412Sjkim 0x0000, /* 0xe0-0xef: 0000000000000000 */ 515182412Sjkim 0x0000 /* 0xf0-0xff: 0000000000000000 */ 516182412Sjkim}; 517182412Sjkim 518182454Sjkim#define BPF_VALIDATE_CODE(c) \ 519182454Sjkim ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0) 520182454Sjkim 5211541Srgrimes/* 5221541Srgrimes * Return true if the 'fcode' is a valid filter program. 5231541Srgrimes * The constraints are that each jump be forward and to a valid 5248876Srgrimes * code. The code must terminate with either an accept or reject. 5251541Srgrimes * 5261541Srgrimes * The kernel needs to be able to verify an application's filter code. 5271541Srgrimes * Otherwise, a bogus program could easily crash the system. 5281541Srgrimes */ 5291541Srgrimesint 5301541Srgrimesbpf_validate(f, len) 53154038Sarchie const struct bpf_insn *f; 5321541Srgrimes int len; 5331541Srgrimes{ 5341541Srgrimes register int i; 53554038Sarchie register const struct bpf_insn *p; 5361541Srgrimes 537153996Sjkim /* Do not accept negative length filter. */ 538153996Sjkim if (len < 0) 539153996Sjkim return 0; 540153996Sjkim 541153996Sjkim /* An empty filter means accept all. */ 542153996Sjkim if (len == 0) 543153995Sjkim return 1; 544153221Sjkim 5451541Srgrimes for (i = 0; i < len; ++i) { 546182412Sjkim p = &f[i]; 5471541Srgrimes /* 548182412Sjkim * Check that the code is valid. 549182412Sjkim */ 550182454Sjkim if (!BPF_VALIDATE_CODE(p->code)) 551182412Sjkim return 0; 552182412Sjkim /* 5538876Srgrimes * Check that that jumps are forward, and within 5541541Srgrimes * the code block. 5551541Srgrimes */ 5561541Srgrimes if (BPF_CLASS(p->code) == BPF_JMP) { 557182425Sjkim register u_int offset; 5581541Srgrimes 559182454Sjkim if (p->code == (BPF_JMP|BPF_JA)) 560182425Sjkim offset = p->k; 561182425Sjkim else 562182425Sjkim offset = p->jt > p->jf ? p->jt : p->jf; 563182425Sjkim if (offset >= (u_int)(len - i) - 1) 5641541Srgrimes return 0; 565182454Sjkim continue; 5661541Srgrimes } 5671541Srgrimes /* 5681541Srgrimes * Check that memory operations use valid addresses. 5691541Srgrimes */ 570182454Sjkim if (p->code == BPF_ST || p->code == BPF_STX || 571182454Sjkim p->code == (BPF_LD|BPF_MEM) || 572182454Sjkim p->code == (BPF_LDX|BPF_MEM)) { 573182454Sjkim if (p->k >= BPF_MEMWORDS) 574182454Sjkim return 0; 575182454Sjkim continue; 576182454Sjkim } 5771541Srgrimes /* 5781541Srgrimes * Check for constant division by 0. 5791541Srgrimes */ 5801541Srgrimes if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) 5811541Srgrimes return 0; 5821541Srgrimes } 5831541Srgrimes return BPF_CLASS(f[len - 1].code) == BPF_RET; 5841541Srgrimes} 5851541Srgrimes#endif 586