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 /*      $NetBSD: bpf_filter.c,v 1.32.2.2 2010/06/13 17:51:11 riz Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from the Stanford/CMU enet packet filter,
    8  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
    9  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
   10  * Berkeley Laboratory.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)bpf_filter.c        8.1 (Berkeley) 6/10/93
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.32.2.2 2010/06/13 17:51:11 riz Exp $");
   41 
   42 #if 0
   43 #if !(defined(lint) || defined(KERNEL))
   44 static const char rcsid[] =
   45     "@(#) Header: bpf_filter.c,v 1.33 97/04/26 13:37:18 leres Exp  (LBL)";
   46 #endif
   47 #endif
   48 
   49 #include <sys/param.h>
   50 #include <sys/time.h>
   51 
   52 #if !defined(UNALIGNED_ACCESS)
   53 #define BPF_ALIGN
   54 #endif
   55 
   56 #ifndef BPF_ALIGN
   57 #define EXTRACT_SHORT(p)        ((uint16_t)ntohs(*(uint16_t *)p))
   58 #define EXTRACT_LONG(p)         (ntohl(*(uint32_t *)p))
   59 #else
   60 #define EXTRACT_SHORT(p)                        \
   61         ((uint16_t)                             \
   62                 ((uint16_t)*((u_char *)p+0)<<8| \
   63                  (uint16_t)*((u_char *)p+1)<<0))
   64 #define EXTRACT_LONG(p)                         \
   65                 ((uint32_t)*((u_char *)p+0)<<24|\
   66                  (uint32_t)*((u_char *)p+1)<<16|\
   67                  (uint32_t)*((u_char *)p+2)<<8| \
   68                  (uint32_t)*((u_char *)p+3)<<0)
   69 #endif
   70 
   71 #ifdef _KERNEL
   72 #include <sys/mbuf.h>
   73 #define MINDEX(len, m, k)               \
   74 {                                       \
   75         len = m->m_len;                 \
   76         while (k >= len) {              \
   77                 k -= len;               \
   78                 m = m->m_next;          \
   79                 if (m == 0)             \
   80                         return 0;       \
   81                 len = m->m_len;         \
   82         }                               \
   83 }
   84 
   85 static int m_xword (struct mbuf *, uint32_t, int *);
   86 static int m_xhalf (struct mbuf *, uint32_t, int *);
   87 
   88 static int
   89 m_xword(struct mbuf *m, uint32_t k, int *err)
   90 {
   91         int len;
   92         u_char *cp, *np;
   93         struct mbuf *m0;
   94 
   95         *err = 1;
   96         MINDEX(len, m, k);
   97         cp = mtod(m, u_char *) + k;
   98         if (len >= k + 4) {
   99                 *err = 0;
  100                 return EXTRACT_LONG(cp);
  101         }
  102         m0 = m->m_next;
  103         if (m0 == 0 || m0->m_len + len - k < 4)
  104                 return 0;
  105         *err = 0;
  106         np = mtod(m0, u_char *);
  107         switch (len - k) {
  108 
  109         case 1:
  110                 return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
  111 
  112         case 2:
  113                 return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
  114 
  115         default:
  116                 return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
  117         }
  118 }
  119 
  120 static int
  121 m_xhalf(struct mbuf *m, uint32_t k, int *err)
  122 {
  123         int len;
  124         u_char *cp;
  125         struct mbuf *m0;
  126 
  127         *err = 1;
  128         MINDEX(len, m, k);
  129         cp = mtod(m, u_char *) + k;
  130         if (len >= k + 2) {
  131                 *err = 0;
  132                 return EXTRACT_SHORT(cp);
  133         }
  134         m0 = m->m_next;
  135         if (m0 == 0)
  136                 return 0;
  137         *err = 0;
  138         return (cp[0] << 8) | mtod(m0, u_char *)[0];
  139 }
  140 #else /* _KERNEL */
  141 #include <stdlib.h>
  142 #endif /* !_KERNEL */
  143 
  144 #include <net/bpf.h>
  145 
  146 /*
  147  * Execute the filter program starting at pc on the packet p
  148  * wirelen is the length of the original packet
  149  * buflen is the amount of data present
  150  */
  151 u_int
  152 bpf_filter(struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
  153 {
  154         uint32_t A, X, k;
  155         int32_t mem[BPF_MEMWORDS];
  156 
  157         if (pc == 0)
  158                 /*
  159                  * No filter means accept all.
  160                  */
  161                 return (u_int)-1;
  162         A = 0;
  163         X = 0;
  164         --pc;
  165         /* CONSTCOND */
  166         while (1) {
  167                 ++pc;
  168                 switch (pc->code) {
  169 
  170                 default:
  171 #ifdef _KERNEL
  172                         return 0;
  173 #else
  174                         abort();
  175 #endif
  176                 case BPF_RET|BPF_K:
  177                         return (u_int)pc->k;
  178 
  179                 case BPF_RET|BPF_A:
  180                         return (u_int)A;
  181 
  182                 case BPF_LD|BPF_W|BPF_ABS:
  183                         k = pc->k;
  184                         if (k + sizeof(int32_t) > buflen) {
  185 #ifdef _KERNEL
  186                                 int merr = 0;   /* XXX: GCC */
  187 
  188                                 if (buflen != 0)
  189                                         return 0;
  190                                 A = m_xword((struct mbuf *)p, k, &merr);
  191                                 if (merr != 0)
  192                                         return 0;
  193                                 continue;
  194 #else
  195                                 return 0;
  196 #endif
  197                         }
  198                         A = EXTRACT_LONG(&p[k]);
  199                         continue;
  200 
  201                 case BPF_LD|BPF_H|BPF_ABS:
  202                         k = pc->k;
  203                         if (k + sizeof(int16_t) > buflen) {
  204 #ifdef _KERNEL
  205                                 int merr;
  206 
  207                                 if (buflen != 0)
  208                                         return 0;
  209                                 A = m_xhalf((struct mbuf *)p, k, &merr);
  210                                 if (merr != 0)
  211                                         return 0;
  212                                 continue;
  213 #else
  214                                 return 0;
  215 #endif
  216                         }
  217                         A = EXTRACT_SHORT(&p[k]);
  218                         continue;
  219 
  220                 case BPF_LD|BPF_B|BPF_ABS:
  221                         k = pc->k;
  222                         if (k >= buflen) {
  223 #ifdef _KERNEL
  224                                 struct mbuf *m;
  225                                 int len;
  226 
  227                                 if (buflen != 0)
  228                                         return 0;
  229                                 m = (struct mbuf *)p;
  230                                 MINDEX(len, m, k);
  231                                 A = mtod(m, u_char *)[k];
  232                                 continue;
  233 #else
  234                                 return 0;
  235 #endif
  236                         }
  237                         A = p[k];
  238                         continue;
  239 
  240                 case BPF_LD|BPF_W|BPF_LEN:
  241                         A = wirelen;
  242                         continue;
  243 
  244                 case BPF_LDX|BPF_W|BPF_LEN:
  245                         X = wirelen;
  246                         continue;
  247 
  248                 case BPF_LD|BPF_W|BPF_IND:
  249                         k = X + pc->k;
  250                         if (k + sizeof(int32_t) > buflen) {
  251 #ifdef _KERNEL
  252                                 int merr = 0;   /* XXX: GCC */
  253 
  254                                 if (buflen != 0)
  255                                         return 0;
  256                                 A = m_xword((struct mbuf *)p, k, &merr);
  257                                 if (merr != 0)
  258                                         return 0;
  259                                 continue;
  260 #else
  261                                 return 0;
  262 #endif
  263                         }
  264                         A = EXTRACT_LONG(&p[k]);
  265                         continue;
  266 
  267                 case BPF_LD|BPF_H|BPF_IND:
  268                         k = X + pc->k;
  269                         if (k + sizeof(int16_t) > buflen) {
  270 #ifdef _KERNEL
  271                                 int merr = 0;   /* XXX: GCC */
  272 
  273                                 if (buflen != 0)
  274                                         return 0;
  275                                 A = m_xhalf((struct mbuf *)p, k, &merr);
  276                                 if (merr != 0)
  277                                         return 0;
  278                                 continue;
  279 #else
  280                                 return 0;
  281 #endif
  282                         }
  283                         A = EXTRACT_SHORT(&p[k]);
  284                         continue;
  285 
  286                 case BPF_LD|BPF_B|BPF_IND:
  287                         k = X + pc->k;
  288                         if (k >= buflen) {
  289 #ifdef _KERNEL
  290                                 struct mbuf *m;
  291                                 int len;
  292 
  293                                 if (buflen != 0)
  294                                         return 0;
  295                                 m = (struct mbuf *)p;
  296                                 MINDEX(len, m, k);
  297                                 A = mtod(m, u_char *)[k];
  298                                 continue;
  299 #else
  300                                 return 0;
  301 #endif
  302                         }
  303                         A = p[k];
  304                         continue;
  305 
  306                 case BPF_LDX|BPF_MSH|BPF_B:
  307                         k = pc->k;
  308                         if (k >= buflen) {
  309 #ifdef _KERNEL
  310                                 struct mbuf *m;
  311                                 int len;
  312 
  313                                 if (buflen != 0)
  314                                         return 0;
  315                                 m = (struct mbuf *)p;
  316                                 MINDEX(len, m, k);
  317                                 X = (mtod(m, char *)[k] & 0xf) << 2;
  318                                 continue;
  319 #else
  320                                 return 0;
  321 #endif
  322                         }
  323                         X = (p[pc->k] & 0xf) << 2;
  324                         continue;
  325 
  326                 case BPF_LD|BPF_IMM:
  327                         A = pc->k;
  328                         continue;
  329 
  330                 case BPF_LDX|BPF_IMM:
  331                         X = pc->k;
  332                         continue;
  333 
  334                 case BPF_LD|BPF_MEM:
  335                         A = mem[pc->k];
  336                         continue;
  337 
  338                 case BPF_LDX|BPF_MEM:
  339                         X = mem[pc->k];
  340                         continue;
  341 
  342                 case BPF_ST:
  343                         mem[pc->k] = A;
  344                         continue;
  345 
  346                 case BPF_STX:
  347                         mem[pc->k] = X;
  348                         continue;
  349 
  350                 case BPF_JMP|BPF_JA:
  351                         pc += pc->k;
  352                         continue;
  353 
  354                 case BPF_JMP|BPF_JGT|BPF_K:
  355                         pc += (A > pc->k) ? pc->jt : pc->jf;
  356                         continue;
  357 
  358                 case BPF_JMP|BPF_JGE|BPF_K:
  359                         pc += (A >= pc->k) ? pc->jt : pc->jf;
  360                         continue;
  361 
  362                 case BPF_JMP|BPF_JEQ|BPF_K:
  363                         pc += (A == pc->k) ? pc->jt : pc->jf;
  364                         continue;
  365 
  366                 case BPF_JMP|BPF_JSET|BPF_K:
  367                         pc += (A & pc->k) ? pc->jt : pc->jf;
  368                         continue;
  369 
  370                 case BPF_JMP|BPF_JGT|BPF_X:
  371                         pc += (A > X) ? pc->jt : pc->jf;
  372                         continue;
  373 
  374                 case BPF_JMP|BPF_JGE|BPF_X:
  375                         pc += (A >= X) ? pc->jt : pc->jf;
  376                         continue;
  377 
  378                 case BPF_JMP|BPF_JEQ|BPF_X:
  379                         pc += (A == X) ? pc->jt : pc->jf;
  380                         continue;
  381 
  382                 case BPF_JMP|BPF_JSET|BPF_X:
  383                         pc += (A & X) ? pc->jt : pc->jf;
  384                         continue;
  385 
  386                 case BPF_ALU|BPF_ADD|BPF_X:
  387                         A += X;
  388                         continue;
  389 
  390                 case BPF_ALU|BPF_SUB|BPF_X:
  391                         A -= X;
  392                         continue;
  393 
  394                 case BPF_ALU|BPF_MUL|BPF_X:
  395                         A *= X;
  396                         continue;
  397 
  398                 case BPF_ALU|BPF_DIV|BPF_X:
  399                         if (X == 0)
  400                                 return 0;
  401                         A /= X;
  402                         continue;
  403 
  404                 case BPF_ALU|BPF_AND|BPF_X:
  405                         A &= X;
  406                         continue;
  407 
  408                 case BPF_ALU|BPF_OR|BPF_X:
  409                         A |= X;
  410                         continue;
  411 
  412                 case BPF_ALU|BPF_LSH|BPF_X:
  413                         A <<= X;
  414                         continue;
  415 
  416                 case BPF_ALU|BPF_RSH|BPF_X:
  417                         A >>= X;
  418                         continue;
  419 
  420                 case BPF_ALU|BPF_ADD|BPF_K:
  421                         A += pc->k;
  422                         continue;
  423 
  424                 case BPF_ALU|BPF_SUB|BPF_K:
  425                         A -= pc->k;
  426                         continue;
  427 
  428                 case BPF_ALU|BPF_MUL|BPF_K:
  429                         A *= pc->k;
  430                         continue;
  431 
  432                 case BPF_ALU|BPF_DIV|BPF_K:
  433                         A /= pc->k;
  434                         continue;
  435 
  436                 case BPF_ALU|BPF_AND|BPF_K:
  437                         A &= pc->k;
  438                         continue;
  439 
  440                 case BPF_ALU|BPF_OR|BPF_K:
  441                         A |= pc->k;
  442                         continue;
  443 
  444                 case BPF_ALU|BPF_LSH|BPF_K:
  445                         A <<= pc->k;
  446                         continue;
  447 
  448                 case BPF_ALU|BPF_RSH|BPF_K:
  449                         A >>= pc->k;
  450                         continue;
  451 
  452                 case BPF_ALU|BPF_NEG:
  453                         A = -A;
  454                         continue;
  455 
  456                 case BPF_MISC|BPF_TAX:
  457                         X = A;
  458                         continue;
  459 
  460                 case BPF_MISC|BPF_TXA:
  461                         A = X;
  462                         continue;
  463                 }
  464         }
  465 }
  466 
  467 #ifdef _KERNEL
  468 /*
  469  * Return true if the 'fcode' is a valid filter program.
  470  * The constraints are that each jump be forward and to a valid
  471  * code, that memory accesses are within valid ranges (to the
  472  * extent that this can be checked statically; loads of packet
  473  * data have to be, and are, also checked at run time), and that
  474  * the code terminates with either an accept or reject.
  475  *
  476  * The kernel needs to be able to verify an application's filter code.
  477  * Otherwise, a bogus program could easily crash the system.
  478  */
  479 int
  480 bpf_validate(struct bpf_insn *f, int len)
  481 {
  482         u_int i, from;
  483         struct bpf_insn *p;
  484 
  485         if (len < 1 || len > BPF_MAXINSNS)
  486                 return 0;
  487 
  488         for (i = 0; i < len; ++i) {
  489                 p = &f[i];
  490                 switch (BPF_CLASS(p->code)) {
  491                 /*
  492                  * Check that memory operations use valid addresses.
  493                  */
  494                 case BPF_LD:
  495                 case BPF_LDX:
  496                         switch (BPF_MODE(p->code)) {
  497                         case BPF_MEM:
  498                                 if (p->k >= BPF_MEMWORDS)
  499                                         return 0;
  500                                 break;
  501                         case BPF_ABS:
  502                         case BPF_IND:
  503                         case BPF_MSH:
  504                         case BPF_IMM:
  505                         case BPF_LEN:
  506                                 break;
  507                         default:
  508                                 return 0;
  509                         }
  510                         break;
  511                 case BPF_ST:
  512                 case BPF_STX:
  513                         if (p->k >= BPF_MEMWORDS)
  514                                 return 0;
  515                         break;
  516                 case BPF_ALU:
  517                         switch (BPF_OP(p->code)) {
  518                         case BPF_ADD:
  519                         case BPF_SUB:
  520                         case BPF_MUL:
  521                         case BPF_OR:
  522                         case BPF_AND:
  523                         case BPF_LSH:
  524                         case BPF_RSH:
  525                         case BPF_NEG:
  526                                 break;
  527                         case BPF_DIV:
  528                                 /*
  529                                  * Check for constant division by 0.
  530                                  */
  531                                 if (BPF_SRC(p->code) == BPF_K && p->k == 0)
  532                                         return 0;
  533                                 break;
  534                         default:
  535                                 return 0;
  536                         }
  537                         break;
  538                 case BPF_JMP:
  539                         /*
  540                          * Check that jumps are within the code block,
  541                          * and that unconditional branches don't go
  542                          * backwards as a result of an overflow.
  543                          * Unconditional branches have a 32-bit offset,
  544                          * so they could overflow; we check to make
  545                          * sure they don't.  Conditional branches have
  546                          * an 8-bit offset, and the from address is <=
  547                          * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
  548                          * is sufficiently small that adding 255 to it
  549                          * won't overflow.
  550                          *
  551                          * We know that len is <= BPF_MAXINSNS, and we
  552                          * assume that BPF_MAXINSNS is < the maximum size
  553                          * of a u_int, so that i + 1 doesn't overflow.
  554                          */
  555                         from = i + 1;
  556                         switch (BPF_OP(p->code)) {
  557                         case BPF_JA:
  558                                 if (from + p->k < from || from + p->k >= len)
  559                                         return 0;
  560                                 break;
  561                         case BPF_JEQ:
  562                         case BPF_JGT:
  563                         case BPF_JGE:
  564                         case BPF_JSET:
  565                                 if (from + p->jt >= len || from + p->jf >= len) 
  566                                         return 0;
  567                                 break;
  568                         default:
  569                                 return 0;
  570                         }
  571                         break;
  572                 case BPF_RET:
  573                         break;
  574                 case BPF_MISC:
  575                         break;
  576                 default:
  577                         return 0;
  578                 }
  579         }
  580 
  581         return BPF_CLASS(f[len - 1].code) == BPF_RET;
  582 }
  583 #endif

Cache object: 8d337de1d5cb09f63941053f788fbf12


[ 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.