[Devel] [PATCH RHEL7 COMMIT] ms/netfilter: x_tables: check for bogus target offset
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Jun 27 04:35:36 PDT 2016
The commit is pushed to "branch-rh7-3.10.0-327.18.2.vz7.14.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.18.2.vz7.14.21
------>
commit c54135d37b6237aed18d0353d3d95fc96a3e71cd
Author: Cyrill Gorcunov <gorcunov at virtuozzo.com>
Date: Mon Jun 27 15:35:35 2016 +0400
ms/netfilter: x_tables: check for bogus target offset
ML: ce683e5f9d045e5d67d1312a42b359cb2ab2a13c
gorcunov@: Drop check for xt_entry
From: Florian Westphal <fw at strlen.de>
We're currently asserting that targetoff + targetsize <= nextoff.
Extend it to also check that targetoff is >= sizeof(xt_entry).
Since this is generic code, add an argument pointing to the start of the
match/target, we can then derive the base structure size from the delta.
We also need the e->elems pointer in a followup change to validate matches.
Signed-off-by: Florian Westphal <fw at strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
https://jira.sw.ru/browse/PSBM-49001
Reviewed-by: Vladimir Davydov <vdavydov at virtuozzo.com>
---
net/ipv4/netfilter/arp_tables.c | 8 ++++++++
net/ipv4/netfilter/ip_tables.c | 8 ++++++++
net/ipv6/netfilter/ip6_tables.c | 8 ++++++++
3 files changed, 24 insertions(+)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index fbfa74e..e2a53cb 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -603,6 +603,10 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
if (err)
return err;
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (e->target_offset < ((const void *)e->elems - (const void *)e))
+ return -EINVAL;
+
/* Check hooks & underflows */
for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
if (!(valid_hooks & (1 << h)))
@@ -1261,6 +1265,10 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
if (ret)
return ret;
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (e->target_offset < ((const void *)e->elems - (const void *)e))
+ return -EINVAL;
+
off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);
entry_offset = (void *)e - (void *)base;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 07370e5..a95135f 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -754,6 +754,10 @@ check_entry_size_and_hooks(struct ipt_entry *e,
if (err)
return err;
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (e->target_offset < ((const void *)e->elems - (const void *)e))
+ return -EINVAL;
+
/* Check hooks & underflows */
for (h = 0; h < NF_INET_NUMHOOKS; h++) {
if (!(valid_hooks & (1 << h)))
@@ -1508,6 +1512,10 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
if (ret)
return ret;
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (e->target_offset < ((const void *)e->elems - (const void *)e))
+ return -EINVAL;
+
off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
entry_offset = (void *)e - (void *)base;
j = 0;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 43919b8..8d053b2 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -763,6 +763,10 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
if (err)
return err;
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (e->target_offset < ((const void *)e->elems - (const void *)e))
+ return -EINVAL;
+
/* Check hooks & underflows */
for (h = 0; h < NF_INET_NUMHOOKS; h++) {
if (!(valid_hooks & (1 << h)))
@@ -1517,6 +1521,10 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
if (ret)
return ret;
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (e->target_offset < ((const void *)e->elems - (const void *)e))
+ return -EINVAL;
+
off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
entry_offset = (void *)e - (void *)base;
j = 0;
More information about the Devel
mailing list