From: Florian Westphal Date: Wed, 1 Jun 2016 00:04:44 +0000 (+0200) Subject: netfilter: x_tables: don't reject valid target size on some architectures X-Git-Tag: v4.1.12-92~70^2~9 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7e5e9c3ed3e872fb0785e8b043fa359c72b220dd;p=users%2Fjedix%2Flinux-maple.git netfilter: x_tables: don't reject valid target size on some architectures Orabug: 24690280 CVE: CVE-2016-3134 [ Upstream commit 7b7eba0f3515fca3296b8881d583f7c1042f5226 ] Quoting John Stultz: In updating a 32bit arm device from 4.6 to Linus' current HEAD, I noticed I was having some trouble with networking, and realized that /proc/net/ip_tables_names was suddenly empty. Digging through the registration process, it seems we're catching on the: if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && target_offset + sizeof(struct xt_standard_target) != next_offset) return -EINVAL; Where next_offset seems to be 4 bytes larger then the offset + standard_target struct size. next_offset needs to be aligned via XT_ALIGN (so we can access all members of ip(6)t_entry struct). This problem didn't show up on i686 as it only needs 4-byte alignment for u64, but iptables userspace on other 32bit arches does insert extra padding. Reported-by: John Stultz Tested-by: John Stultz Fixes: 7ed2abddd20cf ("netfilter: x_tables: check standard target size too") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin (cherry picked from commit d97246b5d16b77b57d835b6b4d1bde8ea6566b46) Signed-off-by: Brian Maly --- diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 239d71bba8de..7ad7e6038af0 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -611,7 +611,7 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems, return -EINVAL; if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && - target_offset + sizeof(struct compat_xt_standard_target) != next_offset) + COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset) return -EINVAL; /* compat_xt_entry match has less strict aligment requirements, @@ -693,7 +693,7 @@ int xt_check_entry_offsets(const void *base, return -EINVAL; if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && - target_offset + sizeof(struct xt_standard_target) != next_offset) + XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset) return -EINVAL; return xt_check_entry_match(elems, base + target_offset,