From: Patrick McHardy <kaber@trash.net>
To: stable@kernel.org
Cc: netfilter-devel@lists.netfilter.org,
Patrick McHardy <kaber@trash.net>,
davem@davemloft.net
Subject: [NETFILTER 04/08]: Missed and reordered checks in {arp, ip, ip6}_tables
Date: Fri, 17 Nov 2006 06:35:45 +0100 (MET) [thread overview]
Message-ID: <20061117053545.10231.94652.sendpatchset@localhost.localdomain> (raw)
In-Reply-To: <20061117053540.10231.92379.sendpatchset@localhost.localdomain>
[NETFILTER]: Missed and reordered checks in {arp,ip,ip6}_tables
There is a number of issues in parsing user-provided table in
translate_table(). Malicious user with CAP_NET_ADMIN may crash system by
passing special-crafted table to the *_tables.
The first issue is that mark_source_chains() function is called before entry
content checks. In case of standard target, mark_source_chains() function
uses t->verdict field in order to determine new position. But the check, that
this field leads no further, than the table end, is in check_entry(), which
is called later, than mark_source_chains().
The second issue, that there is no check that target_offset points inside
entry. If so, *_ITERATE_MATCH macro will follow further, than the entry
ends. As a result, we'll have oops or memory disclosure.
And the third issue, that there is no check that the target is completely
inside entry. Results are the same, as in previous issue.
Signed-off-by: Dmitry Mishin <dim@openvz.org>
Acked-by: Kirill Korotaev <dev@openvz.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
commit 0ef4760e162ea44c847cca7393b36e5bcac5414e
tree 7036ce51d75aaf46d5c4abca281956c39caced10
parent 94a3d63f9ca6cb404f62ee4186d20fec3e8bdc97
author Patrick McHardy <kaber@trash.net> Fri, 17 Nov 2006 06:24:10 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 17 Nov 2006 06:24:10 +0100
net/ipv4/netfilter/arp_tables.c | 25 ++++++++++++++++---------
net/ipv4/netfilter/ip_tables.c | 30 ++++++++++++++++++++++--------
net/ipv6/netfilter/ip6_tables.c | 24 ++++++++++++++++--------
3 files changed, 54 insertions(+), 25 deletions(-)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 8d1d7a6..9ea7869 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -471,7 +471,13 @@ static inline int check_entry(struct arp
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset)
+ return -EINVAL;
+
t = arpt_get_target(e);
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ return -EINVAL;
+
target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name,
t->u.user.revision),
"arpt_%s", t->u.user.name);
@@ -629,20 +635,18 @@ static int translate_table(const char *n
}
}
- if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
- duprintf("Looping hook\n");
- return -ELOOP;
- }
-
/* Finally, each sanity check must pass */
i = 0;
ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
- if (ret != 0) {
- ARPT_ENTRY_ITERATE(entry0, newinfo->size,
- cleanup_entry, &i);
- return ret;
+ if (ret != 0)
+ goto cleanup;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
+ duprintf("Looping hook\n");
+ goto cleanup;
}
/* And one copy for every other CPU */
@@ -651,6 +655,9 @@ static int translate_table(const char *n
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
+ return 0;
+cleanup:
+ ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
return ret;
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index b22e4d3..dcfb7f7 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -552,12 +552,18 @@ check_entry(struct ipt_entry *e, const c
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
+ return -EINVAL;
+
j = 0;
ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;
t = ipt_get_target(e);
+ ret = -EINVAL;
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
@@ -720,19 +726,17 @@ translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks, entry0))
- return -ELOOP;
-
/* Finally, each sanity check must pass */
i = 0;
ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
- if (ret != 0) {
- IPT_ENTRY_ITERATE(entry0, newinfo->size,
- cleanup_entry, &i);
- return ret;
- }
+ if (ret != 0)
+ goto cleanup;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry0))
+ goto cleanup;
/* And one copy for every other CPU */
for_each_possible_cpu(i) {
@@ -740,6 +744,9 @@ translate_table(const char *name,
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
+ return 0;
+cleanup:
+ IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
return ret;
}
@@ -1531,6 +1538,10 @@ check_compat_entry_size_and_hooks(struct
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct compat_xt_entry_target) >
+ e->next_offset)
+ return -EINVAL;
+
off = 0;
entry_offset = (void *)e - (void *)base;
j = 0;
@@ -1540,6 +1551,9 @@ check_compat_entry_size_and_hooks(struct
goto cleanup_matches;
t = ipt_get_target(e);
+ ret = -EINVAL;
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index c9d6b23..9a27156 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -592,12 +592,19 @@ check_entry(struct ip6t_entry *e, const
return -EINVAL;
}
+ if (e->target_offset + sizeof(struct ip6t_entry_target) >
+ e->next_offset)
+ return -EINVAL;
+
j = 0;
ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;
t = ip6t_get_target(e);
+ ret = -EINVAL;
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET6,
t->u.user.name,
t->u.user.revision),
@@ -760,19 +767,17 @@ translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks, entry0))
- return -ELOOP;
-
/* Finally, each sanity check must pass */
i = 0;
ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
- if (ret != 0) {
- IP6T_ENTRY_ITERATE(entry0, newinfo->size,
- cleanup_entry, &i);
- return ret;
- }
+ if (ret != 0)
+ goto cleanup;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry0))
+ goto cleanup;
/* And one copy for every other CPU */
for_each_possible_cpu(i) {
@@ -780,6 +785,9 @@ translate_table(const char *name,
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
+ return 0;
+cleanup:
+ IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
return ret;
}
next prev parent reply other threads:[~2006-11-17 5:35 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-17 5:35 [NETFILTER 00/08]: Netfilter -stable fixes Patrick McHardy
2006-11-17 5:35 ` [NETFILTER 01/08]: Missing check for CAP_NET_ADMIN in iptables compat layer Patrick McHardy
2006-11-17 5:35 ` [NETFILTER 02/08]: ip_tables: compat error way cleanup Patrick McHardy
2006-11-17 5:35 ` [NETFILTER 03/08]: ip_tables: fix module refcount leaks in compat error paths Patrick McHardy
2006-11-17 5:35 ` Patrick McHardy [this message]
2006-11-17 5:35 ` [NETFILTER 05/08]: arp_tables: missing unregistration on module unload Patrick McHardy
2006-11-17 5:35 ` [NETFILTER 06/08]: Honour source routing for LVS-NAT Patrick McHardy
2006-11-17 5:35 ` [NETFILTER 07/08]: Kconfig: fix xt_physdev dependencies Patrick McHardy
2006-11-17 5:35 ` [NETFILTER 08/08]: xt_CONNSECMARK: fix Kconfig dependencies Patrick McHardy
2006-11-17 7:02 ` [stable] [NETFILTER 00/08]: Netfilter -stable fixes Chris Wright
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20061117053545.10231.94652.sendpatchset@localhost.localdomain \
--to=kaber@trash.net \
--cc=davem@davemloft.net \
--cc=netfilter-devel@lists.netfilter.org \
--cc=stable@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.