1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/*- 4145510Sdarrenr * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 5145510Sdarrenr * The Regents of the University of California. All rights reserved. 6145510Sdarrenr * 7145510Sdarrenr * This code is derived from the Stanford/CMU enet packet filter, 8145510Sdarrenr * (net/enet.c) distributed as part of 4.3BSD, and code contributed 9145510Sdarrenr * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 10145510Sdarrenr * Berkeley Laboratory. 11145510Sdarrenr * 12145510Sdarrenr * Redistribution and use in source and binary forms, with or without 13145510Sdarrenr * modification, are permitted provided that the following conditions 14145510Sdarrenr * are met: 15145510Sdarrenr * 1. Redistributions of source code must retain the above copyright 16145510Sdarrenr * notice, this list of conditions and the following disclaimer. 17145510Sdarrenr * 2. Redistributions in binary form must reproduce the above copyright 18145510Sdarrenr * notice, this list of conditions and the following disclaimer in the 19145510Sdarrenr * documentation and/or other materials provided with the distribution. 20145510Sdarrenr * 3. All advertising materials mentioning features or use of this software 21145510Sdarrenr * must display the following acknowledgement: 22145510Sdarrenr * This product includes software developed by the University of 23145510Sdarrenr * California, Berkeley and its contributors. 24145510Sdarrenr * 4. Neither the name of the University nor the names of its contributors 25145510Sdarrenr * may be used to endorse or promote products derived from this software 26145510Sdarrenr * without specific prior written permission. 27145510Sdarrenr * 28145510Sdarrenr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29145510Sdarrenr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30145510Sdarrenr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31145510Sdarrenr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32145510Sdarrenr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33145510Sdarrenr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34145510Sdarrenr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35145510Sdarrenr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36145510Sdarrenr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37145510Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38145510Sdarrenr * SUCH DAMAGE. 39145510Sdarrenr * 40145510Sdarrenr * @(#)bpf.c 7.5 (Berkeley) 7/15/91 41145510Sdarrenr */ 42145510Sdarrenr 43145510Sdarrenr#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) 44145510Sdarrenrstatic const char rcsid[] = 45170268Sdarrenr "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2.2.3 2006/10/03 11:25:56 darrenr Exp $ (LBL)"; 46145510Sdarrenr#endif 47145510Sdarrenr 48145510Sdarrenr#include <sys/param.h> 49145510Sdarrenr#include <sys/types.h> 50145510Sdarrenr#include <sys/time.h> 51145510Sdarrenr#include <sys/socket.h> 52145510Sdarrenr 53145510Sdarrenr#include <netinet/in.h> 54145510Sdarrenr#include <net/if.h> 55145510Sdarrenr 56145554Sdarrenr#include "netinet/ip_compat.h" 57145510Sdarrenr#include "bpf-ipf.h" 58145510Sdarrenr 59145510Sdarrenr 60145510Sdarrenr#if (defined(__hpux) || SOLARIS) && (defined(_KERNEL) || defined(KERNEL)) 61145510Sdarrenr# include <sys/sysmacros.h> 62145510Sdarrenr# include <sys/stream.h> 63145510Sdarrenr#endif 64145510Sdarrenr 65145510Sdarrenr#include "pcap-ipf.h" 66145510Sdarrenr 67145510Sdarrenr#if !defined(KERNEL) && !defined(_KERNEL) 68145510Sdarrenr#include <stdlib.h> 69145510Sdarrenr#endif 70145510Sdarrenr 71145510Sdarrenr#define int32 bpf_int32 72145510Sdarrenr#define u_int32 bpf_u_int32 73145510Sdarrenr 74145510Sdarrenrstatic int m_xword __P((mb_t *, int, int *)); 75145510Sdarrenrstatic int m_xhalf __P((mb_t *, int, int *)); 76145510Sdarrenr 77145510Sdarrenr#ifndef LBL_ALIGN 78145510Sdarrenr/* 79145510Sdarrenr * XXX - IA-64? If not, this probably won't work on Win64 IA-64 80145510Sdarrenr * systems, unless LBL_ALIGN is defined elsewhere for them. 81145510Sdarrenr * XXX - SuperH? If not, this probably won't work on WinCE SuperH 82145510Sdarrenr * systems, unless LBL_ALIGN is defined elsewhere for them. 83145510Sdarrenr */ 84145510Sdarrenr#if defined(sparc) || defined(__sparc__) || defined(mips) || \ 85145510Sdarrenr defined(ibm032) || defined(__alpha) || defined(__hpux) || \ 86145510Sdarrenr defined(__arm__) 87145510Sdarrenr#define LBL_ALIGN 88145510Sdarrenr#endif 89145510Sdarrenr#endif 90145510Sdarrenr 91145510Sdarrenr#ifndef LBL_ALIGN 92145510Sdarrenr 93145510Sdarrenr#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) 94145510Sdarrenr#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p)) 95145510Sdarrenr#else 96145510Sdarrenr#define EXTRACT_SHORT(p)\ 97145510Sdarrenr ((u_short)\ 98145510Sdarrenr ((u_short)*((u_char *)p+0)<<8|\ 99145510Sdarrenr (u_short)*((u_char *)p+1)<<0)) 100145510Sdarrenr#define EXTRACT_LONG(p)\ 101145510Sdarrenr ((u_int32)*((u_char *)p+0)<<24|\ 102145510Sdarrenr (u_int32)*((u_char *)p+1)<<16|\ 103145510Sdarrenr (u_int32)*((u_char *)p+2)<<8|\ 104145510Sdarrenr (u_int32)*((u_char *)p+3)<<0) 105145510Sdarrenr#endif 106145510Sdarrenr 107145510Sdarrenr#define MINDEX(len, _m, _k) \ 108145510Sdarrenr{ \ 109145510Sdarrenr len = M_LEN(m); \ 110145510Sdarrenr while ((_k) >= len) { \ 111145510Sdarrenr (_k) -= len; \ 112145510Sdarrenr (_m) = (_m)->m_next; \ 113145510Sdarrenr if ((_m) == 0) \ 114145510Sdarrenr return 0; \ 115145510Sdarrenr len = M_LEN(m); \ 116145510Sdarrenr } \ 117145510Sdarrenr} 118145510Sdarrenr 119145510Sdarrenrstatic int 120145510Sdarrenrm_xword(m, k, err) 121145510Sdarrenr register mb_t *m; 122145510Sdarrenr register int k, *err; 123145510Sdarrenr{ 124145510Sdarrenr register int len; 125145510Sdarrenr register u_char *cp, *np; 126145510Sdarrenr register mb_t *m0; 127145510Sdarrenr 128145510Sdarrenr MINDEX(len, m, k); 129145510Sdarrenr cp = MTOD(m, u_char *) + k; 130145510Sdarrenr if (len - k >= 4) { 131145510Sdarrenr *err = 0; 132145510Sdarrenr return EXTRACT_LONG(cp); 133145510Sdarrenr } 134145510Sdarrenr m0 = m->m_next; 135145510Sdarrenr if (m0 == 0 || M_LEN(m0) + len - k < 4) 136145510Sdarrenr goto bad; 137145510Sdarrenr *err = 0; 138145510Sdarrenr np = MTOD(m0, u_char *); 139145510Sdarrenr switch (len - k) { 140145510Sdarrenr 141145510Sdarrenr case 1: 142145510Sdarrenr return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; 143145510Sdarrenr 144145510Sdarrenr case 2: 145145510Sdarrenr return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1]; 146145510Sdarrenr 147145510Sdarrenr default: 148145510Sdarrenr return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0]; 149145510Sdarrenr } 150145510Sdarrenr bad: 151145510Sdarrenr *err = 1; 152145510Sdarrenr return 0; 153145510Sdarrenr} 154145510Sdarrenr 155145510Sdarrenrstatic int 156145510Sdarrenrm_xhalf(m, k, err) 157145510Sdarrenr register mb_t *m; 158145510Sdarrenr register int k, *err; 159145510Sdarrenr{ 160145510Sdarrenr register int len; 161145510Sdarrenr register u_char *cp; 162145510Sdarrenr register mb_t *m0; 163145510Sdarrenr 164145510Sdarrenr MINDEX(len, m, k); 165145510Sdarrenr cp = MTOD(m, u_char *) + k; 166145510Sdarrenr if (len - k >= 2) { 167145510Sdarrenr *err = 0; 168145510Sdarrenr return EXTRACT_SHORT(cp); 169145510Sdarrenr } 170145510Sdarrenr m0 = m->m_next; 171145510Sdarrenr if (m0 == 0) 172145510Sdarrenr goto bad; 173145510Sdarrenr *err = 0; 174145510Sdarrenr return (cp[0] << 8) | MTOD(m0, u_char *)[0]; 175145510Sdarrenr bad: 176145510Sdarrenr *err = 1; 177145510Sdarrenr return 0; 178145510Sdarrenr} 179145510Sdarrenr 180145510Sdarrenr/* 181145510Sdarrenr * Execute the filter program starting at pc on the packet p 182145510Sdarrenr * wirelen is the length of the original packet 183145510Sdarrenr * buflen is the amount of data present 184145510Sdarrenr * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0, 185145510Sdarrenr * in all other cases, p is a pointer to a buffer and buflen is its size. 186145510Sdarrenr */ 187145510Sdarrenru_int 188145510Sdarrenrbpf_filter(pc, p, wirelen, buflen) 189145510Sdarrenr register struct bpf_insn *pc; 190145510Sdarrenr register u_char *p; 191145510Sdarrenr u_int wirelen; 192145510Sdarrenr register u_int buflen; 193145510Sdarrenr{ 194145510Sdarrenr register u_int32 A, X; 195145510Sdarrenr register int k; 196145510Sdarrenr int32 mem[BPF_MEMWORDS]; 197145510Sdarrenr mb_t *m, *n; 198170268Sdarrenr int merr = 0; /* XXX: GCC */ 199170268Sdarrenr int len; 200145510Sdarrenr 201145510Sdarrenr if (buflen == 0) { 202145510Sdarrenr m = (mb_t *)p; 203145510Sdarrenr p = MTOD(m, u_char *); 204145510Sdarrenr buflen = M_LEN(m); 205145510Sdarrenr } else 206145510Sdarrenr m = NULL; 207145510Sdarrenr 208145510Sdarrenr if (pc == 0) 209145510Sdarrenr /* 210145510Sdarrenr * No filter means accept all. 211145510Sdarrenr */ 212145510Sdarrenr return (u_int)-1; 213145510Sdarrenr A = 0; 214145510Sdarrenr X = 0; 215145510Sdarrenr --pc; 216145510Sdarrenr while (1) { 217145510Sdarrenr ++pc; 218145510Sdarrenr switch (pc->code) { 219145510Sdarrenr 220145510Sdarrenr default: 221145510Sdarrenr return 0; 222145510Sdarrenr case BPF_RET|BPF_K: 223145510Sdarrenr return (u_int)pc->k; 224145510Sdarrenr 225145510Sdarrenr case BPF_RET|BPF_A: 226145510Sdarrenr return (u_int)A; 227145510Sdarrenr 228145510Sdarrenr case BPF_LD|BPF_W|BPF_ABS: 229145510Sdarrenr k = pc->k; 230145510Sdarrenr if (k + sizeof(int32) > buflen) { 231145510Sdarrenr if (m == NULL) 232145510Sdarrenr return 0; 233145510Sdarrenr A = m_xword(m, k, &merr); 234145510Sdarrenr if (merr != 0) 235145510Sdarrenr return 0; 236145510Sdarrenr continue; 237145510Sdarrenr } 238145510Sdarrenr A = EXTRACT_LONG(&p[k]); 239145510Sdarrenr continue; 240145510Sdarrenr 241145510Sdarrenr case BPF_LD|BPF_H|BPF_ABS: 242145510Sdarrenr k = pc->k; 243145510Sdarrenr if (k + sizeof(short) > buflen) { 244145510Sdarrenr if (m == NULL) 245145510Sdarrenr return 0; 246145510Sdarrenr A = m_xhalf(m, k, &merr); 247145510Sdarrenr if (merr != 0) 248145510Sdarrenr return 0; 249145510Sdarrenr continue; 250145510Sdarrenr } 251145510Sdarrenr A = EXTRACT_SHORT(&p[k]); 252145510Sdarrenr continue; 253145510Sdarrenr 254145510Sdarrenr case BPF_LD|BPF_B|BPF_ABS: 255145510Sdarrenr k = pc->k; 256145510Sdarrenr if (k >= buflen) { 257145510Sdarrenr if (m == NULL) 258145510Sdarrenr return 0; 259145510Sdarrenr n = m; 260145510Sdarrenr MINDEX(len, n, k); 261145510Sdarrenr A = MTOD(n, u_char *)[k]; 262145510Sdarrenr continue; 263145510Sdarrenr } 264145510Sdarrenr A = p[k]; 265145510Sdarrenr continue; 266145510Sdarrenr 267145510Sdarrenr case BPF_LD|BPF_W|BPF_LEN: 268145510Sdarrenr A = wirelen; 269145510Sdarrenr continue; 270145510Sdarrenr 271145510Sdarrenr case BPF_LDX|BPF_W|BPF_LEN: 272145510Sdarrenr X = wirelen; 273145510Sdarrenr continue; 274145510Sdarrenr 275145510Sdarrenr case BPF_LD|BPF_W|BPF_IND: 276145510Sdarrenr k = X + pc->k; 277145510Sdarrenr if (k + sizeof(int32) > buflen) { 278145510Sdarrenr if (m == NULL) 279145510Sdarrenr return 0; 280145510Sdarrenr A = m_xword(m, k, &merr); 281145510Sdarrenr if (merr != 0) 282145510Sdarrenr return 0; 283145510Sdarrenr continue; 284145510Sdarrenr } 285145510Sdarrenr A = EXTRACT_LONG(&p[k]); 286145510Sdarrenr continue; 287145510Sdarrenr 288145510Sdarrenr case BPF_LD|BPF_H|BPF_IND: 289145510Sdarrenr k = X + pc->k; 290145510Sdarrenr if (k + sizeof(short) > buflen) { 291145510Sdarrenr if (m == NULL) 292145510Sdarrenr return 0; 293145510Sdarrenr A = m_xhalf(m, k, &merr); 294145510Sdarrenr if (merr != 0) 295145510Sdarrenr return 0; 296145510Sdarrenr continue; 297145510Sdarrenr } 298145510Sdarrenr A = EXTRACT_SHORT(&p[k]); 299145510Sdarrenr continue; 300145510Sdarrenr 301145510Sdarrenr case BPF_LD|BPF_B|BPF_IND: 302145510Sdarrenr k = X + pc->k; 303145510Sdarrenr if (k >= buflen) { 304145510Sdarrenr if (m == NULL) 305145510Sdarrenr return 0; 306145510Sdarrenr n = m; 307145510Sdarrenr MINDEX(len, n, k); 308145510Sdarrenr A = MTOD(n, u_char *)[k]; 309145510Sdarrenr continue; 310145510Sdarrenr } 311145510Sdarrenr A = p[k]; 312145510Sdarrenr continue; 313145510Sdarrenr 314145510Sdarrenr case BPF_LDX|BPF_MSH|BPF_B: 315145510Sdarrenr k = pc->k; 316145510Sdarrenr if (k >= buflen) { 317145510Sdarrenr if (m == NULL) 318145510Sdarrenr return 0; 319145510Sdarrenr n = m; 320145510Sdarrenr MINDEX(len, n, k); 321145510Sdarrenr X = (MTOD(n, char *)[k] & 0xf) << 2; 322145510Sdarrenr continue; 323145510Sdarrenr } 324145510Sdarrenr X = (p[pc->k] & 0xf) << 2; 325145510Sdarrenr continue; 326145510Sdarrenr 327145510Sdarrenr case BPF_LD|BPF_IMM: 328145510Sdarrenr A = pc->k; 329145510Sdarrenr continue; 330145510Sdarrenr 331145510Sdarrenr case BPF_LDX|BPF_IMM: 332145510Sdarrenr X = pc->k; 333145510Sdarrenr continue; 334145510Sdarrenr 335145510Sdarrenr case BPF_LD|BPF_MEM: 336145510Sdarrenr A = mem[pc->k]; 337145510Sdarrenr continue; 338145510Sdarrenr 339145510Sdarrenr case BPF_LDX|BPF_MEM: 340145510Sdarrenr X = mem[pc->k]; 341145510Sdarrenr continue; 342145510Sdarrenr 343145510Sdarrenr case BPF_ST: 344145510Sdarrenr mem[pc->k] = A; 345145510Sdarrenr continue; 346145510Sdarrenr 347145510Sdarrenr case BPF_STX: 348145510Sdarrenr mem[pc->k] = X; 349145510Sdarrenr continue; 350145510Sdarrenr 351145510Sdarrenr case BPF_JMP|BPF_JA: 352145510Sdarrenr pc += pc->k; 353145510Sdarrenr continue; 354145510Sdarrenr 355145510Sdarrenr case BPF_JMP|BPF_JGT|BPF_K: 356145510Sdarrenr pc += (A > pc->k) ? pc->jt : pc->jf; 357145510Sdarrenr continue; 358145510Sdarrenr 359145510Sdarrenr case BPF_JMP|BPF_JGE|BPF_K: 360145510Sdarrenr pc += (A >= pc->k) ? pc->jt : pc->jf; 361145510Sdarrenr continue; 362145510Sdarrenr 363145510Sdarrenr case BPF_JMP|BPF_JEQ|BPF_K: 364145510Sdarrenr pc += (A == pc->k) ? pc->jt : pc->jf; 365145510Sdarrenr continue; 366145510Sdarrenr 367145510Sdarrenr case BPF_JMP|BPF_JSET|BPF_K: 368145510Sdarrenr pc += (A & pc->k) ? pc->jt : pc->jf; 369145510Sdarrenr continue; 370145510Sdarrenr 371145510Sdarrenr case BPF_JMP|BPF_JGT|BPF_X: 372145510Sdarrenr pc += (A > X) ? pc->jt : pc->jf; 373145510Sdarrenr continue; 374145510Sdarrenr 375145510Sdarrenr case BPF_JMP|BPF_JGE|BPF_X: 376145510Sdarrenr pc += (A >= X) ? pc->jt : pc->jf; 377145510Sdarrenr continue; 378145510Sdarrenr 379145510Sdarrenr case BPF_JMP|BPF_JEQ|BPF_X: 380145510Sdarrenr pc += (A == X) ? pc->jt : pc->jf; 381145510Sdarrenr continue; 382145510Sdarrenr 383145510Sdarrenr case BPF_JMP|BPF_JSET|BPF_X: 384145510Sdarrenr pc += (A & X) ? pc->jt : pc->jf; 385145510Sdarrenr continue; 386145510Sdarrenr 387145510Sdarrenr case BPF_ALU|BPF_ADD|BPF_X: 388145510Sdarrenr A += X; 389145510Sdarrenr continue; 390145510Sdarrenr 391145510Sdarrenr case BPF_ALU|BPF_SUB|BPF_X: 392145510Sdarrenr A -= X; 393145510Sdarrenr continue; 394145510Sdarrenr 395145510Sdarrenr case BPF_ALU|BPF_MUL|BPF_X: 396145510Sdarrenr A *= X; 397145510Sdarrenr continue; 398145510Sdarrenr 399145510Sdarrenr case BPF_ALU|BPF_DIV|BPF_X: 400145510Sdarrenr if (X == 0) 401145510Sdarrenr return 0; 402145510Sdarrenr A /= X; 403145510Sdarrenr continue; 404145510Sdarrenr 405145510Sdarrenr case BPF_ALU|BPF_AND|BPF_X: 406145510Sdarrenr A &= X; 407145510Sdarrenr continue; 408145510Sdarrenr 409145510Sdarrenr case BPF_ALU|BPF_OR|BPF_X: 410145510Sdarrenr A |= X; 411145510Sdarrenr continue; 412145510Sdarrenr 413145510Sdarrenr case BPF_ALU|BPF_LSH|BPF_X: 414145510Sdarrenr A <<= X; 415145510Sdarrenr continue; 416145510Sdarrenr 417145510Sdarrenr case BPF_ALU|BPF_RSH|BPF_X: 418145510Sdarrenr A >>= X; 419145510Sdarrenr continue; 420145510Sdarrenr 421145510Sdarrenr case BPF_ALU|BPF_ADD|BPF_K: 422145510Sdarrenr A += pc->k; 423145510Sdarrenr continue; 424145510Sdarrenr 425145510Sdarrenr case BPF_ALU|BPF_SUB|BPF_K: 426145510Sdarrenr A -= pc->k; 427145510Sdarrenr continue; 428145510Sdarrenr 429145510Sdarrenr case BPF_ALU|BPF_MUL|BPF_K: 430145510Sdarrenr A *= pc->k; 431145510Sdarrenr continue; 432145510Sdarrenr 433145510Sdarrenr case BPF_ALU|BPF_DIV|BPF_K: 434145510Sdarrenr A /= pc->k; 435145510Sdarrenr continue; 436145510Sdarrenr 437145510Sdarrenr case BPF_ALU|BPF_AND|BPF_K: 438145510Sdarrenr A &= pc->k; 439145510Sdarrenr continue; 440145510Sdarrenr 441145510Sdarrenr case BPF_ALU|BPF_OR|BPF_K: 442145510Sdarrenr A |= pc->k; 443145510Sdarrenr continue; 444145510Sdarrenr 445145510Sdarrenr case BPF_ALU|BPF_LSH|BPF_K: 446145510Sdarrenr A <<= pc->k; 447145510Sdarrenr continue; 448145510Sdarrenr 449145510Sdarrenr case BPF_ALU|BPF_RSH|BPF_K: 450145510Sdarrenr A >>= pc->k; 451145510Sdarrenr continue; 452145510Sdarrenr 453145510Sdarrenr case BPF_ALU|BPF_NEG: 454145510Sdarrenr A = -A; 455145510Sdarrenr continue; 456145510Sdarrenr 457145510Sdarrenr case BPF_MISC|BPF_TAX: 458145510Sdarrenr X = A; 459145510Sdarrenr continue; 460145510Sdarrenr 461145510Sdarrenr case BPF_MISC|BPF_TXA: 462145510Sdarrenr A = X; 463145510Sdarrenr continue; 464145510Sdarrenr } 465145510Sdarrenr } 466145510Sdarrenr} 467145510Sdarrenr 468145510Sdarrenr 469145510Sdarrenr/* 470145510Sdarrenr * Return true if the 'fcode' is a valid filter program. 471145510Sdarrenr * The constraints are that each jump be forward and to a valid 472161357Sguido * code, that memory accesses are within valid ranges (to the 473161357Sguido * extent that this can be checked statically; loads of packet 474161357Sguido * data have to be, and are, also checked at run time), and that 475161357Sguido * the code terminates with either an accept or reject. 476145510Sdarrenr * 477145510Sdarrenr * The kernel needs to be able to verify an application's filter code. 478145510Sdarrenr * Otherwise, a bogus program could easily crash the system. 479145510Sdarrenr */ 480145510Sdarrenrint 481145510Sdarrenrbpf_validate(f, len) 482145510Sdarrenr struct bpf_insn *f; 483145510Sdarrenr int len; 484145510Sdarrenr{ 485161357Sguido u_int i, from; 486161357Sguido const struct bpf_insn *p; 487145510Sdarrenr 488161357Sguido if (len == 0) 489161357Sguido return 1; 490161357Sguido 491161357Sguido if (len < 1 || len > BPF_MAXINSNS) 492161357Sguido return 0; 493161357Sguido 494145510Sdarrenr for (i = 0; i < len; ++i) { 495161357Sguido p = &f[i]; 496161357Sguido switch (BPF_CLASS(p->code)) { 497145510Sdarrenr /* 498161357Sguido * Check that memory operations use valid addresses. 499145510Sdarrenr */ 500161357Sguido case BPF_LD: 501161357Sguido case BPF_LDX: 502161357Sguido switch (BPF_MODE(p->code)) { 503161357Sguido case BPF_IMM: 504161357Sguido break; 505161357Sguido case BPF_ABS: 506161357Sguido case BPF_IND: 507161357Sguido case BPF_MSH: 508161357Sguido /* 509161357Sguido * More strict check with actual packet length 510161357Sguido * is done runtime. 511161357Sguido */ 512161357Sguido#if 0 513161357Sguido if (p->k >= bpf_maxbufsize) 514145510Sdarrenr return 0; 515161357Sguido#endif 516161357Sguido break; 517161357Sguido case BPF_MEM: 518161357Sguido if (p->k >= BPF_MEMWORDS) 519161357Sguido return 0; 520161357Sguido break; 521161357Sguido case BPF_LEN: 522161357Sguido break; 523161357Sguido default: 524161357Sguido return 0; 525145510Sdarrenr } 526161357Sguido break; 527161357Sguido case BPF_ST: 528161357Sguido case BPF_STX: 529161357Sguido if (p->k >= BPF_MEMWORDS) 530145510Sdarrenr return 0; 531161357Sguido break; 532161357Sguido case BPF_ALU: 533161357Sguido switch (BPF_OP(p->code)) { 534161357Sguido case BPF_ADD: 535161357Sguido case BPF_SUB: 536161357Sguido case BPF_OR: 537161357Sguido case BPF_AND: 538161357Sguido case BPF_LSH: 539161357Sguido case BPF_RSH: 540161357Sguido case BPF_NEG: 541161357Sguido break; 542161357Sguido case BPF_DIV: 543161357Sguido /* 544161357Sguido * Check for constant division by 0. 545161357Sguido */ 546161357Sguido if (BPF_RVAL(p->code) == BPF_K && p->k == 0) 547161357Sguido return 0; 548161357Sguido default: 549161357Sguido return 0; 550161357Sguido } 551161357Sguido break; 552161357Sguido case BPF_JMP: 553161357Sguido /* 554161357Sguido * Check that jumps are within the code block, 555161357Sguido * and that unconditional branches don't go 556161357Sguido * backwards as a result of an overflow. 557161357Sguido * Unconditional branches have a 32-bit offset, 558161357Sguido * so they could overflow; we check to make 559161357Sguido * sure they don't. Conditional branches have 560161357Sguido * an 8-bit offset, and the from address is <= 561161357Sguido * BPF_MAXINSNS, and we assume that BPF_MAXINSNS 562161357Sguido * is sufficiently small that adding 255 to it 563161357Sguido * won't overflow. 564161357Sguido * 565161357Sguido * We know that len is <= BPF_MAXINSNS, and we 566161357Sguido * assume that BPF_MAXINSNS is < the maximum size 567161357Sguido * of a u_int, so that i + 1 doesn't overflow. 568161357Sguido */ 569161357Sguido from = i + 1; 570161357Sguido switch (BPF_OP(p->code)) { 571161357Sguido case BPF_JA: 572161357Sguido if (from + p->k < from || from + p->k >= len) 573161357Sguido return 0; 574161357Sguido break; 575161357Sguido case BPF_JEQ: 576161357Sguido case BPF_JGT: 577161357Sguido case BPF_JGE: 578161357Sguido case BPF_JSET: 579161357Sguido if (from + p->jt >= len || from + p->jf >= len) 580161357Sguido return 0; 581161357Sguido break; 582161357Sguido default: 583161357Sguido return 0; 584161357Sguido } 585161357Sguido break; 586161357Sguido case BPF_RET: 587161357Sguido break; 588161357Sguido case BPF_MISC: 589161357Sguido break; 590161357Sguido default: 591161357Sguido return 0; 592145510Sdarrenr } 593145510Sdarrenr } 594145510Sdarrenr return BPF_CLASS(f[len - 1].code) == BPF_RET; 595145510Sdarrenr} 596