-stable review patch.  If anyone has any objections, please let us know.
------------------

From: Dmitry Mishin <[EMAIL PROTECTED]>

In compat mode, matches and targets valid hooks checks always successful due
to not initialized e->comefrom field yet. This patch separates this checks from
translation code and moves them after mark_source_chains() call, where these
marks are initialized.

Signed-off-by: Dmitry Mishin <[EMAIL PROTECTED]>
Signed-off-by; Patrick McHardy <[EMAIL PROTECTED]>
Signed-off-by: Chris Wright <[EMAIL PROTECTED]>
---
commit 14f5487cb9bd34cd59360d2cac7dccac9b27e8ce
tree fab7cabcdb7fe450ff47bf42918f845ff3da1b86
parent 756c508367e95d6f963502e4feecb8c76aeee332
author Dmitry Mishin <[EMAIL PROTECTED]> Mon, 04 Dec 2006 12:19:35 +0100
committer Patrick McHardy <[EMAIL PROTECTED]> Mon, 04 Dec 2006 12:19:35 +0100

 net/ipv4/netfilter/ip_tables.c |   78 ++++++++++++++++++++++++++---------------
 1 file changed, 51 insertions(+), 27 deletions(-)

--- linux-2.6.19.orig/net/ipv4/netfilter/ip_tables.c
+++ linux-2.6.19/net/ipv4/netfilter/ip_tables.c
@@ -1516,25 +1516,8 @@ static inline int compat_copy_match_from
        void **dstptr, compat_uint_t *size, const char *name,
        const struct ipt_ip *ip, unsigned int hookmask)
 {
-       struct ipt_entry_match *dm;
-       struct ipt_match *match;
-       int ret;
-
-       dm = (struct ipt_entry_match *)*dstptr;
-       match = m->u.kernel.match;
        xt_compat_match_from_user(m, dstptr, size);
-
-       ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
-                            name, hookmask, ip->proto,
-                            ip->invflags & IPT_INV_PROTO);
-       if (!ret && m->u.kernel.match->checkentry
-           && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
-                                             hookmask)) {
-               duprintf("ip_tables: check failed for `%s'.\n",
-                        m->u.kernel.match->name);
-               ret = -EINVAL;
-       }
-       return ret;
+       return 0;
 }
 
 static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
@@ -1556,7 +1539,7 @@ static int compat_copy_entry_from_user(s
        ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
                        name, &de->ip, de->comefrom);
        if (ret)
-               goto err;
+               return ret;
        de->target_offset = e->target_offset - (origsize - *size);
        t = ipt_get_target(e);
        target = t->u.kernel.target;
@@ -1569,26 +1552,62 @@ static int compat_copy_entry_from_user(s
                if ((unsigned char *)de - base < newinfo->underflow[h])
                        newinfo->underflow[h] -= origsize - *size;
        }
+       return ret;
+}
+
+static inline int compat_check_match(struct ipt_entry_match *m, const char 
*name,
+                               const struct ipt_ip *ip, unsigned int hookmask)
+{
+       struct ipt_match *match;
+       int ret;
 
-       t = ipt_get_target(de);
+       match = m->u.kernel.match;
+       ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
+                            name, hookmask, ip->proto,
+                            ip->invflags & IPT_INV_PROTO);
+       if (!ret && m->u.kernel.match->checkentry
+           && !m->u.kernel.match->checkentry(name, ip, match, m->data,
+                                             hookmask)) {
+               duprintf("ip_tables: compat: check failed for `%s'.\n",
+                        m->u.kernel.match->name);
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static inline int compat_check_target(struct ipt_entry *e, const char *name)
+{
+       struct ipt_entry_target *t;
+       struct ipt_target *target;
+       int ret;
+
+       t = ipt_get_target(e);
        target = t->u.kernel.target;
        ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
                              name, e->comefrom, e->ip.proto,
                              e->ip.invflags & IPT_INV_PROTO);
-       if (ret)
-               goto err;
-
-       if (t->u.kernel.target->checkentry
-                  && !t->u.kernel.target->checkentry(name, de, target,
-                                                     t->data, de->comefrom)) {
+       if (!ret && t->u.kernel.target->checkentry
+                  && !t->u.kernel.target->checkentry(name, e, target,
+                                                     t->data, e->comefrom)) {
                duprintf("ip_tables: compat: check failed for `%s'.\n",
                         t->u.kernel.target->name);
                ret = -EINVAL;
        }
-err:
        return ret;
 }
 
+static inline int compat_check_entry(struct ipt_entry *e, const char *name)
+{
+       int ret;
+
+       ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip,
+                                                               e->comefrom);
+       if (ret)
+               return ret;
+
+       return compat_check_target(e, name);
+}
+
 static int
 translate_compat_table(const char *name,
                unsigned int valid_hooks,
@@ -1677,6 +1696,11 @@ translate_compat_table(const char *name,
        if (!mark_source_chains(newinfo, valid_hooks, entry1))
                goto free_newinfo;
 
+       ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
+                                                                       name);
+       if (ret)
+               goto free_newinfo;
+
        /* And one copy for every other CPU */
        for_each_possible_cpu(i)
                if (newinfo->entries[i] && newinfo->entries[i] != entry1)

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to