]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/bpf_filter.c
   2  * Copyright (c) 2000-2017 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Copyright (c) 1990, 1991, 1993 
  30  *      The Regents of the University of California.  All rights reserved. 
  32  * This code is derived from the Stanford/CMU enet packet filter, 
  33  * (net/enet.c) distributed as part of 4.3BSD, and code contributed 
  34  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
  35  * Berkeley Laboratory. 
  37  * Redistribution and use in source and binary forms, with or without 
  38  * modification, are permitted provided that the following conditions 
  40  * 1. Redistributions of source code must retain the above copyright 
  41  *    notice, this list of conditions and the following disclaimer. 
  42  * 2. Redistributions in binary form must reproduce the above copyright 
  43  *    notice, this list of conditions and the following disclaimer in the 
  44  *    documentation and/or other materials provided with the distribution. 
  45  * 3. All advertising materials mentioning features or use of this software 
  46  *    must display the following acknowledgement: 
  47  *      This product includes software developed by the University of 
  48  *      California, Berkeley and its contributors. 
  49  * 4. Neither the name of the University nor the names of its contributors 
  50  *    may be used to endorse or promote products derived from this software 
  51  *    without specific prior written permission. 
  53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  65  *      @(#)bpf_filter.c        8.1 (Berkeley) 6/10/93 
  67  * $FreeBSD: src/sys/net/bpf_filter.c,v 1.17 1999/12/29 04:38:31 peter Exp $ 
  70 #include <sys/param.h> 
  74 #include <netinet/in.h> 
  83 extern unsigned int bpf_maxbufsize
; 
  85 static inline u_int32_t
 
  86 get_word_from_buffers(u_char 
* cp
, u_char 
* np
, size_t num_from_cp
) 
  90         switch (num_from_cp
) { 
  92                 val 
= ((u_int32_t
)cp
[0] << 24) | 
  93                     ((u_int32_t
)np
[0] << 16) | 
  94                     ((u_int32_t
)np
[1] << 8)  | 
  99                 val 
= ((u_int32_t
)cp
[0] << 24) | 
 100                     ((u_int32_t
)cp
[1] << 16) | 
 101                     ((u_int32_t
)np
[0] << 8) | 
 105                 val 
= ((u_int32_t
)cp
[0] << 24) | 
 106                     ((u_int32_t
)cp
[1] << 16) | 
 107                     ((u_int32_t
)cp
[2] << 8) | 
 115 m_hdr_offset(struct mbuf 
**m_p
, void * hdr
, size_t hdrlen
, bpf_u_int32 
* k_p
, 
 119         bpf_u_int32 k 
= *k_p
; 
 123                 struct mbuf 
*m 
= *m_p
; 
 125                 /* there's no header or the offset we want is past the header */ 
 136                 cp 
= mtod(m
, u_char 
*) + k
; 
 138                 /* return next mbuf, in case it's needed */ 
 141                 /* update the offset */ 
 145                 cp 
= (u_char 
*)hdr 
+ k
; 
 152 m_xword(struct mbuf 
*m
, void * hdr
, size_t hdrlen
, bpf_u_int32 k
, int *err
) 
 157         cp 
= m_hdr_offset(&m
, hdr
, hdrlen
, &k
, &len
); 
 163                 return EXTRACT_LONG(cp
); 
 165         if (m 
== 0 || m
->m_len 
+ len 
- k 
< 4) { 
 169         np 
= mtod(m
, u_char 
*); 
 170         return get_word_from_buffers(cp
, np
, len 
- k
); 
 178 m_xhalf(struct mbuf 
*m
, void * hdr
, size_t hdrlen
, bpf_u_int32 k
, int *err
) 
 183         cp 
= m_hdr_offset(&m
, hdr
, hdrlen
, &k
, &len
); 
 189                 return EXTRACT_SHORT(cp
); 
 195         return (uint16_t)((cp
[0] << 8) | mtod(m
, u_char 
*)[0]); 
 202 m_xbyte(struct mbuf 
*m
, void * hdr
, size_t hdrlen
, bpf_u_int32 k
, int *err
) 
 207         cp 
= m_hdr_offset(&m
, hdr
, hdrlen
, &k
, &len
); 
 220 bp_xword(struct bpf_packet 
*bp
, bpf_u_int32 k
, int *err
) 
 222         void *  hdr 
= bp
->bpfp_header
; 
 223         size_t  hdrlen 
= bp
->bpfp_header_length
; 
 225         switch (bp
->bpfp_type
) { 
 226         case BPF_PACKET_TYPE_MBUF
: 
 227                 return m_xword(bp
->bpfp_mbuf
, hdr
, hdrlen
, k
, err
); 
 236 bp_xhalf(struct bpf_packet 
*bp
, bpf_u_int32 k
, int *err
) 
 238         void *  hdr 
= bp
->bpfp_header
; 
 239         size_t  hdrlen 
= bp
->bpfp_header_length
; 
 241         switch (bp
->bpfp_type
) { 
 242         case BPF_PACKET_TYPE_MBUF
: 
 243                 return m_xhalf(bp
->bpfp_mbuf
, hdr
, hdrlen
, k
, err
); 
 252 bp_xbyte(struct bpf_packet 
*bp
, bpf_u_int32 k
, int *err
) 
 254         void *  hdr 
= bp
->bpfp_header
; 
 255         size_t  hdrlen 
= bp
->bpfp_header_length
; 
 257         switch (bp
->bpfp_type
) { 
 258         case BPF_PACKET_TYPE_MBUF
: 
 259                 return m_xbyte(bp
->bpfp_mbuf
, hdr
, hdrlen
, k
, err
); 
 270  * Execute the filter program starting at pc on the packet p 
 271  * wirelen is the length of the original packet 
 272  * buflen is the amount of data present 
 275 bpf_filter(const struct bpf_insn 
*pc
, u_char 
*p
, u_int wirelen
, u_int buflen
) 
 277         u_int32_t A 
= 0, X 
= 0; 
 279         int32_t mem
[BPF_MEMWORDS
]; 
 282         struct bpf_packet 
* bp 
= (struct bpf_packet 
*)(void *)p
; 
 285         bzero(mem
, sizeof(mem
)); 
 289                  * No filter means accept all. 
 304                 case BPF_RET 
| BPF_K
: 
 307                 case BPF_RET 
| BPF_A
: 
 310                 case BPF_LD 
| BPF_W 
| BPF_ABS
: 
 312                         if (k 
> buflen 
|| sizeof(int32_t) > buflen 
- k
) { 
 317                                 A 
= bp_xword(bp
, k
, &merr
); 
 327                         if (((intptr_t)(p 
+ k
) & 3) != 0) { 
 328                                 A 
= EXTRACT_LONG(&p
[k
]); 
 330 #endif /* BPF_ALIGN */ 
 331                         A 
= ntohl(*(int32_t *)(void *)(p 
+ k
)); 
 334                 case BPF_LD 
| BPF_H 
| BPF_ABS
: 
 336                         if (k 
> buflen 
|| sizeof(int16_t) > buflen 
- k
) { 
 341                                 A 
= bp_xhalf(bp
, k
, &merr
); 
 350                         A 
= EXTRACT_SHORT(&p
[k
]); 
 353                 case BPF_LD 
| BPF_B 
| BPF_ABS
: 
 360                                 A 
= bp_xbyte(bp
, k
, &merr
); 
 372                 case BPF_LD 
| BPF_W 
| BPF_LEN
: 
 376                 case BPF_LDX 
| BPF_W 
| BPF_LEN
: 
 380                 case BPF_LD 
| BPF_W 
| BPF_IND
: 
 382                         if (pc
->k 
> buflen 
|| X 
> buflen 
- pc
->k 
|| 
 383                             sizeof(int32_t) > buflen 
- k
) { 
 388                                 A 
= bp_xword(bp
, k
, &merr
); 
 398                         if (((intptr_t)(p 
+ k
) & 3) != 0) { 
 399                                 A 
= EXTRACT_LONG(&p
[k
]); 
 401 #endif /* BPF_ALIGN */ 
 402                         A 
= ntohl(*(int32_t *)(void *)(p 
+ k
)); 
 405                 case BPF_LD 
| BPF_H 
| BPF_IND
: 
 407                         if (X 
> buflen 
|| pc
->k 
> buflen 
- X 
|| 
 408                             sizeof(int16_t) > buflen 
- k
) { 
 413                                 A 
= bp_xhalf(bp
, k
, &merr
); 
 422                         A 
= EXTRACT_SHORT(&p
[k
]); 
 425                 case BPF_LD 
| BPF_B 
| BPF_IND
: 
 427                         if (pc
->k 
>= buflen 
|| X 
>= buflen 
- pc
->k
) { 
 432                                 A 
= bp_xbyte(bp
, k
, &merr
); 
 444                 case BPF_LDX 
| BPF_MSH 
| BPF_B
: 
 451                                 X 
= bp_xbyte(bp
, k
, &merr
); 
 461                         X 
= (p
[pc
->k
] & 0xf) << 2; 
 464                 case BPF_LD 
| BPF_IMM
: 
 468                 case BPF_LDX 
| BPF_IMM
: 
 472                 case BPF_LD 
| BPF_MEM
: 
 473                         if (pc
->k 
>= BPF_MEMWORDS
) { 
 479                 case BPF_LDX 
| BPF_MEM
: 
 480                         if (pc
->k 
>= BPF_MEMWORDS
) { 
 487                         if (pc
->k 
>= BPF_MEMWORDS
) { 
 494                         if (pc
->k 
>= BPF_MEMWORDS
) { 
 500                 case BPF_JMP 
| BPF_JA
: 
 504                 case BPF_JMP 
| BPF_JGT 
| BPF_K
: 
 505                         pc 
+= (A 
> pc
->k
) ? pc
->jt 
: pc
->jf
; 
 508                 case BPF_JMP 
| BPF_JGE 
| BPF_K
: 
 509                         pc 
+= (A 
>= pc
->k
) ? pc
->jt 
: pc
->jf
; 
 512                 case BPF_JMP 
| BPF_JEQ 
| BPF_K
: 
 513                         pc 
+= (A 
== pc
->k
) ? pc
->jt 
: pc
->jf
; 
 516                 case BPF_JMP 
| BPF_JSET 
| BPF_K
: 
 517                         pc 
+= (A 
& pc
->k
) ? pc
->jt 
: pc
->jf
; 
 520                 case BPF_JMP 
| BPF_JGT 
| BPF_X
: 
 521                         pc 
+= (A 
> X
) ? pc
->jt 
: pc
->jf
; 
 524                 case BPF_JMP 
| BPF_JGE 
| BPF_X
: 
 525                         pc 
+= (A 
>= X
) ? pc
->jt 
: pc
->jf
; 
 528                 case BPF_JMP 
| BPF_JEQ 
| BPF_X
: 
 529                         pc 
+= (A 
== X
) ? pc
->jt 
: pc
->jf
; 
 532                 case BPF_JMP 
| BPF_JSET 
| BPF_X
: 
 533                         pc 
+= (A 
& X
) ? pc
->jt 
: pc
->jf
; 
 536                 case BPF_ALU 
| BPF_ADD 
| BPF_X
: 
 540                 case BPF_ALU 
| BPF_SUB 
| BPF_X
: 
 544                 case BPF_ALU 
| BPF_MUL 
| BPF_X
: 
 548                 case BPF_ALU 
| BPF_DIV 
| BPF_X
: 
 555                 case BPF_ALU 
| BPF_AND 
| BPF_X
: 
 559                 case BPF_ALU 
| BPF_OR 
| BPF_X
: 
 563                 case BPF_ALU 
| BPF_LSH 
| BPF_X
: 
 567                 case BPF_ALU 
| BPF_RSH 
| BPF_X
: 
 571                 case BPF_ALU 
| BPF_ADD 
| BPF_K
: 
 575                 case BPF_ALU 
| BPF_SUB 
| BPF_K
: 
 579                 case BPF_ALU 
| BPF_MUL 
| BPF_K
: 
 583                 case BPF_ALU 
| BPF_DIV 
| BPF_K
: 
 587                 case BPF_ALU 
| BPF_AND 
| BPF_K
: 
 591                 case BPF_ALU 
| BPF_OR 
| BPF_K
: 
 595                 case BPF_ALU 
| BPF_LSH 
| BPF_K
: 
 599                 case BPF_ALU 
| BPF_RSH 
| BPF_K
: 
 603                 case BPF_ALU 
| BPF_NEG
: 
 607                 case BPF_MISC 
| BPF_TAX
: 
 611                 case BPF_MISC 
| BPF_TXA
: 
 620  * Return true if the 'fcode' is a valid filter program. 
 621  * The constraints are that each jump be forward and to a valid 
 622  * code, that memory accesses are within valid ranges (to the 
 623  * extent that this can be checked statically; loads of packet data 
 624  * have to be, and are, also checked at run time), and that 
 625  * the code terminates with either an accept or reject. 
 627  * The kernel needs to be able to verify an application's filter code. 
 628  * Otherwise, a bogus program could easily crash the system. 
 631 bpf_validate(const struct bpf_insn 
*f
, int len
) 
 634         const struct bpf_insn 
*p
; 
 636         if (len 
< 1 || len 
> BPF_MAXINSNS
) { 
 640         for (i 
= 0; i 
< ((u_int
)len
); ++i
) { 
 642                 switch (BPF_CLASS(p
->code
)) { 
 644                  * Check that memory operations use valid addresses 
 648                         switch (BPF_MODE(p
->code
)) { 
 655                                  * More strict check with actual packet length 
 658                                 if (p
->k 
>= bpf_maxbufsize
) { 
 663                                 if (p
->k 
>= BPF_MEMWORDS
) { 
 675                         if (p
->k 
>= BPF_MEMWORDS
) { 
 680                         switch (BPF_OP(p
->code
)) { 
 692                                  * Check for constant division by 0 
 694                                 if (BPF_SRC(p
->code
) == BPF_K 
&& p
->k 
== 0) { 
 704                          * Check that jumps are within the code block, 
 705                          * and that unconditional branches don't go 
 706                          * backwards as a result of an overflow. 
 707                          * Unconditional branches have a 32-bit offset, 
 708                          * so they could overflow; we check to make 
 709                          * sure they don't. Conditional branches have 
 710                          * an 8-bit offset, and the from address is 
 711                          * less than equal to BPF_MAXINSNS, and we assume that 
 712                          * BPF_MAXINSNS is sufficiently small that adding 255 
 713                          * to it won't overlflow 
 715                          * We know that len is <= BPF_MAXINSNS, and we 
 716                          * assume that BPF_MAXINSNS is less than the maximum 
 717                          * size of a u_int, so that i+1 doesn't overflow 
 720                         switch (BPF_OP(p
->code
)) { 
 722                                 if (from 
+ p
->k 
< from 
|| from 
+ p
->k 
>= ((u_int
)len
)) { 
 730                                 if (from 
+ p
->jt 
>= ((u_int
)len
) || from 
+ p
->jf 
>= ((u_int
)len
)) { 
 746         return BPF_CLASS(f
[len 
- 1].code
) == BPF_RET
;