diff options
author | guido <guido@FreeBSD.org> | 2006-08-16 12:23:02 +0000 |
---|---|---|
committer | guido <guido@FreeBSD.org> | 2006-08-16 12:23:02 +0000 |
commit | e49049679f4ee5ce6bb9214122154c529a811b5e (patch) | |
tree | 435ea094ad0e55736442383de5885c9c40c9d2a2 /contrib/ipfilter/bpf_filter.c | |
parent | fcfb8e57499dfda26645e92a1b5ad74c6f35ee92 (diff) | |
download | FreeBSD-src-e49049679f4ee5ce6bb9214122154c529a811b5e.zip FreeBSD-src-e49049679f4ee5ce6bb9214122154c529a811b5e.tar.gz |
Resolve conflicts
MFC after: 1 weeks
Diffstat (limited to 'contrib/ipfilter/bpf_filter.c')
-rw-r--r-- | contrib/ipfilter/bpf_filter.c | 133 |
1 files changed, 105 insertions, 28 deletions
diff --git a/contrib/ipfilter/bpf_filter.c b/contrib/ipfilter/bpf_filter.c index 730e6f8..9291163 100644 --- a/contrib/ipfilter/bpf_filter.c +++ b/contrib/ipfilter/bpf_filter.c @@ -42,7 +42,7 @@ #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) static const char rcsid[] = - "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2.2.1 2005/06/18 02:41:30 darrenr Exp $ (LBL)"; + "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2.2.2 2005/12/30 12:57:28 darrenr Exp $ (LBL)"; #endif #include <sys/param.h> @@ -468,9 +468,10 @@ bpf_filter(pc, p, wirelen, buflen) /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid - * code. The code must terminate with either an accept or reject. - * 'valid' is an array for use by the routine (it must be at least - * 'len' bytes long). + * code, that memory accesses are within valid ranges (to the + * extent that this can be checked statically; loads of packet + * data have to be, and are, also checked at run time), and that + * the code terminates with either an accept or reject. * * The kernel needs to be able to verify an application's filter code. * Otherwise, a bogus program could easily crash the system. @@ -480,38 +481,114 @@ bpf_validate(f, len) struct bpf_insn *f; int len; { - register int i; - register struct bpf_insn *p; + u_int i, from; + const struct bpf_insn *p; + + if (len == 0) + return 1; + + if (len < 1 || len > BPF_MAXINSNS) + return 0; for (i = 0; i < len; ++i) { + p = &f[i]; + switch (BPF_CLASS(p->code)) { /* - * Check that that jumps are forward, and within - * the code block. + * Check that memory operations use valid addresses. */ - p = &f[i]; - if (BPF_CLASS(p->code) == BPF_JMP) { - register int from = i + 1; - - if (BPF_OP(p->code) == BPF_JA) { - if (from + p->k >= (unsigned)len) + case BPF_LD: + case BPF_LDX: + switch (BPF_MODE(p->code)) { + case BPF_IMM: + break; + case BPF_ABS: + case BPF_IND: + case BPF_MSH: + /* + * More strict check with actual packet length + * is done runtime. + */ +#if 0 + if (p->k >= bpf_maxbufsize) + return 0; +#endif + break; + case BPF_MEM: + if (p->k >= BPF_MEMWORDS) return 0; + break; + case BPF_LEN: + break; + default: + return 0; } - else if (from + p->jt >= len || from + p->jf >= len) + break; + case BPF_ST: + case BPF_STX: + if (p->k >= BPF_MEMWORDS) return 0; - } - /* - * Check that memory operations use valid addresses. - */ - if ((BPF_CLASS(p->code) == BPF_ST || - (BPF_CLASS(p->code) == BPF_LD && - (p->code & 0xe0) == BPF_MEM)) && - (p->k >= BPF_MEMWORDS || p->k < 0)) - return 0; - /* - * Check for constant division by 0. - */ - if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) + break; + case BPF_ALU: + switch (BPF_OP(p->code)) { + case BPF_ADD: + case BPF_SUB: + case BPF_OR: + case BPF_AND: + case BPF_LSH: + case BPF_RSH: + case BPF_NEG: + break; + case BPF_DIV: + /* + * Check for constant division by 0. + */ + if (BPF_RVAL(p->code) == BPF_K && p->k == 0) + return 0; + default: + return 0; + } + break; + case BPF_JMP: + /* + * Check that jumps are within the code block, + * and that unconditional branches don't go + * backwards as a result of an overflow. + * Unconditional branches have a 32-bit offset, + * so they could overflow; we check to make + * sure they don't. Conditional branches have + * an 8-bit offset, and the from address is <= + * BPF_MAXINSNS, and we assume that BPF_MAXINSNS + * is sufficiently small that adding 255 to it + * won't overflow. + * + * We know that len is <= BPF_MAXINSNS, and we + * assume that BPF_MAXINSNS is < the maximum size + * of a u_int, so that i + 1 doesn't overflow. + */ + from = i + 1; + switch (BPF_OP(p->code)) { + case BPF_JA: + if (from + p->k < from || from + p->k >= len) + return 0; + break; + case BPF_JEQ: + case BPF_JGT: + case BPF_JGE: + case BPF_JSET: + if (from + p->jt >= len || from + p->jf >= len) + return 0; + break; + default: + return 0; + } + break; + case BPF_RET: + break; + case BPF_MISC: + break; + default: return 0; + } } return BPF_CLASS(f[len - 1].code) == BPF_RET; } |