xref: /dflybsd-src/contrib/libpcap/bpf_filter.c (revision e75ef36f1332e115895388cede9dfd24ca1a806c)
13a289941SAaron LI /*-
23a289941SAaron LI  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
33a289941SAaron LI  *	The Regents of the University of California.  All rights reserved.
43a289941SAaron LI  *
53a289941SAaron LI  * This code is derived from the Stanford/CMU enet packet filter,
63a289941SAaron LI  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
73a289941SAaron LI  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
83a289941SAaron LI  * Berkeley Laboratory.
93a289941SAaron LI  *
103a289941SAaron LI  * Redistribution and use in source and binary forms, with or without
113a289941SAaron LI  * modification, are permitted provided that the following conditions
123a289941SAaron LI  * are met:
133a289941SAaron LI  * 1. Redistributions of source code must retain the above copyright
143a289941SAaron LI  *    notice, this list of conditions and the following disclaimer.
153a289941SAaron LI  * 2. Redistributions in binary form must reproduce the above copyright
163a289941SAaron LI  *    notice, this list of conditions and the following disclaimer in the
173a289941SAaron LI  *    documentation and/or other materials provided with the distribution.
183a289941SAaron LI  * 3. All advertising materials mentioning features or use of this software
193a289941SAaron LI  *    must display the following acknowledgement:
203a289941SAaron LI  *	This product includes software developed by the University of
213a289941SAaron LI  *	California, Berkeley and its contributors.
223a289941SAaron LI  * 4. Neither the name of the University nor the names of its contributors
233a289941SAaron LI  *    may be used to endorse or promote products derived from this software
243a289941SAaron LI  *    without specific prior written permission.
253a289941SAaron LI  *
263a289941SAaron LI  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
273a289941SAaron LI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
283a289941SAaron LI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
293a289941SAaron LI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
303a289941SAaron LI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
313a289941SAaron LI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
323a289941SAaron LI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
333a289941SAaron LI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
343a289941SAaron LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
353a289941SAaron LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
363a289941SAaron LI  * SUCH DAMAGE.
373a289941SAaron LI  *
383a289941SAaron LI  *	@(#)bpf.c	7.5 (Berkeley) 7/15/91
393a289941SAaron LI  */
403a289941SAaron LI 
413a289941SAaron LI #ifdef HAVE_CONFIG_H
423a289941SAaron LI #include <config.h>
433a289941SAaron LI #endif
443a289941SAaron LI 
453a289941SAaron LI #include <pcap/pcap-inttypes.h>
463a289941SAaron LI #include "pcap-types.h"
47*ea16f64eSAntonio Huete Jimenez #include "extract.h"
48*ea16f64eSAntonio Huete Jimenez #include "diag-control.h"
49*ea16f64eSAntonio Huete Jimenez 
50*ea16f64eSAntonio Huete Jimenez #define EXTRACT_SHORT	EXTRACT_BE_U_2
51*ea16f64eSAntonio Huete Jimenez #define EXTRACT_LONG	EXTRACT_BE_U_4
523a289941SAaron LI 
533a289941SAaron LI #ifndef _WIN32
543a289941SAaron LI #include <sys/param.h>
553a289941SAaron LI #include <sys/types.h>
563a289941SAaron LI #include <sys/time.h>
573a289941SAaron LI #endif /* _WIN32 */
583a289941SAaron LI 
593a289941SAaron LI #include <pcap-int.h>
603a289941SAaron LI 
613a289941SAaron LI #include <stdlib.h>
623a289941SAaron LI 
633a289941SAaron LI #ifdef __linux__
643a289941SAaron LI #include <linux/types.h>
653a289941SAaron LI #include <linux/if_packet.h>
663a289941SAaron LI #include <linux/filter.h>
673a289941SAaron LI #endif
683a289941SAaron LI 
693a289941SAaron LI enum {
703a289941SAaron LI         BPF_S_ANC_NONE,
713a289941SAaron LI         BPF_S_ANC_VLAN_TAG,
723a289941SAaron LI         BPF_S_ANC_VLAN_TAG_PRESENT,
733a289941SAaron LI };
743a289941SAaron LI 
753a289941SAaron LI /*
763a289941SAaron LI  * Execute the filter program starting at pc on the packet p
773a289941SAaron LI  * wirelen is the length of the original packet
783a289941SAaron LI  * buflen is the amount of data present
793a289941SAaron LI  * aux_data is auxiliary data, currently used only when interpreting
803a289941SAaron LI  * filters intended for the Linux kernel in cases where the kernel
813a289941SAaron LI  * rejects the filter; it contains VLAN tag information
823a289941SAaron LI  * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
833a289941SAaron LI  * in all other cases, p is a pointer to a buffer and buflen is its size.
843a289941SAaron LI  *
853a289941SAaron LI  * Thanks to Ani Sinha <ani@arista.com> for providing initial implementation
863a289941SAaron LI  */
87*ea16f64eSAntonio Huete Jimenez #if defined(SKF_AD_VLAN_TAG_PRESENT)
883a289941SAaron LI u_int
pcap_filter_with_aux_data(const struct bpf_insn * pc,const u_char * p,u_int wirelen,u_int buflen,const struct pcap_bpf_aux_data * aux_data)89*ea16f64eSAntonio Huete Jimenez pcap_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
90*ea16f64eSAntonio Huete Jimenez     u_int wirelen, u_int buflen, const struct pcap_bpf_aux_data *aux_data)
91*ea16f64eSAntonio Huete Jimenez #else
92*ea16f64eSAntonio Huete Jimenez u_int
93*ea16f64eSAntonio Huete Jimenez pcap_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
94*ea16f64eSAntonio Huete Jimenez     u_int wirelen, u_int buflen, const struct pcap_bpf_aux_data *aux_data _U_)
95*ea16f64eSAntonio Huete Jimenez #endif
963a289941SAaron LI {
97*ea16f64eSAntonio Huete Jimenez 	register uint32_t A, X;
983a289941SAaron LI 	register bpf_u_int32 k;
99*ea16f64eSAntonio Huete Jimenez 	uint32_t mem[BPF_MEMWORDS];
1003a289941SAaron LI 
1013a289941SAaron LI 	if (pc == 0)
1023a289941SAaron LI 		/*
1033a289941SAaron LI 		 * No filter means accept all.
1043a289941SAaron LI 		 */
1053a289941SAaron LI 		return (u_int)-1;
1063a289941SAaron LI 	A = 0;
1073a289941SAaron LI 	X = 0;
1083a289941SAaron LI 	--pc;
1093a289941SAaron LI 	for (;;) {
1103a289941SAaron LI 		++pc;
1113a289941SAaron LI 		switch (pc->code) {
1123a289941SAaron LI 
1133a289941SAaron LI 		default:
1143a289941SAaron LI 			abort();
1153a289941SAaron LI 		case BPF_RET|BPF_K:
1163a289941SAaron LI 			return (u_int)pc->k;
1173a289941SAaron LI 
1183a289941SAaron LI 		case BPF_RET|BPF_A:
1193a289941SAaron LI 			return (u_int)A;
1203a289941SAaron LI 
1213a289941SAaron LI 		case BPF_LD|BPF_W|BPF_ABS:
1223a289941SAaron LI 			k = pc->k;
1233a289941SAaron LI 			if (k > buflen || sizeof(int32_t) > buflen - k) {
1243a289941SAaron LI 				return 0;
1253a289941SAaron LI 			}
1263a289941SAaron LI 			A = EXTRACT_LONG(&p[k]);
1273a289941SAaron LI 			continue;
1283a289941SAaron LI 
1293a289941SAaron LI 		case BPF_LD|BPF_H|BPF_ABS:
1303a289941SAaron LI 			k = pc->k;
1313a289941SAaron LI 			if (k > buflen || sizeof(int16_t) > buflen - k) {
1323a289941SAaron LI 				return 0;
1333a289941SAaron LI 			}
1343a289941SAaron LI 			A = EXTRACT_SHORT(&p[k]);
1353a289941SAaron LI 			continue;
1363a289941SAaron LI 
1373a289941SAaron LI 		case BPF_LD|BPF_B|BPF_ABS:
138*ea16f64eSAntonio Huete Jimenez 			/*
139*ea16f64eSAntonio Huete Jimenez 			 * Yes, we know, this switch doesn't do
140*ea16f64eSAntonio Huete Jimenez 			 * anything unless we're building for
141*ea16f64eSAntonio Huete Jimenez 			 * a Linux kernel with removed VLAN
142*ea16f64eSAntonio Huete Jimenez 			 * tags available as meta-data.
143*ea16f64eSAntonio Huete Jimenez 			 */
144*ea16f64eSAntonio Huete Jimenez DIAG_OFF_DEFAULT_ONLY_SWITCH
1453a289941SAaron LI 			switch (pc->k) {
1463a289941SAaron LI 
1473a289941SAaron LI #if defined(SKF_AD_VLAN_TAG_PRESENT)
1483a289941SAaron LI 			case SKF_AD_OFF + SKF_AD_VLAN_TAG:
1493a289941SAaron LI 				if (!aux_data)
1503a289941SAaron LI 					return 0;
1513a289941SAaron LI 				A = aux_data->vlan_tag;
1523a289941SAaron LI 				break;
1533a289941SAaron LI 
1543a289941SAaron LI 			case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
1553a289941SAaron LI 				if (!aux_data)
1563a289941SAaron LI 					return 0;
1573a289941SAaron LI 				A = aux_data->vlan_tag_present;
1583a289941SAaron LI 				break;
1593a289941SAaron LI #endif
1603a289941SAaron LI 			default:
1613a289941SAaron LI 				k = pc->k;
1623a289941SAaron LI 				if (k >= buflen) {
1633a289941SAaron LI 					return 0;
1643a289941SAaron LI 				}
1653a289941SAaron LI 				A = p[k];
1663a289941SAaron LI 				break;
1673a289941SAaron LI 			}
168*ea16f64eSAntonio Huete Jimenez DIAG_ON_DEFAULT_ONLY_SWITCH
1693a289941SAaron LI 			continue;
1703a289941SAaron LI 
1713a289941SAaron LI 		case BPF_LD|BPF_W|BPF_LEN:
1723a289941SAaron LI 			A = wirelen;
1733a289941SAaron LI 			continue;
1743a289941SAaron LI 
1753a289941SAaron LI 		case BPF_LDX|BPF_W|BPF_LEN:
1763a289941SAaron LI 			X = wirelen;
1773a289941SAaron LI 			continue;
1783a289941SAaron LI 
1793a289941SAaron LI 		case BPF_LD|BPF_W|BPF_IND:
1803a289941SAaron LI 			k = X + pc->k;
1813a289941SAaron LI 			if (pc->k > buflen || X > buflen - pc->k ||
1823a289941SAaron LI 			    sizeof(int32_t) > buflen - k) {
1833a289941SAaron LI 				return 0;
1843a289941SAaron LI 			}
1853a289941SAaron LI 			A = EXTRACT_LONG(&p[k]);
1863a289941SAaron LI 			continue;
1873a289941SAaron LI 
1883a289941SAaron LI 		case BPF_LD|BPF_H|BPF_IND:
1893a289941SAaron LI 			k = X + pc->k;
1903a289941SAaron LI 			if (X > buflen || pc->k > buflen - X ||
1913a289941SAaron LI 			    sizeof(int16_t) > buflen - k) {
1923a289941SAaron LI 				return 0;
1933a289941SAaron LI 			}
1943a289941SAaron LI 			A = EXTRACT_SHORT(&p[k]);
1953a289941SAaron LI 			continue;
1963a289941SAaron LI 
1973a289941SAaron LI 		case BPF_LD|BPF_B|BPF_IND:
1983a289941SAaron LI 			k = X + pc->k;
1993a289941SAaron LI 			if (pc->k >= buflen || X >= buflen - pc->k) {
2003a289941SAaron LI 				return 0;
2013a289941SAaron LI 			}
2023a289941SAaron LI 			A = p[k];
2033a289941SAaron LI 			continue;
2043a289941SAaron LI 
2053a289941SAaron LI 		case BPF_LDX|BPF_MSH|BPF_B:
2063a289941SAaron LI 			k = pc->k;
2073a289941SAaron LI 			if (k >= buflen) {
2083a289941SAaron LI 				return 0;
2093a289941SAaron LI 			}
2103a289941SAaron LI 			X = (p[pc->k] & 0xf) << 2;
2113a289941SAaron LI 			continue;
2123a289941SAaron LI 
2133a289941SAaron LI 		case BPF_LD|BPF_IMM:
2143a289941SAaron LI 			A = pc->k;
2153a289941SAaron LI 			continue;
2163a289941SAaron LI 
2173a289941SAaron LI 		case BPF_LDX|BPF_IMM:
2183a289941SAaron LI 			X = pc->k;
2193a289941SAaron LI 			continue;
2203a289941SAaron LI 
2213a289941SAaron LI 		case BPF_LD|BPF_MEM:
2223a289941SAaron LI 			A = mem[pc->k];
2233a289941SAaron LI 			continue;
2243a289941SAaron LI 
2253a289941SAaron LI 		case BPF_LDX|BPF_MEM:
2263a289941SAaron LI 			X = mem[pc->k];
2273a289941SAaron LI 			continue;
2283a289941SAaron LI 
2293a289941SAaron LI 		case BPF_ST:
2303a289941SAaron LI 			mem[pc->k] = A;
2313a289941SAaron LI 			continue;
2323a289941SAaron LI 
2333a289941SAaron LI 		case BPF_STX:
2343a289941SAaron LI 			mem[pc->k] = X;
2353a289941SAaron LI 			continue;
2363a289941SAaron LI 
2373a289941SAaron LI 		case BPF_JMP|BPF_JA:
2383a289941SAaron LI 			/*
2393a289941SAaron LI 			 * XXX - we currently implement "ip6 protochain"
2403a289941SAaron LI 			 * with backward jumps, so sign-extend pc->k.
2413a289941SAaron LI 			 */
2423a289941SAaron LI 			pc += (bpf_int32)pc->k;
2433a289941SAaron LI 			continue;
2443a289941SAaron LI 
2453a289941SAaron LI 		case BPF_JMP|BPF_JGT|BPF_K:
2463a289941SAaron LI 			pc += (A > pc->k) ? pc->jt : pc->jf;
2473a289941SAaron LI 			continue;
2483a289941SAaron LI 
2493a289941SAaron LI 		case BPF_JMP|BPF_JGE|BPF_K:
2503a289941SAaron LI 			pc += (A >= pc->k) ? pc->jt : pc->jf;
2513a289941SAaron LI 			continue;
2523a289941SAaron LI 
2533a289941SAaron LI 		case BPF_JMP|BPF_JEQ|BPF_K:
2543a289941SAaron LI 			pc += (A == pc->k) ? pc->jt : pc->jf;
2553a289941SAaron LI 			continue;
2563a289941SAaron LI 
2573a289941SAaron LI 		case BPF_JMP|BPF_JSET|BPF_K:
2583a289941SAaron LI 			pc += (A & pc->k) ? pc->jt : pc->jf;
2593a289941SAaron LI 			continue;
2603a289941SAaron LI 
2613a289941SAaron LI 		case BPF_JMP|BPF_JGT|BPF_X:
2623a289941SAaron LI 			pc += (A > X) ? pc->jt : pc->jf;
2633a289941SAaron LI 			continue;
2643a289941SAaron LI 
2653a289941SAaron LI 		case BPF_JMP|BPF_JGE|BPF_X:
2663a289941SAaron LI 			pc += (A >= X) ? pc->jt : pc->jf;
2673a289941SAaron LI 			continue;
2683a289941SAaron LI 
2693a289941SAaron LI 		case BPF_JMP|BPF_JEQ|BPF_X:
2703a289941SAaron LI 			pc += (A == X) ? pc->jt : pc->jf;
2713a289941SAaron LI 			continue;
2723a289941SAaron LI 
2733a289941SAaron LI 		case BPF_JMP|BPF_JSET|BPF_X:
2743a289941SAaron LI 			pc += (A & X) ? pc->jt : pc->jf;
2753a289941SAaron LI 			continue;
2763a289941SAaron LI 
2773a289941SAaron LI 		case BPF_ALU|BPF_ADD|BPF_X:
2783a289941SAaron LI 			A += X;
2793a289941SAaron LI 			continue;
2803a289941SAaron LI 
2813a289941SAaron LI 		case BPF_ALU|BPF_SUB|BPF_X:
2823a289941SAaron LI 			A -= X;
2833a289941SAaron LI 			continue;
2843a289941SAaron LI 
2853a289941SAaron LI 		case BPF_ALU|BPF_MUL|BPF_X:
2863a289941SAaron LI 			A *= X;
2873a289941SAaron LI 			continue;
2883a289941SAaron LI 
2893a289941SAaron LI 		case BPF_ALU|BPF_DIV|BPF_X:
2903a289941SAaron LI 			if (X == 0)
2913a289941SAaron LI 				return 0;
2923a289941SAaron LI 			A /= X;
2933a289941SAaron LI 			continue;
2943a289941SAaron LI 
2953a289941SAaron LI 		case BPF_ALU|BPF_MOD|BPF_X:
2963a289941SAaron LI 			if (X == 0)
2973a289941SAaron LI 				return 0;
2983a289941SAaron LI 			A %= X;
2993a289941SAaron LI 			continue;
3003a289941SAaron LI 
3013a289941SAaron LI 		case BPF_ALU|BPF_AND|BPF_X:
3023a289941SAaron LI 			A &= X;
3033a289941SAaron LI 			continue;
3043a289941SAaron LI 
3053a289941SAaron LI 		case BPF_ALU|BPF_OR|BPF_X:
3063a289941SAaron LI 			A |= X;
3073a289941SAaron LI 			continue;
3083a289941SAaron LI 
3093a289941SAaron LI 		case BPF_ALU|BPF_XOR|BPF_X:
3103a289941SAaron LI 			A ^= X;
3113a289941SAaron LI 			continue;
3123a289941SAaron LI 
3133a289941SAaron LI 		case BPF_ALU|BPF_LSH|BPF_X:
3143a289941SAaron LI 			if (X < 32)
3153a289941SAaron LI 				A <<= X;
3163a289941SAaron LI 			else
3173a289941SAaron LI 				A = 0;
3183a289941SAaron LI 			continue;
3193a289941SAaron LI 
3203a289941SAaron LI 		case BPF_ALU|BPF_RSH|BPF_X:
3213a289941SAaron LI 			if (X < 32)
3223a289941SAaron LI 				A >>= X;
3233a289941SAaron LI 			else
3243a289941SAaron LI 				A = 0;
3253a289941SAaron LI 			continue;
3263a289941SAaron LI 
3273a289941SAaron LI 		case BPF_ALU|BPF_ADD|BPF_K:
3283a289941SAaron LI 			A += pc->k;
3293a289941SAaron LI 			continue;
3303a289941SAaron LI 
3313a289941SAaron LI 		case BPF_ALU|BPF_SUB|BPF_K:
3323a289941SAaron LI 			A -= pc->k;
3333a289941SAaron LI 			continue;
3343a289941SAaron LI 
3353a289941SAaron LI 		case BPF_ALU|BPF_MUL|BPF_K:
3363a289941SAaron LI 			A *= pc->k;
3373a289941SAaron LI 			continue;
3383a289941SAaron LI 
3393a289941SAaron LI 		case BPF_ALU|BPF_DIV|BPF_K:
3403a289941SAaron LI 			A /= pc->k;
3413a289941SAaron LI 			continue;
3423a289941SAaron LI 
3433a289941SAaron LI 		case BPF_ALU|BPF_MOD|BPF_K:
3443a289941SAaron LI 			A %= pc->k;
3453a289941SAaron LI 			continue;
3463a289941SAaron LI 
3473a289941SAaron LI 		case BPF_ALU|BPF_AND|BPF_K:
3483a289941SAaron LI 			A &= pc->k;
3493a289941SAaron LI 			continue;
3503a289941SAaron LI 
3513a289941SAaron LI 		case BPF_ALU|BPF_OR|BPF_K:
3523a289941SAaron LI 			A |= pc->k;
3533a289941SAaron LI 			continue;
3543a289941SAaron LI 
3553a289941SAaron LI 		case BPF_ALU|BPF_XOR|BPF_K:
3563a289941SAaron LI 			A ^= pc->k;
3573a289941SAaron LI 			continue;
3583a289941SAaron LI 
3593a289941SAaron LI 		case BPF_ALU|BPF_LSH|BPF_K:
3603a289941SAaron LI 			A <<= pc->k;
3613a289941SAaron LI 			continue;
3623a289941SAaron LI 
3633a289941SAaron LI 		case BPF_ALU|BPF_RSH|BPF_K:
3643a289941SAaron LI 			A >>= pc->k;
3653a289941SAaron LI 			continue;
3663a289941SAaron LI 
3673a289941SAaron LI 		case BPF_ALU|BPF_NEG:
3683a289941SAaron LI 			/*
3693a289941SAaron LI 			 * Most BPF arithmetic is unsigned, but negation
3703a289941SAaron LI 			 * can't be unsigned; respecify it as subtracting
3713a289941SAaron LI 			 * the accumulator from 0U, so that 1) we don't
3723a289941SAaron LI 			 * get compiler warnings about negating an unsigned
3733a289941SAaron LI 			 * value and 2) don't get UBSan warnings about
3743a289941SAaron LI 			 * the result of negating 0x80000000 being undefined.
3753a289941SAaron LI 			 */
3763a289941SAaron LI 			A = (0U - A);
3773a289941SAaron LI 			continue;
3783a289941SAaron LI 
3793a289941SAaron LI 		case BPF_MISC|BPF_TAX:
3803a289941SAaron LI 			X = A;
3813a289941SAaron LI 			continue;
3823a289941SAaron LI 
3833a289941SAaron LI 		case BPF_MISC|BPF_TXA:
3843a289941SAaron LI 			A = X;
3853a289941SAaron LI 			continue;
3863a289941SAaron LI 		}
3873a289941SAaron LI 	}
3883a289941SAaron LI }
3893a289941SAaron LI 
3903a289941SAaron LI u_int
pcap_filter(const struct bpf_insn * pc,const u_char * p,u_int wirelen,u_int buflen)391*ea16f64eSAntonio Huete Jimenez pcap_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
3923a289941SAaron LI     u_int buflen)
3933a289941SAaron LI {
394*ea16f64eSAntonio Huete Jimenez 	return pcap_filter_with_aux_data(pc, p, wirelen, buflen, NULL);
3953a289941SAaron LI }
3963a289941SAaron LI 
3973a289941SAaron LI /*
3983a289941SAaron LI  * Return true if the 'fcode' is a valid filter program.
3993a289941SAaron LI  * The constraints are that each jump be forward and to a valid
4003a289941SAaron LI  * code, that memory accesses are within valid ranges (to the
4013a289941SAaron LI  * extent that this can be checked statically; loads of packet
4023a289941SAaron LI  * data have to be, and are, also checked at run time), and that
4033a289941SAaron LI  * the code terminates with either an accept or reject.
4043a289941SAaron LI  *
4053a289941SAaron LI  * The kernel needs to be able to verify an application's filter code.
4063a289941SAaron LI  * Otherwise, a bogus program could easily crash the system.
4073a289941SAaron LI  */
4083a289941SAaron LI int
pcap_validate_filter(const struct bpf_insn * f,int len)409*ea16f64eSAntonio Huete Jimenez pcap_validate_filter(const struct bpf_insn *f, int len)
4103a289941SAaron LI {
4113a289941SAaron LI 	u_int i, from;
4123a289941SAaron LI 	const struct bpf_insn *p;
4133a289941SAaron LI 
4143a289941SAaron LI 	if (len < 1)
4153a289941SAaron LI 		return 0;
4163a289941SAaron LI 
4173a289941SAaron LI 	for (i = 0; i < (u_int)len; ++i) {
4183a289941SAaron LI 		p = &f[i];
4193a289941SAaron LI 		switch (BPF_CLASS(p->code)) {
4203a289941SAaron LI 		/*
4213a289941SAaron LI 		 * Check that memory operations use valid addresses.
4223a289941SAaron LI 		 */
4233a289941SAaron LI 		case BPF_LD:
4243a289941SAaron LI 		case BPF_LDX:
4253a289941SAaron LI 			switch (BPF_MODE(p->code)) {
4263a289941SAaron LI 			case BPF_IMM:
4273a289941SAaron LI 				break;
4283a289941SAaron LI 			case BPF_ABS:
4293a289941SAaron LI 			case BPF_IND:
4303a289941SAaron LI 			case BPF_MSH:
4313a289941SAaron LI 				/*
4323a289941SAaron LI 				 * There's no maximum packet data size
4333a289941SAaron LI 				 * in userland.  The runtime packet length
4343a289941SAaron LI 				 * check suffices.
4353a289941SAaron LI 				 */
4363a289941SAaron LI 				break;
4373a289941SAaron LI 			case BPF_MEM:
4383a289941SAaron LI 				if (p->k >= BPF_MEMWORDS)
4393a289941SAaron LI 					return 0;
4403a289941SAaron LI 				break;
4413a289941SAaron LI 			case BPF_LEN:
4423a289941SAaron LI 				break;
4433a289941SAaron LI 			default:
4443a289941SAaron LI 				return 0;
4453a289941SAaron LI 			}
4463a289941SAaron LI 			break;
4473a289941SAaron LI 		case BPF_ST:
4483a289941SAaron LI 		case BPF_STX:
4493a289941SAaron LI 			if (p->k >= BPF_MEMWORDS)
4503a289941SAaron LI 				return 0;
4513a289941SAaron LI 			break;
4523a289941SAaron LI 		case BPF_ALU:
4533a289941SAaron LI 			switch (BPF_OP(p->code)) {
4543a289941SAaron LI 			case BPF_ADD:
4553a289941SAaron LI 			case BPF_SUB:
4563a289941SAaron LI 			case BPF_MUL:
4573a289941SAaron LI 			case BPF_OR:
4583a289941SAaron LI 			case BPF_AND:
4593a289941SAaron LI 			case BPF_XOR:
4603a289941SAaron LI 			case BPF_LSH:
4613a289941SAaron LI 			case BPF_RSH:
4623a289941SAaron LI 			case BPF_NEG:
4633a289941SAaron LI 				break;
4643a289941SAaron LI 			case BPF_DIV:
4653a289941SAaron LI 			case BPF_MOD:
4663a289941SAaron LI 				/*
4673a289941SAaron LI 				 * Check for constant division or modulus
4683a289941SAaron LI 				 * by 0.
4693a289941SAaron LI 				 */
4703a289941SAaron LI 				if (BPF_SRC(p->code) == BPF_K && p->k == 0)
4713a289941SAaron LI 					return 0;
4723a289941SAaron LI 				break;
4733a289941SAaron LI 			default:
4743a289941SAaron LI 				return 0;
4753a289941SAaron LI 			}
4763a289941SAaron LI 			break;
4773a289941SAaron LI 		case BPF_JMP:
4783a289941SAaron LI 			/*
4793a289941SAaron LI 			 * Check that jumps are within the code block,
4803a289941SAaron LI 			 * and that unconditional branches don't go
4813a289941SAaron LI 			 * backwards as a result of an overflow.
4823a289941SAaron LI 			 * Unconditional branches have a 32-bit offset,
4833a289941SAaron LI 			 * so they could overflow; we check to make
4843a289941SAaron LI 			 * sure they don't.  Conditional branches have
4853a289941SAaron LI 			 * an 8-bit offset, and the from address is <=
4863a289941SAaron LI 			 * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
4873a289941SAaron LI 			 * is sufficiently small that adding 255 to it
4883a289941SAaron LI 			 * won't overflow.
4893a289941SAaron LI 			 *
4903a289941SAaron LI 			 * We know that len is <= BPF_MAXINSNS, and we
4913a289941SAaron LI 			 * assume that BPF_MAXINSNS is < the maximum size
4923a289941SAaron LI 			 * of a u_int, so that i + 1 doesn't overflow.
4933a289941SAaron LI 			 *
4943a289941SAaron LI 			 * For userland, we don't know that the from
4953a289941SAaron LI 			 * or len are <= BPF_MAXINSNS, but we know that
4963a289941SAaron LI 			 * from <= len, and, except on a 64-bit system,
4973a289941SAaron LI 			 * it's unlikely that len, if it truly reflects
4983a289941SAaron LI 			 * the size of the program we've been handed,
4993a289941SAaron LI 			 * will be anywhere near the maximum size of
5003a289941SAaron LI 			 * a u_int.  We also don't check for backward
5013a289941SAaron LI 			 * branches, as we currently support them in
5023a289941SAaron LI 			 * userland for the protochain operation.
5033a289941SAaron LI 			 */
5043a289941SAaron LI 			from = i + 1;
5053a289941SAaron LI 			switch (BPF_OP(p->code)) {
5063a289941SAaron LI 			case BPF_JA:
5073a289941SAaron LI 				if (from + p->k >= (u_int)len)
5083a289941SAaron LI 					return 0;
5093a289941SAaron LI 				break;
5103a289941SAaron LI 			case BPF_JEQ:
5113a289941SAaron LI 			case BPF_JGT:
5123a289941SAaron LI 			case BPF_JGE:
5133a289941SAaron LI 			case BPF_JSET:
5143a289941SAaron LI 				if (from + p->jt >= (u_int)len || from + p->jf >= (u_int)len)
5153a289941SAaron LI 					return 0;
5163a289941SAaron LI 				break;
5173a289941SAaron LI 			default:
5183a289941SAaron LI 				return 0;
5193a289941SAaron LI 			}
5203a289941SAaron LI 			break;
5213a289941SAaron LI 		case BPF_RET:
5223a289941SAaron LI 			break;
5233a289941SAaron LI 		case BPF_MISC:
5243a289941SAaron LI 			break;
5253a289941SAaron LI 		default:
5263a289941SAaron LI 			return 0;
5273a289941SAaron LI 		}
5283a289941SAaron LI 	}
5293a289941SAaron LI 	return BPF_CLASS(f[len - 1].code) == BPF_RET;
5303a289941SAaron LI }
531*ea16f64eSAntonio Huete Jimenez 
532*ea16f64eSAntonio Huete Jimenez /*
533*ea16f64eSAntonio Huete Jimenez  * Exported because older versions of libpcap exported them.
534*ea16f64eSAntonio Huete Jimenez  */
535*ea16f64eSAntonio Huete Jimenez u_int
bpf_filter(const struct bpf_insn * pc,const u_char * p,u_int wirelen,u_int buflen)536*ea16f64eSAntonio Huete Jimenez bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
537*ea16f64eSAntonio Huete Jimenez     u_int buflen)
538*ea16f64eSAntonio Huete Jimenez {
539*ea16f64eSAntonio Huete Jimenez 	return pcap_filter(pc, p, wirelen, buflen);
540*ea16f64eSAntonio Huete Jimenez }
541*ea16f64eSAntonio Huete Jimenez 
542*ea16f64eSAntonio Huete Jimenez int
bpf_validate(const struct bpf_insn * f,int len)543*ea16f64eSAntonio Huete Jimenez bpf_validate(const struct bpf_insn *f, int len)
544*ea16f64eSAntonio Huete Jimenez {
545*ea16f64eSAntonio Huete Jimenez 	return pcap_validate_filter(f, len);
546*ea16f64eSAntonio Huete Jimenez }
547