mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
116 lines
3.7 KiB
Diff
116 lines
3.7 KiB
Diff
|
From 82e2616ad251a3f72991036d6e8acebbd0aceb80 Mon Sep 17 00:00:00 2001
|
||
|
From: Florian Westphal <fw@strlen.de>
|
||
|
Date: Fri, 15 Jul 2016 15:08:15 -0400
|
||
|
Subject: netfilter: x_tables: don't move to non-existent next rule
|
||
|
|
||
|
commit f24e230d257af1ad7476c6e81a8dc3127a74204e upstream.
|
||
|
|
||
|
Ben Hawkes says:
|
||
|
|
||
|
In the mark_source_chains function (net/ipv4/netfilter/ip_tables.c) it
|
||
|
is possible for a user-supplied ipt_entry structure to have a large
|
||
|
next_offset field. This field is not bounds checked prior to writing a
|
||
|
counter value at the supplied offset.
|
||
|
|
||
|
Base chains enforce absolute verdict.
|
||
|
|
||
|
User defined chains are supposed to end with an unconditional return,
|
||
|
xtables userspace adds them automatically.
|
||
|
|
||
|
But if such return is missing we will move to non-existent next rule.
|
||
|
|
||
|
CVE-2016-3134
|
||
|
|
||
|
Reported-by: Ben Hawkes <hawkes@google.com>
|
||
|
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||
|
Signed-off-by: Chas Williams <3chas3@gmail.com>
|
||
|
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
||
|
---
|
||
|
net/ipv4/netfilter/arp_tables.c | 8 +++++---
|
||
|
net/ipv4/netfilter/ip_tables.c | 4 ++++
|
||
|
net/ipv6/netfilter/ip6_tables.c | 4 ++++
|
||
|
3 files changed, 13 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
|
||
|
index 456fc6e..7460b7b 100644
|
||
|
--- a/net/ipv4/netfilter/arp_tables.c
|
||
|
+++ b/net/ipv4/netfilter/arp_tables.c
|
||
|
@@ -430,6 +430,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
|
||
|
size = e->next_offset;
|
||
|
e = (struct arpt_entry *)
|
||
|
(entry0 + pos + size);
|
||
|
+ if (pos + size >= newinfo->size)
|
||
|
+ return 0;
|
||
|
e->counters.pcnt = pos;
|
||
|
pos += size;
|
||
|
} else {
|
||
|
@@ -452,6 +454,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
|
||
|
} else {
|
||
|
/* ... this is a fallthru */
|
||
|
newpos = pos + e->next_offset;
|
||
|
+ if (newpos >= newinfo->size)
|
||
|
+ return 0;
|
||
|
}
|
||
|
e = (struct arpt_entry *)
|
||
|
(entry0 + newpos);
|
||
|
@@ -675,10 +679,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) {
|
||
|
- duprintf("Looping hook\n");
|
||
|
+ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
|
||
|
return -ELOOP;
|
||
|
- }
|
||
|
|
||
|
/* Finally, each sanity check must pass */
|
||
|
i = 0;
|
||
|
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
|
||
|
index a5bd3c8..8fc22ee 100644
|
||
|
--- a/net/ipv4/netfilter/ip_tables.c
|
||
|
+++ b/net/ipv4/netfilter/ip_tables.c
|
||
|
@@ -511,6 +511,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
||
|
size = e->next_offset;
|
||
|
e = (struct ipt_entry *)
|
||
|
(entry0 + pos + size);
|
||
|
+ if (pos + size >= newinfo->size)
|
||
|
+ return 0;
|
||
|
e->counters.pcnt = pos;
|
||
|
pos += size;
|
||
|
} else {
|
||
|
@@ -532,6 +534,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
||
|
} else {
|
||
|
/* ... this is a fallthru */
|
||
|
newpos = pos + e->next_offset;
|
||
|
+ if (newpos >= newinfo->size)
|
||
|
+ return 0;
|
||
|
}
|
||
|
e = (struct ipt_entry *)
|
||
|
(entry0 + newpos);
|
||
|
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
|
||
|
index fb8a146..63f7876 100644
|
||
|
--- a/net/ipv6/netfilter/ip6_tables.c
|
||
|
+++ b/net/ipv6/netfilter/ip6_tables.c
|
||
|
@@ -521,6 +521,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
||
|
size = e->next_offset;
|
||
|
e = (struct ip6t_entry *)
|
||
|
(entry0 + pos + size);
|
||
|
+ if (pos + size >= newinfo->size)
|
||
|
+ return 0;
|
||
|
e->counters.pcnt = pos;
|
||
|
pos += size;
|
||
|
} else {
|
||
|
@@ -542,6 +544,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
|
||
|
} else {
|
||
|
/* ... this is a fallthru */
|
||
|
newpos = pos + e->next_offset;
|
||
|
+ if (newpos >= newinfo->size)
|
||
|
+ return 0;
|
||
|
}
|
||
|
e = (struct ip6t_entry *)
|
||
|
(entry0 + newpos);
|
||
|
--
|
||
|
cgit v1.1
|
||
|
|