From 429da4c0b1e59837ec946cdf0f04eb1899586923 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Wed, 2 Jan 2013 05:24:40 +0000 Subject: [PATCH 1/3] netfilter: ip6t_NPT: fix IPv6 NTP checksum calculation csum16_add() has a broken carry detection, should be: sum += sum < (__force u16)b; Instead of fixing csum16_add, remove the custom checksum functions and use the generic csum_add/csum_sub ones. Signed-off-by: Ulrich Weber Acked-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/ip6t_NPT.c | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index e9486915eff6..7302b0b7b642 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c @@ -14,42 +14,23 @@ #include #include -static __sum16 csum16_complement(__sum16 a) -{ - return (__force __sum16)(0xffff - (__force u16)a); -} - -static __sum16 csum16_add(__sum16 a, __sum16 b) -{ - u16 sum; - - sum = (__force u16)a + (__force u16)b; - sum += (__force u16)a < (__force u16)b; - return (__force __sum16)sum; -} - -static __sum16 csum16_sub(__sum16 a, __sum16 b) -{ - return csum16_add(a, csum16_complement(b)); -} - static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) { struct ip6t_npt_tginfo *npt = par->targinfo; - __sum16 src_sum = 0, dst_sum = 0; + __wsum src_sum = 0, dst_sum = 0; unsigned int i; if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64) return -EINVAL; for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) { - src_sum = csum16_add(src_sum, - (__force __sum16)npt->src_pfx.in6.s6_addr16[i]); - dst_sum = csum16_add(dst_sum, - (__force __sum16)npt->dst_pfx.in6.s6_addr16[i]); + src_sum = csum_add(src_sum, + (__force __wsum)npt->src_pfx.in6.s6_addr16[i]); + dst_sum = csum_add(dst_sum, + (__force __wsum)npt->dst_pfx.in6.s6_addr16[i]); } - npt->adjustment = csum16_sub(src_sum, dst_sum); + npt->adjustment = (__force __sum16) csum_sub(src_sum, dst_sum); return 0; } @@ -85,7 +66,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt, return false; } - sum = csum16_add((__force __sum16)addr->s6_addr16[idx], + sum = (__force __sum16) csum_add((__force __wsum)addr->s6_addr16[idx], npt->adjustment); if (sum == CSUM_MANGLED_0) sum = 0; From 757ae316fb35811cfd8c67de0e0b8680ec4c1f37 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 2 Jan 2013 16:30:01 +0000 Subject: [PATCH 2/3] netfilter: fix missing dependencies for the NOTRACK target warning: (NETFILTER_XT_TARGET_NOTRACK) selects NETFILTER_XT_TARGET_CT which has unmet direct +dependencies (NET && INET && NETFILTER && NETFILTER_XTABLES && NF_CONNTRACK && (IP_NF_RAW || +IP6_NF_RAW) && NETFILTER_ADVANCED) Reported-by: Randy Dunlap Reported-by: kbuild test robot Acked-by: Randy Dunlap Signed-off-by: Pablo Neira Ayuso --- net/netfilter/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 390f96cc8ed4..49e96df5fbc4 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -682,6 +682,9 @@ config NETFILTER_XT_TARGET_NFQUEUE config NETFILTER_XT_TARGET_NOTRACK tristate '"NOTRACK" target support (DEPRECATED)' + depends on NF_CONNTRACK + depends on IP_NF_RAW || IP6_NF_RAW + depends on NETFILTER_ADVANCED select NETFILTER_XT_TARGET_CT config NETFILTER_XT_TARGET_RATEEST From 2727de76041b2064c0b74f00a2a89678fb3efafc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 3 Jan 2013 22:18:39 +0000 Subject: [PATCH 3/3] netfilter: xt_recent: avoid high order page allocations xt_recent can try high order page allocations and this can fail. iptables: page allocation failure: order:9, mode:0xc0d0 It also wastes about half the allocated space because of kmalloc() power-of-two roundups and struct recent_table layout. Use vmalloc() instead to save space and be less prone to allocation errors when memory is fragmented. Reported-by: Miroslav Kratochvil Reported-by: Dave Jones Reported-by: Harald Reindl Signed-off-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_recent.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index dab053e2a1a2..978efc9b555a 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -310,6 +311,14 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par) return ret; } +static void recent_table_free(void *addr) +{ + if (is_vmalloc_addr(addr)) + vfree(addr); + else + kfree(addr); +} + static int recent_mt_check(const struct xt_mtchk_param *par, const struct xt_recent_mtinfo_v1 *info) { @@ -322,6 +331,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par, #endif unsigned int i; int ret = -EINVAL; + size_t sz; if (unlikely(!hash_rnd_inited)) { get_random_bytes(&hash_rnd, sizeof(hash_rnd)); @@ -360,8 +370,11 @@ static int recent_mt_check(const struct xt_mtchk_param *par, goto out; } - t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size, - GFP_KERNEL); + sz = sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size; + if (sz <= PAGE_SIZE) + t = kzalloc(sz, GFP_KERNEL); + else + t = vzalloc(sz); if (t == NULL) { ret = -ENOMEM; goto out; @@ -377,14 +390,14 @@ static int recent_mt_check(const struct xt_mtchk_param *par, uid = make_kuid(&init_user_ns, ip_list_uid); gid = make_kgid(&init_user_ns, ip_list_gid); if (!uid_valid(uid) || !gid_valid(gid)) { - kfree(t); + recent_table_free(t); ret = -EINVAL; goto out; } pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, &recent_mt_fops, t); if (pde == NULL) { - kfree(t); + recent_table_free(t); ret = -ENOMEM; goto out; } @@ -435,7 +448,7 @@ static void recent_mt_destroy(const struct xt_mtdtor_param *par) remove_proc_entry(t->name, recent_net->xt_recent); #endif recent_table_flush(t); - kfree(t); + recent_table_free(t); } mutex_unlock(&recent_mutex); }