CVE-2016-4998 oob reads when processing IPT_SO_SET_REPLACE setsockopt (rhbz 1349886 1350316)

This commit is contained in:
Justin M. Forbes 2016-06-28 13:00:03 -05:00
parent c3a014b8cf
commit 9759d1d73d
3 changed files with 3114 additions and 154 deletions

View File

@ -42,7 +42,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
%global baserelease 201
%global baserelease 202
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@ -620,9 +620,6 @@ Patch648: 0001-mm-CONFIG_NR_ZONES_EXTENDED.patch
#CVE-2016-3135 rhbz 1317386 1317387
Patch664: netfilter-x_tables-check-for-size-overflow.patch
#CVE-2016-3134 rhbz 1317383 1317384
Patch665: netfilter-x_tables-deal-with-bogus-nextoffset-values.patch
# CVE-2016-3672 rhbz 1324749 1324750
Patch689: x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch
@ -673,6 +670,9 @@ Patch728: hp-wmi-fix-wifi-cannot-be-hard-unblock.patch
#CVE-2016-4998 rhbz 1349886 1350316
Patch729: CVE-2016-4998.patch
#CVE-2016-4998 rhbz 1349886 1350316
Patch730: netfilter-more-fixes.patch
#CVE-2016-5829 rhbz 1350509 1350513
Patch826: HID-hiddev-validate-num_values-for-HIDIOCGUSAGES-HID.patch
@ -2200,6 +2200,9 @@ fi
#
#
%changelog
* Tue Jun 28 2016 Justin M. Forbes <jforbes@fedoraproject.org> - 4.5.7-202
- CVE-2016-4998 oob reads when processing IPT_SO_SET_REPLACE setsockopt (rhbz 1349886 1350316)
* Tue Jun 28 2016 Josh Boyer <jwboyer@fedoraproject.org>
- CVE-2016-1237 missing check for permissions setting ACL (rhbz 1350845 1350847)
- CVE-2016-5728 race condition in mic driver (rhbz 1350811 1350812)

3107
netfilter-more-fixes.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,150 +0,0 @@
Subject: [PATCH nf] netfilter: x_tables: deal with bogus nextoffset values
From: Florian Westphal <fw () strlen ! de>
Date: 2016-03-10 0:56:02
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.
Problem is that xt_entry_foreach() macro stops iterating once e->next_offset
is out of bounds, assuming this is the last entry.
With malformed data thats not necessarily the case so we can
write outside of allocated area later as we might not have walked the
entire blob.
Fix this by simplifying mark_source_chains -- it already has to check
if nextoff is in range to catch invalid jumps, so just do the check
when we move to a next entry as well.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/ipv4/netfilter/arp_tables.c | 16 ++++++++--------
net/ipv4/netfilter/ip_tables.c | 15 ++++++++-------
net/ipv6/netfilter/ip6_tables.c | 13 ++++++-------
3 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index b488cac..5a0b591 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -437,6 +437,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
/* Move along one */
size = e->next_offset;
+
+ if (pos + size > newinfo->size - sizeof(*e))
+ return 0;
+
e = (struct arpt_entry *)
(entry0 + pos + size);
e->counters.pcnt = pos;
@@ -447,14 +451,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
if (strcmp(t->target.u.user.name,
XT_STANDARD_TARGET) == 0 &&
newpos >= 0) {
- if (newpos > newinfo->size -
- sizeof(struct arpt_entry)) {
- duprintf("mark_source_chains: "
- "bad verdict (%i)\n",
- newpos);
- return 0;
- }
-
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
@@ -462,6 +458,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
/* ... this is a fallthru */
newpos = pos + e->next_offset;
}
+
+ if (newpos > newinfo->size - sizeof(*e))
+ return 0;
+
e = (struct arpt_entry *)
(entry0 + newpos);
e->counters.pcnt = pos;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index b99affa..ceb995f 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -519,6 +519,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* Move along one */
size = e->next_offset;
+
+ if (pos + size > newinfo->size - sizeof(*e))
+ return 0;
+
e = (struct ipt_entry *)
(entry0 + pos + size);
e->counters.pcnt = pos;
@@ -529,13 +533,6 @@ mark_source_chains(const struct xt_table_info *newinfo,
if (strcmp(t->target.u.user.name,
XT_STANDARD_TARGET) == 0 &&
newpos >= 0) {
- if (newpos > newinfo->size -
- sizeof(struct ipt_entry)) {
- duprintf("mark_source_chains: "
- "bad verdict (%i)\n",
- newpos);
- return 0;
- }
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
@@ -543,6 +540,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* ... this is a fallthru */
newpos = pos + e->next_offset;
}
+
+ if (newpos > newinfo->size - sizeof(*e))
+ return 0;
+
e = (struct ipt_entry *)
(entry0 + newpos);
e->counters.pcnt = pos;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 99425cf..d88a794 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -531,6 +531,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* Move along one */
size = e->next_offset;
+ if (pos + size > newinfo->size - sizeof(*e))
+ return 0;
e = (struct ip6t_entry *)
(entry0 + pos + size);
e->counters.pcnt = pos;
@@ -541,13 +543,6 @@ mark_source_chains(const struct xt_table_info *newinfo,
if (strcmp(t->target.u.user.name,
XT_STANDARD_TARGET) == 0 &&
newpos >= 0) {
- if (newpos > newinfo->size -
- sizeof(struct ip6t_entry)) {
- duprintf("mark_source_chains: "
- "bad verdict (%i)\n",
- newpos);
- return 0;
- }
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
@@ -555,6 +550,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* ... this is a fallthru */
newpos = pos + e->next_offset;
}
+
+ if (newpos > newinfo->size - sizeof(*e))
+ return 0;
+
e = (struct ip6t_entry *)
(entry0 + newpos);
e->counters.pcnt = pos;
--
2.4.10