bpf_filter.c revision 182455
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 182455 2008-08-29 19:32:04Z 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) \ 80182455Sjkim 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: 115182455Sjkim return (((u_int32_t)cp[0] << 24) | 11641588Seivind ((u_int32_t)np[0] << 16) | 11741588Seivind ((u_int32_t)np[1] << 8) | 118182455Sjkim (u_int32_t)np[2]); 1191541Srgrimes 1201541Srgrimes case 2: 121182455Sjkim return (((u_int32_t)cp[0] << 24) | 12241588Seivind ((u_int32_t)cp[1] << 16) | 12341588Seivind ((u_int32_t)np[0] << 8) | 124182455Sjkim (u_int32_t)np[1]); 1251541Srgrimes 1261541Srgrimes default: 127182455Sjkim return (((u_int32_t)cp[0] << 24) | 12841588Seivind ((u_int32_t)cp[1] << 16) | 12941588Seivind ((u_int32_t)cp[2] << 8) | 130182455Sjkim (u_int32_t)np[0]); 1311541Srgrimes } 1321541Srgrimes bad: 1331541Srgrimes *err = 1; 134177003Srwatson return (0); 1351541Srgrimes} 1361541Srgrimes 13741588Seivindstatic u_int16_t 138177003Srwatsonm_xhalf(struct mbuf *m, bpf_u_int32 k, int *err) 1391541Srgrimes{ 140177003Srwatson size_t len; 141177003Srwatson u_char *cp; 142177003Srwatson struct mbuf *m0; 1431541Srgrimes 1441541Srgrimes len = m->m_len; 1451541Srgrimes while (k >= len) { 1461541Srgrimes k -= len; 1471541Srgrimes m = m->m_next; 1481541Srgrimes if (m == 0) 1491541Srgrimes goto bad; 1501541Srgrimes len = m->m_len; 1511541Srgrimes } 1521541Srgrimes cp = mtod(m, u_char *) + k; 1531541Srgrimes if (len - k >= 2) { 1541541Srgrimes *err = 0; 155177003Srwatson return (EXTRACT_SHORT(cp)); 1561541Srgrimes } 1571541Srgrimes m0 = m->m_next; 1581541Srgrimes if (m0 == 0) 1591541Srgrimes goto bad; 1601541Srgrimes *err = 0; 161177003Srwatson return ((cp[0] << 8) | mtod(m0, u_char *)[0]); 1621541Srgrimes bad: 1631541Srgrimes *err = 1; 164177003Srwatson return (0); 1651541Srgrimes} 1661541Srgrimes#endif 1671541Srgrimes 1681541Srgrimes/* 1691541Srgrimes * Execute the filter program starting at pc on the packet p 1701541Srgrimes * wirelen is the length of the original packet 1711541Srgrimes * buflen is the amount of data present 1721541Srgrimes */ 1731541Srgrimesu_int 174177003Srwatsonbpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) 1751541Srgrimes{ 176177003Srwatson u_int32_t A = 0, X = 0; 177177003Srwatson bpf_u_int32 k; 178172154Sdwmalone u_int32_t mem[BPF_MEMWORDS]; 1791541Srgrimes 180177003Srwatson if (pc == NULL) 1811541Srgrimes /* 1821541Srgrimes * No filter means accept all. 1831541Srgrimes */ 184177003Srwatson return ((u_int)-1); 1851549Srgrimes 1861541Srgrimes --pc; 1871541Srgrimes while (1) { 1881541Srgrimes ++pc; 1891541Srgrimes switch (pc->code) { 1901541Srgrimes default: 19155205Speter#ifdef _KERNEL 192182455Sjkim return (0); 1931541Srgrimes#else 1941541Srgrimes abort(); 1958876Srgrimes#endif 196177003Srwatson 1971541Srgrimes case BPF_RET|BPF_K: 198177003Srwatson return ((u_int)pc->k); 1991541Srgrimes 2001541Srgrimes case BPF_RET|BPF_A: 201177003Srwatson return ((u_int)A); 2021541Srgrimes 2031541Srgrimes case BPF_LD|BPF_W|BPF_ABS: 2041541Srgrimes k = pc->k; 20541588Seivind if (k > buflen || sizeof(int32_t) > buflen - k) { 20655205Speter#ifdef _KERNEL 2071541Srgrimes int merr; 2081541Srgrimes 2091541Srgrimes if (buflen != 0) 210182455Sjkim return (0); 2111541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2121541Srgrimes if (merr != 0) 213182455Sjkim return (0); 2141541Srgrimes continue; 2151541Srgrimes#else 216177003Srwatson return (0); 2171541Srgrimes#endif 2181541Srgrimes } 2191541Srgrimes#ifdef BPF_ALIGN 22040779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2211541Srgrimes A = EXTRACT_LONG(&p[k]); 2221541Srgrimes else 2231541Srgrimes#endif 22440779Sdfr A = ntohl(*(int32_t *)(p + k)); 2251541Srgrimes continue; 2261541Srgrimes 2271541Srgrimes case BPF_LD|BPF_H|BPF_ABS: 2281541Srgrimes k = pc->k; 22941588Seivind if (k > buflen || sizeof(int16_t) > buflen - k) { 23055205Speter#ifdef _KERNEL 2311541Srgrimes int merr; 2321541Srgrimes 2331541Srgrimes if (buflen != 0) 234182455Sjkim return (0); 2351541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 2361541Srgrimes continue; 2371541Srgrimes#else 238182455Sjkim return (0); 2391541Srgrimes#endif 2401541Srgrimes } 2411541Srgrimes A = EXTRACT_SHORT(&p[k]); 2421541Srgrimes continue; 2431541Srgrimes 2441541Srgrimes case BPF_LD|BPF_B|BPF_ABS: 2451541Srgrimes k = pc->k; 2461541Srgrimes if (k >= buflen) { 24755205Speter#ifdef _KERNEL 248177003Srwatson struct mbuf *m; 2491541Srgrimes 2501541Srgrimes if (buflen != 0) 251182455Sjkim return (0); 2521541Srgrimes m = (struct mbuf *)p; 2531541Srgrimes MINDEX(m, k); 2541541Srgrimes A = mtod(m, u_char *)[k]; 2551541Srgrimes continue; 2561541Srgrimes#else 257182455Sjkim return (0); 2581541Srgrimes#endif 2591541Srgrimes } 2601541Srgrimes A = p[k]; 2611541Srgrimes continue; 2621541Srgrimes 2631541Srgrimes case BPF_LD|BPF_W|BPF_LEN: 2641541Srgrimes A = wirelen; 2651541Srgrimes continue; 2661541Srgrimes 2671541Srgrimes case BPF_LDX|BPF_W|BPF_LEN: 2681541Srgrimes X = wirelen; 2691541Srgrimes continue; 2701541Srgrimes 2711541Srgrimes case BPF_LD|BPF_W|BPF_IND: 2721541Srgrimes k = X + pc->k; 27345574Seivind if (pc->k > buflen || X > buflen - pc->k || 27445574Seivind sizeof(int32_t) > buflen - k) { 27555205Speter#ifdef _KERNEL 2761541Srgrimes int merr; 2771541Srgrimes 2781541Srgrimes if (buflen != 0) 279177003Srwatson return (0); 2801541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2811541Srgrimes if (merr != 0) 282177003Srwatson return (0); 2831541Srgrimes continue; 2841541Srgrimes#else 285177003Srwatson return (0); 2861541Srgrimes#endif 2871541Srgrimes } 2881541Srgrimes#ifdef BPF_ALIGN 28940779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2901541Srgrimes A = EXTRACT_LONG(&p[k]); 2911541Srgrimes else 2921541Srgrimes#endif 29340779Sdfr A = ntohl(*(int32_t *)(p + k)); 2941541Srgrimes continue; 2951541Srgrimes 2961541Srgrimes case BPF_LD|BPF_H|BPF_IND: 2971541Srgrimes k = X + pc->k; 29845574Seivind if (X > buflen || pc->k > buflen - X || 29945574Seivind sizeof(int16_t) > buflen - k) { 30055205Speter#ifdef _KERNEL 3011541Srgrimes int merr; 3021541Srgrimes 3031541Srgrimes if (buflen != 0) 304182455Sjkim return (0); 3051541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 3061541Srgrimes if (merr != 0) 307177003Srwatson return (0); 3081541Srgrimes continue; 3091541Srgrimes#else 310177003Srwatson return (0); 3111541Srgrimes#endif 3121541Srgrimes } 3131541Srgrimes A = EXTRACT_SHORT(&p[k]); 3141541Srgrimes continue; 3151541Srgrimes 3161541Srgrimes case BPF_LD|BPF_B|BPF_IND: 3171541Srgrimes k = X + pc->k; 31848548Sbde if (pc->k >= buflen || X >= buflen - pc->k) { 31955205Speter#ifdef _KERNEL 320177003Srwatson struct mbuf *m; 3211541Srgrimes 3221541Srgrimes if (buflen != 0) 323182455Sjkim return (0); 3241541Srgrimes m = (struct mbuf *)p; 3251541Srgrimes MINDEX(m, k); 326159018Sdwmalone A = mtod(m, u_char *)[k]; 3271541Srgrimes continue; 3281541Srgrimes#else 329177003Srwatson return (0); 3301541Srgrimes#endif 3311541Srgrimes } 3321541Srgrimes A = p[k]; 3331541Srgrimes continue; 3341541Srgrimes 3351541Srgrimes case BPF_LDX|BPF_MSH|BPF_B: 3361541Srgrimes k = pc->k; 3371541Srgrimes if (k >= buflen) { 33855205Speter#ifdef _KERNEL 3391541Srgrimes register struct mbuf *m; 3401541Srgrimes 3411541Srgrimes if (buflen != 0) 342182455Sjkim return (0); 3431541Srgrimes m = (struct mbuf *)p; 3441541Srgrimes MINDEX(m, k); 345159018Sdwmalone X = (mtod(m, u_char *)[k] & 0xf) << 2; 3461541Srgrimes continue; 3471541Srgrimes#else 348182455Sjkim return (0); 3491541Srgrimes#endif 3501541Srgrimes } 3511541Srgrimes X = (p[pc->k] & 0xf) << 2; 3521541Srgrimes continue; 3531541Srgrimes 3541541Srgrimes case BPF_LD|BPF_IMM: 3551541Srgrimes A = pc->k; 3561541Srgrimes continue; 3571541Srgrimes 3581541Srgrimes case BPF_LDX|BPF_IMM: 3591541Srgrimes X = pc->k; 3601541Srgrimes continue; 3611541Srgrimes 3621541Srgrimes case BPF_LD|BPF_MEM: 3631541Srgrimes A = mem[pc->k]; 3641541Srgrimes continue; 3658876Srgrimes 3661541Srgrimes case BPF_LDX|BPF_MEM: 3671541Srgrimes X = mem[pc->k]; 3681541Srgrimes continue; 3691541Srgrimes 3701541Srgrimes case BPF_ST: 3711541Srgrimes mem[pc->k] = A; 3721541Srgrimes continue; 3731541Srgrimes 3741541Srgrimes case BPF_STX: 3751541Srgrimes mem[pc->k] = X; 3761541Srgrimes continue; 3771541Srgrimes 3781541Srgrimes case BPF_JMP|BPF_JA: 3791541Srgrimes pc += pc->k; 3801541Srgrimes continue; 3811541Srgrimes 3821541Srgrimes case BPF_JMP|BPF_JGT|BPF_K: 3831541Srgrimes pc += (A > pc->k) ? pc->jt : pc->jf; 3841541Srgrimes continue; 3851541Srgrimes 3861541Srgrimes case BPF_JMP|BPF_JGE|BPF_K: 3871541Srgrimes pc += (A >= pc->k) ? pc->jt : pc->jf; 3881541Srgrimes continue; 3891541Srgrimes 3901541Srgrimes case BPF_JMP|BPF_JEQ|BPF_K: 3911541Srgrimes pc += (A == pc->k) ? pc->jt : pc->jf; 3921541Srgrimes continue; 3931541Srgrimes 3941541Srgrimes case BPF_JMP|BPF_JSET|BPF_K: 3951541Srgrimes pc += (A & pc->k) ? pc->jt : pc->jf; 3961541Srgrimes continue; 3971541Srgrimes 3981541Srgrimes case BPF_JMP|BPF_JGT|BPF_X: 3991541Srgrimes pc += (A > X) ? pc->jt : pc->jf; 4001541Srgrimes continue; 4011541Srgrimes 4021541Srgrimes case BPF_JMP|BPF_JGE|BPF_X: 4031541Srgrimes pc += (A >= X) ? pc->jt : pc->jf; 4041541Srgrimes continue; 4051541Srgrimes 4061541Srgrimes case BPF_JMP|BPF_JEQ|BPF_X: 4071541Srgrimes pc += (A == X) ? pc->jt : pc->jf; 4081541Srgrimes continue; 4091541Srgrimes 4101541Srgrimes case BPF_JMP|BPF_JSET|BPF_X: 4111541Srgrimes pc += (A & X) ? pc->jt : pc->jf; 4121541Srgrimes continue; 4131541Srgrimes 4141541Srgrimes case BPF_ALU|BPF_ADD|BPF_X: 4151541Srgrimes A += X; 4161541Srgrimes continue; 4178876Srgrimes 4181541Srgrimes case BPF_ALU|BPF_SUB|BPF_X: 4191541Srgrimes A -= X; 4201541Srgrimes continue; 4218876Srgrimes 4221541Srgrimes case BPF_ALU|BPF_MUL|BPF_X: 4231541Srgrimes A *= X; 4241541Srgrimes continue; 4258876Srgrimes 4261541Srgrimes case BPF_ALU|BPF_DIV|BPF_X: 4271541Srgrimes if (X == 0) 428182455Sjkim return (0); 4291541Srgrimes A /= X; 4301541Srgrimes continue; 4318876Srgrimes 4321541Srgrimes case BPF_ALU|BPF_AND|BPF_X: 4331541Srgrimes A &= X; 4341541Srgrimes continue; 4358876Srgrimes 4361541Srgrimes case BPF_ALU|BPF_OR|BPF_X: 4371541Srgrimes A |= X; 4381541Srgrimes continue; 4391541Srgrimes 4401541Srgrimes case BPF_ALU|BPF_LSH|BPF_X: 4411541Srgrimes A <<= X; 4421541Srgrimes continue; 4431541Srgrimes 4441541Srgrimes case BPF_ALU|BPF_RSH|BPF_X: 4451541Srgrimes A >>= X; 4461541Srgrimes continue; 4471541Srgrimes 4481541Srgrimes case BPF_ALU|BPF_ADD|BPF_K: 4491541Srgrimes A += pc->k; 4501541Srgrimes continue; 4518876Srgrimes 4521541Srgrimes case BPF_ALU|BPF_SUB|BPF_K: 4531541Srgrimes A -= pc->k; 4541541Srgrimes continue; 4558876Srgrimes 4561541Srgrimes case BPF_ALU|BPF_MUL|BPF_K: 4571541Srgrimes A *= pc->k; 4581541Srgrimes continue; 4598876Srgrimes 4601541Srgrimes case BPF_ALU|BPF_DIV|BPF_K: 4611541Srgrimes A /= pc->k; 4621541Srgrimes continue; 4638876Srgrimes 4641541Srgrimes case BPF_ALU|BPF_AND|BPF_K: 4651541Srgrimes A &= pc->k; 4661541Srgrimes continue; 4678876Srgrimes 4681541Srgrimes case BPF_ALU|BPF_OR|BPF_K: 4691541Srgrimes A |= pc->k; 4701541Srgrimes continue; 4711541Srgrimes 4721541Srgrimes case BPF_ALU|BPF_LSH|BPF_K: 4731541Srgrimes A <<= pc->k; 4741541Srgrimes continue; 4751541Srgrimes 4761541Srgrimes case BPF_ALU|BPF_RSH|BPF_K: 4771541Srgrimes A >>= pc->k; 4781541Srgrimes continue; 4791541Srgrimes 4801541Srgrimes case BPF_ALU|BPF_NEG: 4811541Srgrimes A = -A; 4821541Srgrimes continue; 4831541Srgrimes 4841541Srgrimes case BPF_MISC|BPF_TAX: 4851541Srgrimes X = A; 4861541Srgrimes continue; 4871541Srgrimes 4881541Srgrimes case BPF_MISC|BPF_TXA: 4891541Srgrimes A = X; 4901541Srgrimes continue; 4911541Srgrimes } 4921541Srgrimes } 4931541Srgrimes} 4941541Srgrimes 49555205Speter#ifdef _KERNEL 496182454Sjkimstatic const u_short bpf_code_map[] = { 497182412Sjkim 0x10ff, /* 0x00-0x0f: 1111111100001000 */ 498182412Sjkim 0x3070, /* 0x10-0x1f: 0000111000001100 */ 499182412Sjkim 0x3131, /* 0x20-0x2f: 1000110010001100 */ 500182412Sjkim 0x3031, /* 0x30-0x3f: 1000110000001100 */ 501182412Sjkim 0x3131, /* 0x40-0x4f: 1000110010001100 */ 502182412Sjkim 0x1011, /* 0x50-0x5f: 1000100000001000 */ 503182412Sjkim 0x1013, /* 0x60-0x6f: 1100100000001000 */ 504182412Sjkim 0x1010, /* 0x70-0x7f: 0000100000001000 */ 505182412Sjkim 0x0093, /* 0x80-0x8f: 1100100100000000 */ 506182412Sjkim 0x0000, /* 0x90-0x9f: 0000000000000000 */ 507182412Sjkim 0x0000, /* 0xa0-0xaf: 0000000000000000 */ 508182412Sjkim 0x0002, /* 0xb0-0xbf: 0100000000000000 */ 509182412Sjkim 0x0000, /* 0xc0-0xcf: 0000000000000000 */ 510182412Sjkim 0x0000, /* 0xd0-0xdf: 0000000000000000 */ 511182412Sjkim 0x0000, /* 0xe0-0xef: 0000000000000000 */ 512182412Sjkim 0x0000 /* 0xf0-0xff: 0000000000000000 */ 513182412Sjkim}; 514182412Sjkim 515182454Sjkim#define BPF_VALIDATE_CODE(c) \ 516182454Sjkim ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0) 517182454Sjkim 5181541Srgrimes/* 5191541Srgrimes * Return true if the 'fcode' is a valid filter program. 5201541Srgrimes * The constraints are that each jump be forward and to a valid 5218876Srgrimes * code. The code must terminate with either an accept or reject. 5221541Srgrimes * 5231541Srgrimes * The kernel needs to be able to verify an application's filter code. 5241541Srgrimes * Otherwise, a bogus program could easily crash the system. 5251541Srgrimes */ 5261541Srgrimesint 527182455Sjkimbpf_validate(const struct bpf_insn *f, int len) 5281541Srgrimes{ 5291541Srgrimes register int i; 53054038Sarchie register const struct bpf_insn *p; 5311541Srgrimes 532153996Sjkim /* Do not accept negative length filter. */ 533153996Sjkim if (len < 0) 534182455Sjkim return (0); 535153996Sjkim 536153996Sjkim /* An empty filter means accept all. */ 537153996Sjkim if (len == 0) 538182455Sjkim return (1); 539153221Sjkim 5401541Srgrimes for (i = 0; i < len; ++i) { 541182412Sjkim p = &f[i]; 5421541Srgrimes /* 543182412Sjkim * Check that the code is valid. 544182412Sjkim */ 545182454Sjkim if (!BPF_VALIDATE_CODE(p->code)) 546182455Sjkim return (0); 547182412Sjkim /* 5488876Srgrimes * Check that that jumps are forward, and within 5491541Srgrimes * the code block. 5501541Srgrimes */ 5511541Srgrimes if (BPF_CLASS(p->code) == BPF_JMP) { 552182425Sjkim register u_int offset; 5531541Srgrimes 554182454Sjkim if (p->code == (BPF_JMP|BPF_JA)) 555182425Sjkim offset = p->k; 556182425Sjkim else 557182425Sjkim offset = p->jt > p->jf ? p->jt : p->jf; 558182425Sjkim if (offset >= (u_int)(len - i) - 1) 559182455Sjkim return (0); 560182454Sjkim continue; 5611541Srgrimes } 5621541Srgrimes /* 5631541Srgrimes * Check that memory operations use valid addresses. 5641541Srgrimes */ 565182454Sjkim if (p->code == BPF_ST || p->code == BPF_STX || 566182454Sjkim p->code == (BPF_LD|BPF_MEM) || 567182454Sjkim p->code == (BPF_LDX|BPF_MEM)) { 568182454Sjkim if (p->k >= BPF_MEMWORDS) 569182455Sjkim return (0); 570182454Sjkim continue; 571182454Sjkim } 5721541Srgrimes /* 5731541Srgrimes * Check for constant division by 0. 5741541Srgrimes */ 5751541Srgrimes if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) 576182455Sjkim return (0); 5771541Srgrimes } 578182455Sjkim return (BPF_CLASS(f[len - 1].code) == BPF_RET); 5791541Srgrimes} 5801541Srgrimes#endif 581