diff options
author | Laura Abbott <labbott@fedoraproject.org> | 2016-07-25 15:01:09 -0700 |
---|---|---|
committer | Laura Abbott <labbott@fedoraproject.org> | 2016-07-26 16:36:43 -0700 |
commit | f339ce1dadf093ec63e24a19c01e75b821bb3974 (patch) | |
tree | 03552e16d4f7efe60041baeba6835989e8a99dd5 /netfilter-x_tables-deal-with-bogus-nextoffset-values.patch | |
parent | bf1d35cfe8b31cbac09a036ab36cd742b63031f1 (diff) | |
download | kernel-f339ce1dadf093ec63e24a19c01e75b821bb3974.tar.gz kernel-f339ce1dadf093ec63e24a19c01e75b821bb3974.tar.xz kernel-f339ce1dadf093ec63e24a19c01e75b821bb3974.zip |
Linux v4.7
Diffstat (limited to 'netfilter-x_tables-deal-with-bogus-nextoffset-values.patch')
-rw-r--r-- | netfilter-x_tables-deal-with-bogus-nextoffset-values.patch | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/netfilter-x_tables-deal-with-bogus-nextoffset-values.patch b/netfilter-x_tables-deal-with-bogus-nextoffset-values.patch new file mode 100644 index 000000000..e6f5fa6f5 --- /dev/null +++ b/netfilter-x_tables-deal-with-bogus-nextoffset-values.patch @@ -0,0 +1,109 @@ +From 2b32a7d82223d76ace432305b18c5816cadff878 Mon Sep 17 00:00:00 2001 +From: Florian Westphal <fw () strlen ! de> +Date: Thu, 10 Mar 2016 00:56:02 -0800 +Subject: [PATCH] netfilter: x_tables: deal with bogus nextoffset values + +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 | 8 ++++++++ + net/ipv4/netfilter/ip_tables.c | 8 ++++++++ + net/ipv6/netfilter/ip6_tables.c | 6 ++++++ + 3 files changed, 22 insertions(+) + +diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c +index 2033f92..a9b6c76 100644 +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -376,6 +376,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); + if (pos + size >= newinfo->size) +@@ -399,6 +403,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + if (newpos >= newinfo->size) + return 0; + } ++ ++ 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 54906e0..7530ecd 100644 +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -447,6 +447,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); + if (pos + size >= newinfo->size) +@@ -470,6 +474,10 @@ mark_source_chains(const struct xt_table_info *newinfo, + if (newpos >= newinfo->size) + return 0; + } ++ ++ 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 63e06c3..894da69 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -474,6 +474,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); + if (pos + size >= newinfo->size) +@@ -497,6 +499,10 @@ mark_source_chains(const struct xt_table_info *newinfo, + if (newpos >= newinfo->size) + return 0; + } ++ ++ if (newpos > newinfo->size - sizeof(*e)) ++ return 0; ++ + e = (struct ip6t_entry *) + (entry0 + newpos); + e->counters.pcnt = pos; +-- +2.5.5 + |