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

Reply via email to