[patch 13/32] NETFILTER: Fix iptables compat hook validation

2006-12-08 Thread Chris Wright
-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, >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, >ip,
+   e->comefrom);
+   if (ret)
+   return ret;
+
+   return 

[patch 13/32] NETFILTER: Fix iptables compat hook validation

2006-12-08 Thread Chris Wright
-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