Module Name: src Committed By: christos Date: Sun Dec 5 02:40:40 UTC 2010
Modified Files: src/sys/net: bpf.h bpf_filter.c Log Message: make bpf_validate available in userland. To generate a diff of this commit: cvs rdiff -u -r1.56 -r1.57 src/sys/net/bpf.h cvs rdiff -u -r1.37 -r1.38 src/sys/net/bpf_filter.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/bpf.h diff -u src/sys/net/bpf.h:1.56 src/sys/net/bpf.h:1.57 --- src/sys/net/bpf.h:1.56 Sat Dec 4 19:34:21 2010 +++ src/sys/net/bpf.h Sat Dec 4 21:40:40 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: bpf.h,v 1.56 2010/12/05 00:34:21 christos Exp $ */ +/* $NetBSD: bpf.h,v 1.57 2010/12/05 02:40:40 christos Exp $ */ /* * Copyright (c) 1990, 1991, 1993 @@ -358,9 +358,9 @@ void bpfilterattach(int); -int bpf_validate(struct bpf_insn *, int); #endif +int bpf_validate(const struct bpf_insn *, int); u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); /* Index: src/sys/net/bpf_filter.c diff -u src/sys/net/bpf_filter.c:1.37 src/sys/net/bpf_filter.c:1.38 --- src/sys/net/bpf_filter.c:1.37 Sat Dec 4 19:34:21 2010 +++ src/sys/net/bpf_filter.c Sat Dec 4 21:40:40 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: bpf_filter.c,v 1.37 2010/12/05 00:34:21 christos Exp $ */ +/* $NetBSD: bpf_filter.c,v 1.38 2010/12/05 02:40:40 christos Exp $ */ /*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.37 2010/12/05 00:34:21 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.38 2010/12/05 02:40:40 christos Exp $"); #if 0 #if !(defined(lint) || defined(KERNEL)) @@ -450,7 +450,6 @@ } } -#ifdef _KERNEL /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid @@ -463,13 +462,17 @@ * Otherwise, a bogus program could easily crash the system. */ int -bpf_validate(struct bpf_insn *f, int len) +bpf_validate(const struct bpf_insn *f, int len) { u_int i, from; - struct bpf_insn *p; + const struct bpf_insn *p; - if (len < 1 || len > BPF_MAXINSNS) + if (len < 1) + return 0; +#if defined(KERNEL) || defined(_KERNEL) + if (len > BPF_MAXINSNS) return 0; +#endif for (i = 0; i < len; ++i) { p = &f[i]; @@ -480,14 +483,29 @@ case BPF_LD: case BPF_LDX: switch (BPF_MODE(p->code)) { - case BPF_MEM: - if (p->k >= BPF_MEMWORDS) - return 0; + case BPF_IMM: break; case BPF_ABS: case BPF_IND: case BPF_MSH: - case BPF_IMM: + /* + * There's no maximum packet data size + * in userland. The runtime packet length + * check suffices. + */ +#if defined(KERNEL) || defined(_KERNEL) + /* + * More strict check with actual packet length + * is done runtime. + */ + if (p->k >= BPF_MEMWORDS) + return 0; +#endif + break; + case BPF_MEM: + if (p->k >= BPF_MEMWORDS) + return 0; + break; case BPF_LEN: break; default: @@ -514,7 +532,7 @@ /* * Check for constant division by 0. */ - if (BPF_SRC(p->code) == BPF_K && p->k == 0) + if (BPF_RVAL(p->code) == BPF_K && p->k == 0) return 0; break; default: @@ -537,18 +555,32 @@ * 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. + * + * For userland, we don't know that the from + * or len are <= BPF_MAXINSNS, but we know that + * from <= len, and, except on a 64-bit system, + * it's unlikely that len, if it truly reflects + * the size of the program we've been handed, + * will be anywhere near the maximum size of + * a u_int. We also don't check for backward + * branches, as we currently support them in + * userland for the protochain operation. */ from = i + 1; switch (BPF_OP(p->code)) { case BPF_JA: +#if defined(KERNEL) || defined(_KERNEL) if (from + p->k < from || from + p->k >= len) +#else + if (from + p->k >= len) +#endif return 0; break; case BPF_JEQ: case BPF_JGT: case BPF_JGE: case BPF_JSET: - if (from + p->jt >= len || from + p->jf >= len) + if (from + p->jt >= len || from + p->jf >= len) return 0; break; default: @@ -566,4 +598,3 @@ return BPF_CLASS(f[len - 1].code) == BPF_RET; } -#endif