Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net make bpf_validate available in userland.



details:   https://anonhg.NetBSD.org/src/rev/e94eb160296b
branches:  trunk
changeset: 759272:e94eb160296b
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Dec 05 02:40:40 2010 +0000

description:
make bpf_validate available in userland.

diffstat:

 sys/net/bpf.h        |   4 +-
 sys/net/bpf_filter.c |  57 ++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 46 insertions(+), 15 deletions(-)

diffs (149 lines):

diff -r 727e41fb71c6 -r e94eb160296b sys/net/bpf.h
--- a/sys/net/bpf.h     Sun Dec 05 01:45:46 2010 +0000
+++ b/sys/net/bpf.h     Sun Dec 05 02:40:40 2010 +0000
@@ -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);
 
 /*
diff -r 727e41fb71c6 -r e94eb160296b sys/net/bpf_filter.c
--- a/sys/net/bpf_filter.c      Sun Dec 05 01:45:46 2010 +0000
+++ b/sys/net/bpf_filter.c      Sun Dec 05 02:40:40 2010 +0000
@@ -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_IMM:
+                               break;
+                       case BPF_ABS:
+                       case BPF_IND:
+                       case BPF_MSH:
+                               /*
+                                * 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_ABS:
-                       case BPF_IND:
-                       case BPF_MSH:
-                       case BPF_IMM:
                        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



Home | Main Index | Thread Index | Old Index