]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
[PATCH] EBTABLES: Fix wraparounds in ebt_entries verification.
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 1 Dec 2006 03:47:52 +0000 (19:47 -0800)
committerChris Wright <chrisw@sous-sol.org>
Sun, 17 Dec 2006 00:20:46 +0000 (16:20 -0800)
We need to verify that
a) we are not too close to the end of buffer to dereference
b) next entry we'll be checking won't be _before_ our

While we are at it, don't subtract unrelated pointers...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
net/bridge/netfilter/ebtables.c

index 3a13ed643459bc3d249d0b73b1c98a1d76e5a3c5..efbbf279f560fe2765d2e5da0643da88096ed1cb 100644 (file)
@@ -423,13 +423,17 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
    struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
    unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
 {
+       unsigned int offset = (char *)e - newinfo->entries;
+       size_t left = (limit - base) - offset;
        int i;
 
+       if (left < sizeof(unsigned int))
+               goto Esmall;
+
        for (i = 0; i < NF_BR_NUMHOOKS; i++) {
                if ((valid_hooks & (1 << i)) == 0)
                        continue;
-               if ( (char *)hook_entries[i] - base ==
-                  (char *)e - newinfo->entries)
+               if ((char *)hook_entries[i] == base + offset)
                        break;
        }
        /* beginning of a new chain
@@ -450,11 +454,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
                        return -EINVAL;
                }
                /* before we look at the struct, be sure it is not too big */
-               if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
-                  > limit) {
-                       BUGPRINT("entries_size too small\n");
-                       return -EINVAL;
-               }
+               if (left < sizeof(struct ebt_entries))
+                       goto Esmall;
                if (((struct ebt_entries *)e)->policy != EBT_DROP &&
                   ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
                        /* only RETURN from udc */
@@ -477,6 +478,8 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
                return 0;
        }
        /* a plain old entry, heh */
+       if (left < sizeof(struct ebt_entry))
+               goto Esmall;
        if (sizeof(struct ebt_entry) > e->watchers_offset ||
           e->watchers_offset > e->target_offset ||
           e->target_offset >= e->next_offset) {
@@ -488,10 +491,16 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
                BUGPRINT("target size too small\n");
                return -EINVAL;
        }
+       if (left < e->next_offset)
+               goto Esmall;
 
        (*cnt)++;
        (*totalcnt)++;
        return 0;
+
+Esmall:
+       BUGPRINT("entries_size too small\n");
+       return -EINVAL;
 }
 
 struct ebt_cl_stack