From: Greg Kroah-Hartman Date: Wed, 22 Jun 2016 21:18:43 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.14.73~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cecea5dcc234e7922854b382ec4dce6dd041bac1;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: netfilter-x_tables-don-t-move-to-non-existent-next-rule.patch netfilter-x_tables-validate-targets-of-jumps.patch --- diff --git a/queue-3.14/netfilter-x_tables-don-t-move-to-non-existent-next-rule.patch b/queue-3.14/netfilter-x_tables-don-t-move-to-non-existent-next-rule.patch new file mode 100644 index 00000000000..d19e00f2e44 --- /dev/null +++ b/queue-3.14/netfilter-x_tables-don-t-move-to-non-existent-next-rule.patch @@ -0,0 +1,106 @@ +From f24e230d257af1ad7476c6e81a8dc3127a74204e Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 1 Apr 2016 14:17:21 +0200 +Subject: netfilter: x_tables: don't move to non-existent next rule + +From: Florian Westphal + +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. + +Reported-by: Ben Hawkes +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + 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(-) + +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -435,6 +435,8 @@ static int mark_source_chains(const stru + 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 { +@@ -457,6 +459,8 @@ static int mark_source_chains(const stru + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct arpt_entry *) + (entry0 + newpos); +@@ -681,10 +685,8 @@ static int translate_table(struct xt_tab + } + } + +- 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; +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -516,6 +516,8 @@ mark_source_chains(const struct xt_table + 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 { +@@ -537,6 +539,8 @@ mark_source_chains(const struct xt_table + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ipt_entry *) + (entry0 + newpos); +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -526,6 +526,8 @@ mark_source_chains(const struct xt_table + 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 { +@@ -547,6 +549,8 @@ mark_source_chains(const struct xt_table + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ip6t_entry *) + (entry0 + newpos); diff --git a/queue-3.14/netfilter-x_tables-validate-targets-of-jumps.patch b/queue-3.14/netfilter-x_tables-validate-targets-of-jumps.patch new file mode 100644 index 00000000000..384b84d648f --- /dev/null +++ b/queue-3.14/netfilter-x_tables-validate-targets-of-jumps.patch @@ -0,0 +1,133 @@ +From 36472341017529e2b12573093cc0f68719300997 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 1 Apr 2016 14:17:22 +0200 +Subject: netfilter: x_tables: validate targets of jumps + +From: Florian Westphal + +commit 36472341017529e2b12573093cc0f68719300997 upstream. + +When we see a jump also check that the offset gets us to beginning of +a rule (an ipt_entry). + +The extra overhead is negible, even with absurd cases. + +300k custom rules, 300k jumps to 'next' user chain: +[ plus one jump from INPUT to first userchain ]: + +Before: +real 0m24.874s +user 0m7.532s +sys 0m16.076s + +After: +real 0m27.464s +user 0m7.436s +sys 0m18.840s + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + net/ipv4/netfilter/arp_tables.c | 16 ++++++++++++++++ + net/ipv4/netfilter/ip_tables.c | 16 ++++++++++++++++ + net/ipv6/netfilter/ip6_tables.c | 16 ++++++++++++++++ + 3 files changed, 48 insertions(+) + +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -363,6 +363,18 @@ static inline bool unconditional(const s + memcmp(&e->arp, &uncond, sizeof(uncond)) == 0; + } + ++static bool find_jump_target(const struct xt_table_info *t, ++ const struct arpt_entry *target) ++{ ++ struct arpt_entry *iter; ++ ++ xt_entry_foreach(iter, t->entries, t->size) { ++ if (iter == target) ++ return true; ++ } ++ return false; ++} ++ + /* Figures out from what hook each rule can be called: returns 0 if + * there are loops. Puts hook bitmask in comefrom. + */ +@@ -456,6 +468,10 @@ static int mark_source_chains(const stru + /* This a jump; chase it. */ + duprintf("Jump rule %u -> %u\n", + pos, newpos); ++ e = (struct arpt_entry *) ++ (entry0 + newpos); ++ if (!find_jump_target(newinfo, e)) ++ return 0; + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -439,6 +439,18 @@ ipt_do_table(struct sk_buff *skb, + #endif + } + ++static bool find_jump_target(const struct xt_table_info *t, ++ const struct ipt_entry *target) ++{ ++ struct ipt_entry *iter; ++ ++ xt_entry_foreach(iter, t->entries, t->size) { ++ if (iter == target) ++ return true; ++ } ++ return false; ++} ++ + /* Figures out from what hook each rule can be called: returns 0 if + there are loops. Puts hook bitmask in comefrom. */ + static int +@@ -536,6 +548,10 @@ mark_source_chains(const struct xt_table + /* This a jump; chase it. */ + duprintf("Jump rule %u -> %u\n", + pos, newpos); ++ e = (struct ipt_entry *) ++ (entry0 + newpos); ++ if (!find_jump_target(newinfo, e)) ++ return 0; + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -449,6 +449,18 @@ ip6t_do_table(struct sk_buff *skb, + #endif + } + ++static bool find_jump_target(const struct xt_table_info *t, ++ const struct ip6t_entry *target) ++{ ++ struct ip6t_entry *iter; ++ ++ xt_entry_foreach(iter, t->entries, t->size) { ++ if (iter == target) ++ return true; ++ } ++ return false; ++} ++ + /* Figures out from what hook each rule can be called: returns 0 if + there are loops. Puts hook bitmask in comefrom. */ + static int +@@ -546,6 +558,10 @@ mark_source_chains(const struct xt_table + /* This a jump; chase it. */ + duprintf("Jump rule %u -> %u\n", + pos, newpos); ++ e = (struct ip6t_entry *) ++ (entry0 + newpos); ++ if (!find_jump_target(newinfo, e)) ++ return 0; + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; diff --git a/queue-3.14/series b/queue-3.14/series index a8fd38cb0bd..39d568b00e6 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -16,3 +16,5 @@ netfilter-x_tables-make-sure-e-next_offset-covers-remaining-blob-size.patch netfilter-x_tables-fix-unconditional-helper.patch xfs-fix-up-backport-error-in-fs-xfs-xfs_inode.c.patch pipe-limit-the-per-user-amount-of-pages-allocated-in-pipes.patch +netfilter-x_tables-don-t-move-to-non-existent-next-rule.patch +netfilter-x_tables-validate-targets-of-jumps.patch