1 /* $OpenBSD: bpf_filter.c,v 1.32 2016/09/13 12:09:53 krw Exp $ */ 2 /* $NetBSD: bpf_filter.c,v 1.12 1996/02/13 22:00:00 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1990, 1991, 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from the Stanford/CMU enet packet filter, 9 * (net/enet.c) distributed as part of 4.3BSD, and code contributed 10 * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 11 * Berkeley Laboratory. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93 38 */ 39 40 #include <sys/param.h> 41 #include <sys/types.h> 42 #include <sys/time.h> 43 #ifndef _KERNEL 44 #include <stdlib.h> 45 #include <string.h> 46 #include "pcap.h" 47 #else 48 #include <sys/systm.h> 49 #endif 50 51 #include <sys/endian.h> 52 53 #ifdef _KERNEL 54 extern int bpf_maxbufsize; 55 #define Static 56 #else /* _KERNEL */ 57 #define Static static 58 #endif /* _KERNEL */ 59 60 #include <net/bpf.h> 61 62 struct bpf_mem { 63 const u_char *pkt; 64 u_int len; 65 }; 66 67 Static u_int32_t bpf_mem_ldw(const void *, u_int32_t, int *); 68 Static u_int32_t bpf_mem_ldh(const void *, u_int32_t, int *); 69 Static u_int32_t bpf_mem_ldb(const void *, u_int32_t, int *); 70 71 static const struct bpf_ops bpf_mem_ops = { 72 bpf_mem_ldw, 73 bpf_mem_ldh, 74 bpf_mem_ldb, 75 }; 76 77 Static u_int32_t 78 bpf_mem_ldw(const void *mem, u_int32_t k, int *err) 79 { 80 const struct bpf_mem *bm = mem; 81 u_int32_t v; 82 83 *err = 1; 84 85 if (k + sizeof(v) > bm->len) 86 return (0); 87 88 memcpy(&v, bm->pkt + k, sizeof(v)); 89 90 *err = 0; 91 return ntohl(v); 92 } 93 94 Static u_int32_t 95 bpf_mem_ldh(const void *mem, u_int32_t k, int *err) 96 { 97 const struct bpf_mem *bm = mem; 98 u_int16_t v; 99 100 *err = 1; 101 102 if (k + sizeof(v) > bm->len) 103 return (0); 104 105 memcpy(&v, bm->pkt + k, sizeof(v)); 106 107 *err = 0; 108 return ntohs(v); 109 } 110 111 Static u_int32_t 112 bpf_mem_ldb(const void *mem, u_int32_t k, int *err) 113 { 114 const struct bpf_mem *bm = mem; 115 116 *err = 1; 117 118 if (k >= bm->len) 119 return (0); 120 121 *err = 0; 122 return bm->pkt[k]; 123 } 124 125 /* 126 * Execute the filter program starting at pc on the packet p 127 * wirelen is the length of the original packet 128 * buflen is the amount of data present 129 */ 130 u_int 131 bpf_filter(const struct bpf_insn *pc, const u_char *pkt, 132 u_int wirelen, u_int buflen) 133 { 134 struct bpf_mem bm; 135 136 bm.pkt = pkt; 137 bm.len = buflen; 138 139 return _bpf_filter(pc, &bpf_mem_ops, &bm, wirelen); 140 } 141 142 u_int 143 _bpf_filter(const struct bpf_insn *pc, const struct bpf_ops *ops, 144 const void *pkt, u_int wirelen) 145 { 146 u_int32_t A = 0, X = 0; 147 u_int32_t k; 148 int32_t mem[BPF_MEMWORDS]; 149 int err; 150 151 if (pc == NULL) { 152 /* 153 * No filter means accept all. 154 */ 155 return (u_int)-1; 156 } 157 158 memset(mem, 0, sizeof(mem)); 159 160 --pc; 161 while (1) { 162 ++pc; 163 switch (pc->code) { 164 165 default: 166 #ifdef _KERNEL 167 return 0; 168 #else 169 abort(); 170 #endif 171 case BPF_RET|BPF_K: 172 return (u_int)pc->k; 173 174 case BPF_RET|BPF_A: 175 return (u_int)A; 176 177 case BPF_LD|BPF_W|BPF_ABS: 178 A = ops->ldw(pkt, pc->k, &err); 179 if (err != 0) 180 return 0; 181 continue; 182 183 case BPF_LD|BPF_H|BPF_ABS: 184 A = ops->ldh(pkt, pc->k, &err); 185 if (err != 0) 186 return 0; 187 continue; 188 189 case BPF_LD|BPF_B|BPF_ABS: 190 A = ops->ldb(pkt, pc->k, &err); 191 if (err != 0) 192 return 0; 193 continue; 194 195 case BPF_LD|BPF_W|BPF_LEN: 196 A = wirelen; 197 continue; 198 199 case BPF_LDX|BPF_W|BPF_LEN: 200 X = wirelen; 201 continue; 202 203 case BPF_LD|BPF_W|BPF_IND: 204 k = X + pc->k; 205 A = ops->ldw(pkt, k, &err); 206 if (err != 0) 207 return 0; 208 continue; 209 210 case BPF_LD|BPF_H|BPF_IND: 211 k = X + pc->k; 212 A = ops->ldh(pkt, k, &err); 213 if (err != 0) 214 return 0; 215 continue; 216 217 case BPF_LD|BPF_B|BPF_IND: 218 k = X + pc->k; 219 A = ops->ldb(pkt, k, &err); 220 if (err != 0) 221 return 0; 222 continue; 223 224 case BPF_LDX|BPF_MSH|BPF_B: 225 X = ops->ldb(pkt, pc->k, &err); 226 if (err != 0) 227 return 0; 228 X &= 0xf; 229 X <<= 2; 230 continue; 231 232 case BPF_LD|BPF_IMM: 233 A = pc->k; 234 continue; 235 236 case BPF_LDX|BPF_IMM: 237 X = pc->k; 238 continue; 239 240 case BPF_LD|BPF_MEM: 241 A = mem[pc->k]; 242 continue; 243 244 case BPF_LDX|BPF_MEM: 245 X = mem[pc->k]; 246 continue; 247 248 case BPF_ST: 249 mem[pc->k] = A; 250 continue; 251 252 case BPF_STX: 253 mem[pc->k] = X; 254 continue; 255 256 case BPF_JMP|BPF_JA: 257 pc += pc->k; 258 continue; 259 260 case BPF_JMP|BPF_JGT|BPF_K: 261 pc += (A > pc->k) ? pc->jt : pc->jf; 262 continue; 263 264 case BPF_JMP|BPF_JGE|BPF_K: 265 pc += (A >= pc->k) ? pc->jt : pc->jf; 266 continue; 267 268 case BPF_JMP|BPF_JEQ|BPF_K: 269 pc += (A == pc->k) ? pc->jt : pc->jf; 270 continue; 271 272 case BPF_JMP|BPF_JSET|BPF_K: 273 pc += (A & pc->k) ? pc->jt : pc->jf; 274 continue; 275 276 case BPF_JMP|BPF_JGT|BPF_X: 277 pc += (A > X) ? pc->jt : pc->jf; 278 continue; 279 280 case BPF_JMP|BPF_JGE|BPF_X: 281 pc += (A >= X) ? pc->jt : pc->jf; 282 continue; 283 284 case BPF_JMP|BPF_JEQ|BPF_X: 285 pc += (A == X) ? pc->jt : pc->jf; 286 continue; 287 288 case BPF_JMP|BPF_JSET|BPF_X: 289 pc += (A & X) ? pc->jt : pc->jf; 290 continue; 291 292 case BPF_ALU|BPF_ADD|BPF_X: 293 A += X; 294 continue; 295 296 case BPF_ALU|BPF_SUB|BPF_X: 297 A -= X; 298 continue; 299 300 case BPF_ALU|BPF_MUL|BPF_X: 301 A *= X; 302 continue; 303 304 case BPF_ALU|BPF_DIV|BPF_X: 305 if (X == 0) 306 return 0; 307 A /= X; 308 continue; 309 310 case BPF_ALU|BPF_AND|BPF_X: 311 A &= X; 312 continue; 313 314 case BPF_ALU|BPF_OR|BPF_X: 315 A |= X; 316 continue; 317 318 case BPF_ALU|BPF_LSH|BPF_X: 319 A <<= X; 320 continue; 321 322 case BPF_ALU|BPF_RSH|BPF_X: 323 A >>= X; 324 continue; 325 326 case BPF_ALU|BPF_ADD|BPF_K: 327 A += pc->k; 328 continue; 329 330 case BPF_ALU|BPF_SUB|BPF_K: 331 A -= pc->k; 332 continue; 333 334 case BPF_ALU|BPF_MUL|BPF_K: 335 A *= pc->k; 336 continue; 337 338 case BPF_ALU|BPF_DIV|BPF_K: 339 A /= pc->k; 340 continue; 341 342 case BPF_ALU|BPF_AND|BPF_K: 343 A &= pc->k; 344 continue; 345 346 case BPF_ALU|BPF_OR|BPF_K: 347 A |= pc->k; 348 continue; 349 350 case BPF_ALU|BPF_LSH|BPF_K: 351 A <<= pc->k; 352 continue; 353 354 case BPF_ALU|BPF_RSH|BPF_K: 355 A >>= pc->k; 356 continue; 357 358 case BPF_ALU|BPF_NEG: 359 A = -A; 360 continue; 361 362 case BPF_MISC|BPF_TAX: 363 X = A; 364 continue; 365 366 case BPF_MISC|BPF_TXA: 367 A = X; 368 continue; 369 } 370 } 371 } 372 373 #ifdef _KERNEL 374 /* 375 * Return true if the 'fcode' is a valid filter program. 376 * The constraints are that each jump be forward and to a valid 377 * code and memory operations use valid addresses. The code 378 * must terminate with either an accept or reject. 379 * 380 * The kernel needs to be able to verify an application's filter code. 381 * Otherwise, a bogus program could easily crash the system. 382 */ 383 int 384 bpf_validate(struct bpf_insn *f, int len) 385 { 386 u_int i, from; 387 struct bpf_insn *p; 388 389 if (len < 1 || len > BPF_MAXINSNS) 390 return 0; 391 392 for (i = 0; i < len; ++i) { 393 p = &f[i]; 394 switch (BPF_CLASS(p->code)) { 395 /* 396 * Check that memory operations use valid addresses. 397 */ 398 case BPF_LD: 399 case BPF_LDX: 400 switch (BPF_MODE(p->code)) { 401 case BPF_IMM: 402 break; 403 case BPF_ABS: 404 case BPF_IND: 405 case BPF_MSH: 406 /* 407 * More strict check with actual packet length 408 * is done runtime. 409 */ 410 if (p->k >= bpf_maxbufsize) 411 return 0; 412 break; 413 case BPF_MEM: 414 if (p->k >= BPF_MEMWORDS) 415 return 0; 416 break; 417 case BPF_LEN: 418 break; 419 default: 420 return 0; 421 } 422 break; 423 case BPF_ST: 424 case BPF_STX: 425 if (p->k >= BPF_MEMWORDS) 426 return 0; 427 break; 428 case BPF_ALU: 429 switch (BPF_OP(p->code)) { 430 case BPF_ADD: 431 case BPF_SUB: 432 case BPF_MUL: 433 case BPF_OR: 434 case BPF_AND: 435 case BPF_LSH: 436 case BPF_RSH: 437 case BPF_NEG: 438 break; 439 case BPF_DIV: 440 /* 441 * Check for constant division by 0. 442 */ 443 if (BPF_SRC(p->code) == BPF_K && p->k == 0) 444 return 0; 445 break; 446 default: 447 return 0; 448 } 449 break; 450 case BPF_JMP: 451 /* 452 * Check that jumps are forward, and within 453 * the code block. 454 */ 455 from = i + 1; 456 switch (BPF_OP(p->code)) { 457 case BPF_JA: 458 if (from + p->k < from || from + p->k >= len) 459 return 0; 460 break; 461 case BPF_JEQ: 462 case BPF_JGT: 463 case BPF_JGE: 464 case BPF_JSET: 465 if (from + p->jt >= len || from + p->jf >= len) 466 return 0; 467 break; 468 default: 469 return 0; 470 } 471 break; 472 case BPF_RET: 473 break; 474 case BPF_MISC: 475 break; 476 default: 477 return 0; 478 } 479 480 } 481 return BPF_CLASS(f[len - 1].code) == BPF_RET; 482 } 483 #endif 484