FreeBSD/tools/regression/bpf/bpf_filter/bpf_test.c
/*
 * XXX Copied from sys/net/bpf_filter.c and modified.
 *
 * 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.
 *
 * The kernel needs to be able to verify an application's filter code.
 * Otherwise, a bogus program could easily crash the system.
 */
XXX Copied from sys/net/bpf_filter.c and modified.
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.

The kernel needs to be able to verify an application's filter code.
Otherwise, a bogus program could easily crash the system.
XXX Copied from sys / net / bpf_filter . c and modified . 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 . The kernel needs to be able to verify an application ' s filter code . Otherwise a bogus program could easily crash the system .
static int
bpf_validate(const struct bpf_insn *f, int len)
{
	register int i;
	register const struct bpf_insn *p;
	if (len < 0)
		return (0);
	if (len == 0)
		return (1);
	for (i = 0; i < len; ++i) {
		p = &f[i];
		if (!BPF_VALIDATE_CODE(p->code))
			return (0);
		if (BPF_CLASS(p->code) == BPF_JMP) {
			register u_int offset;
			if (p->code == (BPF_JMP|BPF_JA))
				offset = p->k;
			else
				offset = p->jt > p->jf ? p->jt : p->jf;
			if (offset >= (u_int)(len - i) - 1)
				return (0);
			continue;
		}
		if (p->code == BPF_ST || p->code == BPF_STX ||
		    p->code == (BPF_LD|BPF_MEM) ||
		    p->code == (BPF_LDX|BPF_MEM)) {
			if (p->k >= BPF_MEMWORDS)
				return (0);
			continue;
		}
		if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
			return (0);
	}
	return (BPF_CLASS(f[len - 1].code) == BPF_RET);
}
static int bpf_validate ( const struct bpf_insn * f , int len ) { register int i ; register const struct bpf_insn * p ; if ( len < 0 ) return ( 0 ) ; if ( len == 0 ) return ( 1 ) ; for ( i = 0 ; i < len ; ++ i ) { p = & f [ i ] ; if ( ! BPF_VALIDATE_CODE ( p -> code ) ) return ( 0 ) ; if ( BPF_CLASS ( p -> code ) == BPF_JMP ) { register u_int offset ; if ( p -> code == ( BPF_JMP | BPF_JA ) ) offset = p -> k ; else offset = p -> jt > p -> jf ? p -> jt : p -> jf ; if ( offset >= ( u_int ) ( len - i ) - 1 ) return ( 0 ) ; continue ; } if ( p -> code == BPF_ST || p -> code == BPF_STX || p -> code == ( BPF_LD | BPF_MEM ) || p -> code == ( BPF_LDX | BPF_MEM ) ) { if ( p -> k >= BPF_MEMWORDS ) return ( 0 ) ; continue ; } if ( p -> code == ( BPF_ALU | BPF_DIV | BPF_K ) && p -> k == 0 ) return ( 0 ) ; } return ( BPF_CLASS ( f [ len - 1 ] . code ) == BPF_RET ) ; }
XXX Copied from sys/net/bpf_filter.c and modified.
XXX Copied from sys / net / bpf_filter . c and modified .
/* Do not accept negative length filter. */ /* An empty filter means accept all. */ /*
		 * Check that the code is valid.
		 */ /*
		 * Check that that jumps are forward, and within
		 * the code block.
		 */ /*
		 * Check that memory operations use valid addresses.
		 */ /*
		 * Check for constant division by 0.
		 */