Source-Changes-HG archive

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

[src/trunk]: src/sys/net Avoid stack memory disclosure by keeping track durin...



details:   https://anonhg.NetBSD.org/src/rev/63495efb933a
branches:  trunk
changeset: 762305:63495efb933a
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Feb 19 01:12:39 2011 +0000

description:
Avoid stack memory disclosure by keeping track during filter validation time
of initialized memory. Idea taken from linux.

diffstat:

 sys/net/bpf_filter.c |  76 ++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 59 insertions(+), 17 deletions(-)

diffs (162 lines):

diff -r 4c4712c460c9 -r 63495efb933a sys/net/bpf_filter.c
--- a/sys/net/bpf_filter.c      Sat Feb 19 00:22:50 2011 +0000
+++ b/sys/net/bpf_filter.c      Sat Feb 19 01:12:39 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bpf_filter.c,v 1.41 2010/12/05 22:40:56 mrg Exp $      */
+/*     $NetBSD: bpf_filter.c,v 1.42 2011/02/19 01:12:39 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.41 2010/12/05 22:40:56 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.42 2011/02/19 01:12:39 christos Exp $");
 
 #if 0
 #if !(defined(lint) || defined(KERNEL))
@@ -461,11 +461,16 @@
  * The kernel needs to be able to verify an application's filter code.
  * Otherwise, a bogus program could easily crash the system.
  */
+CTASSERT(BPF_MEMWORDS == sizeof(uint16_t) * NBBY);
+
 int
 bpf_validate(const struct bpf_insn *f, int signed_len)
 {
-       u_int i, from, len;
+       u_int i, from, len, ok = 0;
        const struct bpf_insn *p;
+#if defined(KERNEL) || defined(_KERNEL)
+       uint16_t *mem, invalid;
+#endif
 
        len = (u_int)signed_len;
        if (len < 1)
@@ -474,8 +479,19 @@
        if (len > BPF_MAXINSNS)
                return 0;
 #endif
+       if (BPF_CLASS(f[len - 1].code) != BPF_RET)
+               return 0;
+
+#if defined(KERNEL) || defined(_KERNEL)
+       mem = malloc(sizeof(*mem) * len, M_TEMP, M_WAITOK|M_ZERO);
+       invalid = ~0;   /* All is invalid on startup */
+#endif
 
        for (i = 0; i < len; ++i) {
+#if defined(KERNEL) || defined(_KERNEL)
+               /* blend in any invalid bits for current pc */
+               invalid |= mem[i];
+#endif
                p = &f[i];
                switch (BPF_CLASS(p->code)) {
                /*
@@ -496,7 +512,10 @@
                                 * is done runtime.
                                 */
                                if (p->k >= BPF_MEMWORDS)
-                                       return 0;
+                                       goto out;
+                               /* check for current memory invalid */
+                               if (invalid & (1 << p->k))
+                                       goto out;
 #endif
                                break;
                        case BPF_ABS:
@@ -506,13 +525,17 @@
                        case BPF_LEN:
                                break;
                        default:
-                               return 0;
+                               goto out;
                        }
                        break;
                case BPF_ST:
                case BPF_STX:
                        if (p->k >= BPF_MEMWORDS)
-                               return 0;
+                               goto out;
+#if defined(KERNEL) || defined(_KERNEL)
+                       /* validate the memory word */
+                       invalid &= ~(1 << p->k);
+#endif
                        break;
                case BPF_ALU:
                        switch (BPF_OP(p->code)) {
@@ -530,10 +553,10 @@
                                 * Check for constant division by 0.
                                 */
                                if (BPF_SRC(p->code) == BPF_K && p->k == 0)
-                                       return 0;
+                                       goto out;
                                break;
                        default:
-                               return 0;
+                               goto out;
                        }
                        break;
                case BPF_JMP:
@@ -566,22 +589,37 @@
                        from = i + 1;
                        switch (BPF_OP(p->code)) {
                        case BPF_JA:
+                               if (from + p->k >= len)
+                                       goto out;
 #if defined(KERNEL) || defined(_KERNEL)
-                               if (from + p->k < from || from + p->k >= len)
-#else
-                               if (from + p->k >= len)
+                               if (from + p->k < from)
+                                       goto out;
+                               /*
+                                * mark the currently invalid bits for the
+                                * destination
+                                */
+                               mem[from + p->k] |= invalid;
+                               invalid = 0;
 #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)
-                                       return 0;
+                                       goto out;
+#if defined(KERNEL) || defined(_KERNEL)
+                               /*
+                                * mark the currently invalid bits for both
+                                * possible jump destinations
+                                */
+                               mem[from + p->jt] |= invalid;
+                               mem[from + p->jf] |= invalid;
+                               invalid = 0;
+#endif
                                break;
                        default:
-                               return 0;
+                               goto out;
                        }
                        break;
                case BPF_RET:
@@ -589,9 +627,13 @@
                case BPF_MISC:
                        break;
                default:
-                       return 0;
+                       goto out;
                }
        }
-
-       return BPF_CLASS(f[len - 1].code) == BPF_RET;
+       ok = 1;
+out:
+#if defined(KERNEL) || defined(_KERNEL)
+       free(mem, M_TEMP);
+#endif
+       return ok;
 }



Home | Main Index | Thread Index | Old Index