The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/bpf_filter.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: bpf_filter.c,v 1.34 2020/08/03 03:21:24 dlg 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/time.h>
   42 #ifndef _KERNEL
   43 #include <stdlib.h>
   44 #include <string.h>
   45 #include "pcap.h"
   46 #else
   47 #include <sys/systm.h>
   48 #endif
   49 
   50 #include <sys/endian.h>
   51 
   52 #ifdef _KERNEL
   53 extern int bpf_maxbufsize;
   54 #define Static
   55 #else /* _KERNEL */
   56 #define Static static
   57 #endif /* _KERNEL */
   58 
   59 #include <net/bpf.h>
   60 
   61 struct bpf_mem {
   62         const u_char    *pkt;
   63         u_int            len;
   64 };
   65 
   66 Static u_int32_t        bpf_mem_ldw(const void *, u_int32_t, int *);
   67 Static u_int32_t        bpf_mem_ldh(const void *, u_int32_t, int *);
   68 Static u_int32_t        bpf_mem_ldb(const void *, u_int32_t, int *);
   69 
   70 static const struct bpf_ops bpf_mem_ops = {
   71         bpf_mem_ldw,
   72         bpf_mem_ldh,
   73         bpf_mem_ldb,
   74 };
   75 
   76 Static u_int32_t
   77 bpf_mem_ldw(const void *mem, u_int32_t k, int *err)
   78 {
   79         const struct bpf_mem *bm = mem;
   80         u_int32_t v;
   81 
   82         *err = 1;
   83 
   84         if (k + sizeof(v) > bm->len)
   85                 return (0);
   86 
   87         memcpy(&v, bm->pkt + k, sizeof(v));
   88 
   89         *err = 0;
   90         return ntohl(v);
   91 }
   92 
   93 Static u_int32_t
   94 bpf_mem_ldh(const void *mem, u_int32_t k, int *err)
   95 {
   96         const struct bpf_mem *bm = mem;
   97         u_int16_t v;
   98 
   99         *err = 1;
  100 
  101         if (k + sizeof(v) > bm->len)
  102                 return (0);
  103 
  104         memcpy(&v, bm->pkt + k, sizeof(v));
  105 
  106         *err = 0;
  107         return ntohs(v);
  108 }
  109 
  110 Static u_int32_t
  111 bpf_mem_ldb(const void *mem, u_int32_t k, int *err)
  112 {
  113         const struct bpf_mem *bm = mem;
  114 
  115         *err = 1;
  116 
  117         if (k >= bm->len)
  118                 return (0);
  119 
  120         *err = 0;
  121         return bm->pkt[k];
  122 }
  123 
  124 /*
  125  * Execute the filter program starting at pc on the packet p
  126  * wirelen is the length of the original packet
  127  * buflen is the amount of data present
  128  */
  129 u_int
  130 bpf_filter(const struct bpf_insn *pc, const u_char *pkt,
  131     u_int wirelen, u_int buflen)
  132 {
  133         struct bpf_mem bm;
  134 
  135         bm.pkt = pkt;
  136         bm.len = buflen;
  137 
  138         return _bpf_filter(pc, &bpf_mem_ops, &bm, wirelen);
  139 }
  140 
  141 u_int
  142 _bpf_filter(const struct bpf_insn *pc, const struct bpf_ops *ops,
  143     const void *pkt, u_int wirelen)
  144 {
  145         u_int32_t A = 0, X = 0;
  146         u_int32_t k;
  147         int32_t mem[BPF_MEMWORDS];
  148         int err;
  149 
  150         if (pc == NULL) {
  151                 /*
  152                  * No filter means accept all.
  153                  */
  154                 return (u_int)-1;
  155         }
  156 
  157         memset(mem, 0, sizeof(mem));
  158 
  159         --pc;
  160         while (1) {
  161                 ++pc;
  162                 switch (pc->code) {
  163 
  164                 default:
  165 #ifdef _KERNEL
  166                         return 0;
  167 #else
  168                         abort();
  169 #endif
  170                 case BPF_RET|BPF_K:
  171                         return (u_int)pc->k;
  172 
  173                 case BPF_RET|BPF_A:
  174                         return (u_int)A;
  175 
  176                 case BPF_LD|BPF_W|BPF_ABS:
  177                         A = ops->ldw(pkt, pc->k, &err);
  178                         if (err != 0)
  179                                 return 0;
  180                         continue;
  181 
  182                 case BPF_LD|BPF_H|BPF_ABS:
  183                         A = ops->ldh(pkt, pc->k, &err);
  184                         if (err != 0)
  185                                 return 0;
  186                         continue;
  187 
  188                 case BPF_LD|BPF_B|BPF_ABS:
  189                         A = ops->ldb(pkt, pc->k, &err);
  190                         if (err != 0)
  191                                 return 0;
  192                         continue;
  193 
  194                 case BPF_LD|BPF_W|BPF_LEN:
  195                         A = wirelen;
  196                         continue;
  197 
  198                 case BPF_LDX|BPF_W|BPF_LEN:
  199                         X = wirelen;
  200                         continue;
  201 
  202                 case BPF_LD|BPF_W|BPF_RND:
  203                         A = arc4random();
  204                         continue;
  205 
  206                 case BPF_LD|BPF_W|BPF_IND:
  207                         k = X + pc->k;
  208                         A = ops->ldw(pkt, k, &err);
  209                         if (err != 0)
  210                                 return 0;
  211                         continue;
  212 
  213                 case BPF_LD|BPF_H|BPF_IND:
  214                         k = X + pc->k;
  215                         A = ops->ldh(pkt, k, &err);
  216                         if (err != 0)
  217                                 return 0;
  218                         continue;
  219 
  220                 case BPF_LD|BPF_B|BPF_IND:
  221                         k = X + pc->k;
  222                         A = ops->ldb(pkt, k, &err);
  223                         if (err != 0)
  224                                 return 0;
  225                         continue;
  226 
  227                 case BPF_LDX|BPF_MSH|BPF_B:
  228                         X = ops->ldb(pkt, pc->k, &err);
  229                         if (err != 0)
  230                                 return 0;
  231                         X &= 0xf;
  232                         X <<= 2;
  233                         continue;
  234 
  235                 case BPF_LD|BPF_IMM:
  236                         A = pc->k;
  237                         continue;
  238 
  239                 case BPF_LDX|BPF_IMM:
  240                         X = pc->k;
  241                         continue;
  242 
  243                 case BPF_LD|BPF_MEM:
  244                         A = mem[pc->k];
  245                         continue;
  246 
  247                 case BPF_LDX|BPF_MEM:
  248                         X = mem[pc->k];
  249                         continue;
  250 
  251                 case BPF_ST:
  252                         mem[pc->k] = A;
  253                         continue;
  254 
  255                 case BPF_STX:
  256                         mem[pc->k] = X;
  257                         continue;
  258 
  259                 case BPF_JMP|BPF_JA:
  260                         pc += pc->k;
  261                         continue;
  262 
  263                 case BPF_JMP|BPF_JGT|BPF_K:
  264                         pc += (A > pc->k) ? pc->jt : pc->jf;
  265                         continue;
  266 
  267                 case BPF_JMP|BPF_JGE|BPF_K:
  268                         pc += (A >= pc->k) ? pc->jt : pc->jf;
  269                         continue;
  270 
  271                 case BPF_JMP|BPF_JEQ|BPF_K:
  272                         pc += (A == pc->k) ? pc->jt : pc->jf;
  273                         continue;
  274 
  275                 case BPF_JMP|BPF_JSET|BPF_K:
  276                         pc += (A & pc->k) ? pc->jt : pc->jf;
  277                         continue;
  278 
  279                 case BPF_JMP|BPF_JGT|BPF_X:
  280                         pc += (A > X) ? pc->jt : pc->jf;
  281                         continue;
  282 
  283                 case BPF_JMP|BPF_JGE|BPF_X:
  284                         pc += (A >= X) ? pc->jt : pc->jf;
  285                         continue;
  286 
  287                 case BPF_JMP|BPF_JEQ|BPF_X:
  288                         pc += (A == X) ? pc->jt : pc->jf;
  289                         continue;
  290 
  291                 case BPF_JMP|BPF_JSET|BPF_X:
  292                         pc += (A & X) ? pc->jt : pc->jf;
  293                         continue;
  294 
  295                 case BPF_ALU|BPF_ADD|BPF_X:
  296                         A += X;
  297                         continue;
  298 
  299                 case BPF_ALU|BPF_SUB|BPF_X:
  300                         A -= X;
  301                         continue;
  302 
  303                 case BPF_ALU|BPF_MUL|BPF_X:
  304                         A *= X;
  305                         continue;
  306 
  307                 case BPF_ALU|BPF_DIV|BPF_X:
  308                         if (X == 0)
  309                                 return 0;
  310                         A /= X;
  311                         continue;
  312 
  313                 case BPF_ALU|BPF_AND|BPF_X:
  314                         A &= X;
  315                         continue;
  316 
  317                 case BPF_ALU|BPF_OR|BPF_X:
  318                         A |= X;
  319                         continue;
  320 
  321                 case BPF_ALU|BPF_LSH|BPF_X:
  322                         A <<= X;
  323                         continue;
  324 
  325                 case BPF_ALU|BPF_RSH|BPF_X:
  326                         A >>= X;
  327                         continue;
  328 
  329                 case BPF_ALU|BPF_ADD|BPF_K:
  330                         A += pc->k;
  331                         continue;
  332 
  333                 case BPF_ALU|BPF_SUB|BPF_K:
  334                         A -= pc->k;
  335                         continue;
  336 
  337                 case BPF_ALU|BPF_MUL|BPF_K:
  338                         A *= pc->k;
  339                         continue;
  340 
  341                 case BPF_ALU|BPF_DIV|BPF_K:
  342                         A /= pc->k;
  343                         continue;
  344 
  345                 case BPF_ALU|BPF_AND|BPF_K:
  346                         A &= pc->k;
  347                         continue;
  348 
  349                 case BPF_ALU|BPF_OR|BPF_K:
  350                         A |= pc->k;
  351                         continue;
  352 
  353                 case BPF_ALU|BPF_LSH|BPF_K:
  354                         A <<= pc->k;
  355                         continue;
  356 
  357                 case BPF_ALU|BPF_RSH|BPF_K:
  358                         A >>= pc->k;
  359                         continue;
  360 
  361                 case BPF_ALU|BPF_NEG:
  362                         A = -A;
  363                         continue;
  364 
  365                 case BPF_MISC|BPF_TAX:
  366                         X = A;
  367                         continue;
  368 
  369                 case BPF_MISC|BPF_TXA:
  370                         A = X;
  371                         continue;
  372                 }
  373         }
  374 }
  375 
  376 #ifdef _KERNEL
  377 /*
  378  * Return true if the 'fcode' is a valid filter program.
  379  * The constraints are that each jump be forward and to a valid
  380  * code and memory operations use valid addresses.  The code
  381  * must terminate with either an accept or reject.
  382  *
  383  * The kernel needs to be able to verify an application's filter code.
  384  * Otherwise, a bogus program could easily crash the system.
  385  */
  386 int
  387 bpf_validate(struct bpf_insn *f, int len)
  388 {
  389         u_int i, from;
  390         struct bpf_insn *p;
  391 
  392         if (len < 1 || len > BPF_MAXINSNS)
  393                 return 0;
  394 
  395         for (i = 0; i < len; ++i) {
  396                 p = &f[i];
  397                 switch (BPF_CLASS(p->code)) {
  398                 /*
  399                  * Check that memory operations use valid addresses.
  400                  */
  401                 case BPF_LD:
  402                 case BPF_LDX:
  403                         switch (BPF_MODE(p->code)) {
  404                         case BPF_IMM:
  405                                 break;
  406                         case BPF_ABS:
  407                         case BPF_IND:
  408                         case BPF_MSH:
  409                                 /*
  410                                  * More strict check with actual packet length
  411                                  * is done runtime.
  412                                  */
  413                                 if (p->k >= bpf_maxbufsize)
  414                                         return 0;
  415                                 break;
  416                         case BPF_MEM:
  417                                 if (p->k >= BPF_MEMWORDS)
  418                                         return 0;
  419                                 break;
  420                         case BPF_LEN:
  421                         case BPF_RND:
  422                                 break;
  423                         default:
  424                                 return 0;
  425                         }
  426                         break;
  427                 case BPF_ST:
  428                 case BPF_STX:
  429                         if (p->k >= BPF_MEMWORDS)
  430                                 return 0;
  431                         break;
  432                 case BPF_ALU:
  433                         switch (BPF_OP(p->code)) {
  434                         case BPF_ADD:
  435                         case BPF_SUB:
  436                         case BPF_MUL:
  437                         case BPF_OR:
  438                         case BPF_AND:
  439                         case BPF_LSH:
  440                         case BPF_RSH:
  441                         case BPF_NEG:
  442                                 break;
  443                         case BPF_DIV:
  444                                 /*
  445                                  * Check for constant division by 0.
  446                                  */
  447                                 if (BPF_SRC(p->code) == BPF_K && p->k == 0)
  448                                         return 0;
  449                                 break;
  450                         default:
  451                                 return 0;
  452                         }
  453                         break;
  454                 case BPF_JMP:
  455                         /*
  456                          * Check that jumps are forward, and within
  457                          * the code block.
  458                          */
  459                         from = i + 1;
  460                         switch (BPF_OP(p->code)) {
  461                         case BPF_JA:
  462                                 if (from + p->k < from || from + p->k >= len)
  463                                         return 0;
  464                                 break;
  465                         case BPF_JEQ:
  466                         case BPF_JGT:
  467                         case BPF_JGE:
  468                         case BPF_JSET:
  469                                 if (from + p->jt >= len || from + p->jf >= len)
  470                                         return 0;
  471                                 break;
  472                         default:
  473                                 return 0;
  474                         }
  475                         break;
  476                 case BPF_RET:
  477                         break;
  478                 case BPF_MISC:
  479                         break;
  480                 default:
  481                         return 0;
  482                 }
  483 
  484         }
  485         return BPF_CLASS(f[len - 1].code) == BPF_RET;
  486 }
  487 #endif

Cache object: 89db115bd39248ff500095ac643f8aed


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.